Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DAGCircuit.substitute_node_with_dag mutates input_dag if node has a condition #4727

Closed
kdk opened this issue Jul 16, 2020 · 0 comments · Fixed by #4734
Closed

DAGCircuit.substitute_node_with_dag mutates input_dag if node has a condition #4727

kdk opened this issue Jul 16, 2020 · 0 comments · Fixed by #4734
Labels
bug Something isn't working

Comments

@kdk
Copy link
Member

kdk commented Jul 16, 2020

Information

What is the current behavior?

From https://travis-ci.com/github/Qiskit/qiskit-terra/jobs/361028025#L6256 , DAGCircuit.substitute_node_with_dag(node, input_dag) will mutate input_dag to add the condition from node. This will lead to issues of input_dag is later re-used in a non-conditional context.

Steps to reproduce the problem

>>> import qiskit as qk
>>> qc = qk.QuantumCircuit(2,1)
>>> qc.cx(0,1).c_if(qc.cregs[0], 1)
>>> qc.cx(1,0)
>>> print(qc)
            ┌───┐
q_0: ───■───┤ X ├
      ┌─┴─┐ └─┬─┘
q_1: ─┤ X ├───■──
      └─┬─┘      
     ┌──┴──┐     
c: 1/╡ = 1 ╞═════
     └─────┘     
>>> qk.transpile(qc, basis_gates=['u3', 'cz'])

---------------------------------------------------------------------------
DAGCircuitError                           Traceback (most recent call last)
<ipython-input-2-ee46705662ef> in <module>
      4 
      5 
----> 6 qk.transpile(qc, basis_gates=['u3', 'cz']).draw()

~/q/qiskit-terra/qiskit/compiler/transpile.py in transpile(circuits, backend, basis_gates, coupling_map, backend_properties, initial_layout, layout_method, routing_method, translation_method, seed_transpiler, optimization_level, pass_manager, callback, output_name)
    217     # Transpile circuits in parallel
    218     circuits = parallel_map(_transpile_circuit, list(zip(circuits, transpile_args)),
--> 219                             task_args=(faulty_qubits_map, backend))
    220 
    221     if len(circuits) == 1:

~/q/qiskit-terra/qiskit/tools/parallel.py in parallel_map(task, values, task_args, task_kwargs, num_processes)
    106         return []
    107     if len(values) == 1:
--> 108         return [task(values[0], *task_args, **task_kwargs)]
    109 
    110     Publisher().publish("terra.parallel.start", len(values))

~/q/qiskit-terra/qiskit/compiler/transpile.py in _transpile_circuit(circuit_config_tuple, faulty_qubits_map, backend)
    320 
    321     result = pass_manager.run(circuit, callback=transpile_config['callback'],
--> 322                               output_name=transpile_config['output_name'])
    323 
    324     if faulty_qubits_map:

~/q/qiskit-terra/qiskit/transpiler/passmanager.py in run(self, circuits, output_name, callback)
    212         """
    213         if isinstance(circuits, QuantumCircuit):
--> 214             return self._run_single_circuit(circuits, output_name, callback)
    215         elif len(circuits) == 1:
    216             return self._run_single_circuit(circuits[0], output_name, callback)

~/q/qiskit-terra/qiskit/transpiler/passmanager.py in _run_single_circuit(self, circuit, output_name, callback)
    275         if callback is None and self.callback:  # TODO to remove with __init__(callback)
    276             callback = self.callback
--> 277         result = running_passmanager.run(circuit, output_name=output_name, callback=callback)
    278         self.property_set = running_passmanager.property_set
    279         return result

~/q/qiskit-terra/qiskit/transpiler/runningpassmanager.py in run(***failed resolving arguments***)
    113         for passset in self.working_list:
    114             for pass_ in passset:
--> 115                 dag = self._do_pass(pass_, dag, passset.options)
    116 
    117         circuit = dag_to_circuit(dag)

~/q/qiskit-terra/qiskit/transpiler/runningpassmanager.py in _do_pass(self, pass_, dag, options)
    143         # Run the pass itself, if not already run
    144         if pass_ not in self.valid_passes:
--> 145             dag = self._run_this_pass(pass_, dag)
    146 
    147             # update the valid_passes property

~/q/qiskit-terra/qiskit/transpiler/runningpassmanager.py in _run_this_pass(self, pass_, dag)
    155             # Measure time if we have a callback or logging set
    156             start_time = time()
--> 157             new_dag = pass_.run(dag)
    158             end_time = time()
    159             run_time = end_time - start_time

~/q/qiskit-terra/qiskit/transpiler/passes/basis/basis_translator.py in run(self, dag)
    153                     dag.substitute_node(node, bound_target_dag.op_nodes()[0].op, inplace=True)
    154                 else:
--> 155                     dag.substitute_node_with_dag(node, bound_target_dag)
    156             else:
    157                 raise TranspilerError('BasisTranslator did not map {}.'.format(node.name))

~/q/qiskit-terra/qiskit/dagcircuit/dagcircuit.py in substitute_node_with_dag(self, node, input_dag, wires)
    810             wires = input_dag.wires
    811 
--> 812         self._check_wires_list(wires, node)
    813 
    814         # Create a proxy wire_map to identify fragments and duplicates

~/q/qiskit-terra/qiskit/dagcircuit/dagcircuit.py in _check_wires_list(self, wires, node)
    686         if len(wires) != wire_tot:
    687             raise DAGCircuitError("expected %d wires, got %d"
--> 688                                   % (wire_tot, len(wires)))
    689 
    690     def _make_pred_succ_maps(self, node):

DAGCircuitError: 'expected 2 wires, got 3'

What is the expected behavior?

Suggested solutions

Around https://github.com/Qiskit/qiskit-terra/blob/700beea/qiskit/dagcircuit/dagcircuit.py#L796 , we should make a copy of input_dag if it needs to be modified prior to insertion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
1 participant