I am trying to transpile a circuit with CCU and CU gates with different rotation angles. In the qiskit 11.4 version the transpiler was able to optimize and transpile the circuit with the basis gate set ['sx','cz','x','rz','barrier', 'save_statevector', 'delay'], But for the current version of qiskit, the transpiler throws an error for the particular gate set.
SympifyError: sympy2symengine: Cannot convert 'None' (of type <class 'NoneType'>) to a symengine type.
from qiskit_aer import AerSimulator
from qiskit import transpile, QuantumCircuit
from qiskit.circuit.library import UGate
from qiskit.circuit.add_control import add_control
qc = QuantumCircuit(4)
qca_U = add_control(UGate(-1.945632646294958, 1.5120405041931422, 2.4393357222229826),num_ctrl_qubits=2, ctrl_state='00', label = 'qca_u')
qca_U_red = add_control(UGate(-1.945632646294958, 1.5120405041931422, 2.4393357222229826),num_ctrl_qubits=1, ctrl_state='0', label = 'qca_u_red')
qc.append(qca_U, [0,2,1])
qc.append(qca_U_red, [0,1])
sim = AerSimulator()
# qcd = transpile(qc, sim, optimization_level=3,basis_gates=['ccx','ccz','cu','cx','u','mcphase','x', 'cx', 'save_statevector','delay', 'barrier'])
qcd = transpile(qc, sim, optimization_level=3, basis_gates=['barrier', 'save_statevector', 'delay','sx','cz','x','rz'])
# qcd = transpile(qc, sim, optimization_level=3)
{
"name": "SympifyError",
"message": "sympy2symengine: Cannot convert 'None' (of type <class 'NoneType'>) to a symengine type.",
"stack": "---------------------------------------------------------------------------
SympifyError Traceback (most recent call last)
Cell In[23], line 13
11 sim = AerSimulator()
12 # qcd = transpile(qc, sim, optimization_level=3,basis_gates=['ccx','ccz','cu','cx','u','mcphase','x', 'cx', 'save_statevector','delay', 'barrier'])
---> 13 qcd = transpile(qc, sim, optimization_level=3, basis_gates=['barrier', 'save_statevector', 'delay','sx','cz','x','rz'])
14 # qcd = transpile(qc, sim, optimization_level=3)
File ~/anaconda3/envs/qca/lib/python3.11/site-packages/qiskit/compiler/transpiler.py:391, in transpile(circuits, backend, basis_gates, inst_map, coupling_map, backend_properties, initial_layout, layout_method, routing_method, translation_method, scheduling_method, instruction_durations, dt, approximation_degree, timing_constraints, seed_transpiler, optimization_level, callback, output_name, unitary_synthesis_method, unitary_synthesis_plugin_config, target, hls_config, init_method, optimization_method, ignore_backend_supplied_default_methods, num_processes)
363 # Edge cases require using the old model (loose constraints) instead of building a target,
364 # but we don't populate the passmanager config with loose constraints unless it's one of
365 # the known edge cases to control the execution path.
366 pm = generate_preset_pass_manager(
367 optimization_level,
368 target=target,
(...)
388 dt=dt,
389 )
--> 391 out_circuits = pm.run(circuits, callback=callback, num_processes=num_processes)
393 for name, circ in zip(output_name, out_circuits):
394 circ.name = name
File ~/anaconda3/envs/qca/lib/python3.11/site-packages/qiskit/transpiler/passmanager.py:441, in StagedPassManager.run(self, circuits, output_name, callback, num_processes)
433 def run(
434 self,
435 circuits: _CircuitsT,
(...)
438 num_processes: int = None,
439 ) -> _CircuitsT:
440 self._update_passmanager()
--> 441 return super().run(circuits, output_name, callback, num_processes=num_processes)
File ~/anaconda3/envs/qca/lib/python3.11/site-packages/qiskit/transpiler/passmanager.py:464, in _replace_error.<locals>.wrapper(*meth_args, **meth_kwargs)
461 @wraps(meth)
462 def wrapper(*meth_args, **meth_kwargs):
463 try:
--> 464 return meth(*meth_args, **meth_kwargs)
465 except PassManagerError as ex:
466 raise TranspilerError(ex.message) from ex
File ~/anaconda3/envs/qca/lib/python3.11/site-packages/qiskit/transpiler/passmanager.py:226, in PassManager.run(self, circuits, output_name, callback, num_processes)
223 if callback is not None:
224 callback = _legacy_style_callback(callback)
--> 226 return super().run(
227 in_programs=circuits,
228 callback=callback,
229 output_name=output_name,
230 num_processes=num_processes,
231 )
File ~/anaconda3/envs/qca/lib/python3.11/site-packages/qiskit/passmanager/passmanager.py:231, in BasePassManager.run(self, in_programs, callback, num_processes, **kwargs)
228 # If we're not going to run in parallel, we want to avoid spending time `dill` serializing
229 # ourselves, since that can be quite expensive.
230 if len(in_programs) == 1 or not should_run_in_parallel(num_processes):
--> 231 out = [
232 _run_workflow(program=program, pass_manager=self, callback=callback, **kwargs)
233 for program in in_programs
234 ]
235 if len(in_programs) == 1 and not is_list:
236 return out[0]
File ~/anaconda3/envs/qca/lib/python3.11/site-packages/qiskit/passmanager/passmanager.py:232, in <listcomp>(.0)
228 # If we're not going to run in parallel, we want to avoid spending time `dill` serializing
229 # ourselves, since that can be quite expensive.
230 if len(in_programs) == 1 or not should_run_in_parallel(num_processes):
231 out = [
--> 232 _run_workflow(program=program, pass_manager=self, callback=callback, **kwargs)
233 for program in in_programs
234 ]
235 if len(in_programs) == 1 and not is_list:
236 return out[0]
File ~/anaconda3/envs/qca/lib/python3.11/site-packages/qiskit/passmanager/passmanager.py:292, in _run_workflow(program, pass_manager, **kwargs)
286 initial_status = WorkflowStatus()
288 passmanager_ir = pass_manager._passmanager_frontend(
289 input_program=program,
290 **kwargs,
291 )
--> 292 passmanager_ir, final_state = flow_controller.execute(
293 passmanager_ir=passmanager_ir,
294 state=PassManagerState(
295 workflow_status=initial_status,
296 property_set=PropertySet(),
297 ),
298 callback=kwargs.get(\"callback\", None),
299 )
300 # The `property_set` has historically been returned as a mutable attribute on `PassManager`
301 # This makes us non-reentrant (though `PassManager` would be dependent on its internal tasks to
302 # be re-entrant if that was required), but is consistent with previous interfaces. We're still
303 # safe to be called in a serial loop, again assuming internal tasks are re-runnable. The
304 # conversion to the backend language is also allowed to use the property set, so it must be set
305 # before calling it.
306 pass_manager.property_set = final_state.property_set
File ~/anaconda3/envs/qca/lib/python3.11/site-packages/qiskit/passmanager/base_tasks.py:218, in BaseController.execute(self, passmanager_ir, state, callback)
216 return passmanager_ir, state
217 while True:
--> 218 passmanager_ir, state = next_task.execute(
219 passmanager_ir=passmanager_ir,
220 state=state,
221 callback=callback,
222 )
223 try:
224 # Sending the object through the generator implies the custom controllers
225 # can always rely on the latest data to choose the next task to run.
226 next_task = task_generator.send(state)
File ~/anaconda3/envs/qca/lib/python3.11/site-packages/qiskit/transpiler/basepasses.py:195, in TransformationPass.execute(self, passmanager_ir, state, callback)
189 def execute(
190 self,
191 passmanager_ir: PassManagerIR,
192 state: PassManagerState,
193 callback: Callable = None,
194 ) -> tuple[PassManagerIR, PassManagerState]:
--> 195 new_dag, state = super().execute(
196 passmanager_ir=passmanager_ir,
197 state=state,
198 callback=callback,
199 )
201 if state.workflow_status.previous_run == RunState.SUCCESS:
202 if isinstance(new_dag, DAGCircuit):
203 # Copy calibration data from the original program
File ~/anaconda3/envs/qca/lib/python3.11/site-packages/qiskit/passmanager/base_tasks.py:98, in GenericPass.execute(self, passmanager_ir, state, callback)
96 try:
97 if self not in state.workflow_status.completed_passes:
---> 98 ret = self.run(passmanager_ir)
99 run_state = RunState.SUCCESS
100 else:
File ~/anaconda3/envs/qca/lib/python3.11/site-packages/qiskit/transpiler/passes/basis/basis_translator.py:237, in BasisTranslator.run(self, dag)
234 # Compose found path into a set of instruction substitution rules.
236 compose_start_time = time.time()
--> 237 instr_map = _compose_transforms(basis_transforms, source_basis, dag)
238 extra_instr_map = {
239 qarg: _compose_transforms(transforms, qargs_local_source_basis[qarg], dag)
240 for qarg, transforms in qarg_local_basis_transforms.items()
241 }
243 compose_end_time = time.time()
File ~/anaconda3/envs/qca/lib/python3.11/site-packages/qiskit/transpiler/passes/basis/basis_translator.py:669, in _compose_transforms(basis_transforms, source_basis, source_dag)
660 logger.debug(
661 \"Updating transform for mapped instr %s %s from \
%s\",
662 mapped_instr_name,
663 dag_params,
664 dag_to_circuit(dag, copy_operations=False),
665 )
667 for node in doomed_nodes:
--> 669 replacement = equiv.assign_parameters(dict(zip_longest(equiv_params, node.params)))
671 replacement_dag = circuit_to_dag(replacement)
673 dag.substitute_node_with_dag(node, replacement_dag)
File ~/anaconda3/envs/qca/lib/python3.11/site-packages/qiskit/circuit/quantumcircuit.py:4342, in QuantumCircuit.assign_parameters(self, parameters, inplace, flat_input, strict)
4337 raise CircuitError(
4338 f\"Cannot bind parameters ({', '.join(str(x) for x in extras)}) not present in\"
4339 \" the circuit.\"
4340 )
4341 parameter_binds = _ParameterBindsDict(raw_mapping, our_parameters)
-> 4342 target._data.assign_parameters_mapping(parameter_binds)
4343 else:
4344 parameter_binds = _ParameterBindsSequence(target._data.parameters, parameters)
File ~/anaconda3/envs/qca/lib/python3.11/site-packages/qiskit/circuit/parameter.py:103, in Parameter.assign(self, parameter, value)
100 return value
101 # This is the `super().bind` case, where we're required to return a `ParameterExpression`,
102 # so we need to lift the given value to a symbolic expression.
--> 103 return ParameterExpression({}, symengine.sympify(value))
File symengine_wrapper.pyx:534, in symengine.lib.symengine_wrapper.sympify()
File symengine_wrapper.pyx:579, in symengine.lib.symengine_wrapper._sympify()
File symengine_wrapper.pyx:500, in symengine.lib.symengine_wrapper.sympy2symengine()
SympifyError: sympy2symengine: Cannot convert 'None' (of type <class 'NoneType'>) to a symengine type."
}
Noticed this when there is a CU gate in the circuit (It works well when there are CCU gates). Also for the basis gate set ['ccx','ccz','cu','cx','u','mcphase','x', 'cx', 'save_statevector','delay', 'barrier'] it transpiles properly
Environment
What is happening?
I am trying to transpile a circuit with CCU and CU gates with different rotation angles. In the qiskit 11.4 version the transpiler was able to optimize and transpile the circuit with the basis gate set ['sx','cz','x','rz','barrier', 'save_statevector', 'delay'], But for the current version of qiskit, the transpiler throws an error for the particular gate set.
SympifyError: sympy2symengine: Cannot convert 'None' (of type <class 'NoneType'>) to a symengine type.
How can we reproduce the issue?
What should happen?
Any suggestions?
Noticed this when there is a CU gate in the circuit (It works well when there are CCU gates). Also for the basis gate set ['ccx','ccz','cu','cx','u','mcphase','x', 'cx', 'save_statevector','delay', 'barrier'] it transpiles properly