Repository: Qiskit/qiskit

Issue:
Make circuit.layout name descriptive
#2736 added a `QuantumCircuit.layout` property and sets it with the layout determined during transpile. With the current naming, it is ambiguous as to where this property is generated, and whether or not it is user set-able. (e.g. demo code #2781 sets `circuit.layout` but this would be ignored if that circuit was passed to `transpile`.)

We should add some documentation to the layout property, and consider making it read-only. We should also consider moving it to a location that better describes it's origin and purpose: e.g. `circuit.transpile_history.layout = { 'layout': Layout(...), 'source': 'DenseLayout'}`




Discussion:

Resolving patch:
diff --git a/qiskit/circuit/quantumcircuit.py b/qiskit/circuit/quantumcircuit.py
--- a/qiskit/circuit/quantumcircuit.py
+++ b/qiskit/circuit/quantumcircuit.py
@@ -99,7 +99,7 @@ def __init__(self, *regs, name=None):
         # Parameter table tracks instructions with variable parameters.
         self._parameter_table = ParameterTable()
 
-        self.layout = None
+        self._layout = None
 
     def __str__(self):
         return str(self.draw(output='text'))
diff --git a/qiskit/transpiler/passmanager.py b/qiskit/transpiler/passmanager.py
--- a/qiskit/transpiler/passmanager.py
+++ b/qiskit/transpiler/passmanager.py
@@ -172,7 +172,7 @@ def run(self, circuit):
 
         circuit = dag_to_circuit(dag)
         circuit.name = name
-        circuit.layout = self.property_set['layout']
+        circuit._layout = self.property_set['layout']
         return circuit
 
     def draw(self, filename, style=None, raw=False):
diff --git a/qiskit/visualization/gate_map.py b/qiskit/visualization/gate_map.py
--- a/qiskit/visualization/gate_map.py
+++ b/qiskit/visualization/gate_map.py
@@ -235,7 +235,7 @@ def plot_circuit_layout(circuit, backend, view='virtual'):
         QiskitError: Invalid view type given.
         VisualizationError: Circuit has no layout attribute.
     """
-    if circuit.layout is None:
+    if circuit._layout is None:
         raise QiskitError('Circuit has no layout. '
                           'Perhaps it has not been transpiled.')
 
@@ -246,14 +246,14 @@ def plot_circuit_layout(circuit, backend, view='virtual'):
 
     if view == 'virtual':
         idx = 0
-        for key, val in circuit.layout.get_virtual_bits().items():
+        for key, val in circuit._layout.get_virtual_bits().items():
             if key.register.name != 'ancilla':
                 qubits.append(val)
                 qubit_labels[val] = idx
             idx += 1
 
     elif view == 'physical':
-        for key, val in circuit.layout.get_physical_bits().items():
+        for key, val in circuit._layout.get_physical_bits().items():
             if val.register.name != 'ancilla':
                 qubits.append(key)
                 qubit_labels[key] = key


Test patch:
diff --git a/test/python/transpiler/test_preset_passmanagers.py b/test/python/transpiler/test_preset_passmanagers.py
--- a/test/python/transpiler/test_preset_passmanagers.py
+++ b/test/python/transpiler/test_preset_passmanagers.py
@@ -97,7 +97,7 @@ def test_layout_1711(self, level):
         qc_b = transpile(qc, backend, initial_layout=initial_layout, optimization_level=level)
         qobj = assemble(qc_b)
 
-        self.assertEqual(qc_b.layout._p2v, final_layout)
+        self.assertEqual(qc_b._layout._p2v, final_layout)
 
         compiled_ops = qobj.experiments[0].instructions
         for operation in compiled_ops:
@@ -127,7 +127,7 @@ def test_layout_2532(self, level):
 
         qc_b = transpile(qc, backend, initial_layout=initial_layout, optimization_level=level)
 
-        self.assertEqual(qc_b.layout._p2v, final_layout)
+        self.assertEqual(qc_b._layout._p2v, final_layout)
 
         for gate, qubits, _ in qc_b:
             if gate.name == 'cx':
@@ -163,7 +163,7 @@ def test_layout_2503(self, level):
 
         qc_b = transpile(qc, backend, initial_layout=initial_layout, optimization_level=level)
 
-        self.assertEqual(qc_b.layout._p2v, final_layout)
+        self.assertEqual(qc_b._layout._p2v, final_layout)
 
         gate_0, qubits_0, _ = qc_b[0]
         gate_1, qubits_1, _ = qc_b[1]