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

Passmanager fails to transpile a basic StatePreparation gate #12984

Closed
mmlouamri opened this issue Aug 19, 2024 · 1 comment · Fixed by #12988
Closed

Passmanager fails to transpile a basic StatePreparation gate #12984

mmlouamri opened this issue Aug 19, 2024 · 1 comment · Fixed by #12988
Labels
bug Something isn't working

Comments

@mmlouamri
Copy link

Environment

  • Qiskit version: 1.2.0
  • Python version: 3.12
  • Operating system: Ubuntu 24.04

What is happening?

I am trying to execute the following circuit:

from qiskit import QuantumCircuit, __version__ as qversion
from qiskit.circuit.library import StatePreparation
from qiskit_aer import AerSimulator, __version__ as qaversion
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager

print(qversion, '/', qaversion) # 1.2.0 / 0.14.2

pm = generate_preset_pass_manager(backend=AerSimulator(), optimization_level=3)

qc =  QuantumCircuit(1)
qc.compose(StatePreparation([1, 1], normalize=True), range(1), inplace=True)

pm.run(qc)

And I am getting the following error:

---------------------------------------------------------------------------
QiskitError                               Traceback (most recent call last)
Cell In[21], line 13
     10 qc =  QuantumCircuit(1)
     11 qc.compose(StatePreparation([1, 1], normalize=True), range(1), inplace=True)
---> 13 pm.run(qc)

File ~/anaconda3/envs/building-agi/lib/python3.12/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/building-agi/lib/python3.12/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/building-agi/lib/python3.12/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/building-agi/lib/python3.12/site-packages/qiskit/passmanager/passmanager.py:232, 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/building-agi/lib/python3.12/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/building-agi/lib/python3.12/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/building-agi/lib/python3.12/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/building-agi/lib/python3.12/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/building-agi/lib/python3.12/site-packages/qiskit/transpiler/passes/synthesis/high_level_synthesis.py:443, in HighLevelSynthesis.run(self, dag)
    440 if self._definitely_skip_node(node, qubits):
    441     continue
--> 443 decomposition, modified = self._recursively_handle_op(node.op, qubits)
    445 if not modified:
    446     continue

File ~/anaconda3/envs/building-agi/lib/python3.12/site-packages/qiskit/transpiler/passes/synthesis/high_level_synthesis.py:551, in HighLevelSynthesis._recursively_handle_op(self, op, qubits)
    547         return op, False
    549 try:
    550     # extract definition
--> 551     definition = op.definition
    552 except TypeError as err:
    553     raise TranspilerError(
    554         f"HighLevelSynthesis was unable to extract definition for {op.name}: {err}"
    555     ) from err

File ~/anaconda3/envs/building-agi/lib/python3.12/site-packages/qiskit/circuit/instruction.py:312, in Instruction.definition(self)
    310 """Return definition in terms of other basic gates."""
    311 if self._definition is None:
--> 312     self._define()
    313 return self._definition

File ~/anaconda3/envs/building-agi/lib/python3.12/site-packages/qiskit/circuit/library/data_preparation/state_preparation.py:122, in StatePreparation._define(self)
    120     self.definition = self._define_from_int()
    121 else:
--> 122     self.definition = self._define_synthesis_isom()

File ~/anaconda3/envs/building-agi/lib/python3.12/site-packages/qiskit/circuit/library/data_preparation/state_preparation.py:176, in StatePreparation._define_synthesis_isom(self)
    173 q = QuantumRegister(self.num_qubits, "q")
    174 initialize_circuit = QuantumCircuit(q, name="init_def")
--> 176 isom = Isometry(self._params_arg, 0, 0)
    177 initialize_circuit.append(isom, q[:])
    179 # invert the circuit to create the desired vector from zero (assuming
    180 # the qubits are in the zero state)

File ~/anaconda3/envs/building-agi/lib/python3.12/site-packages/qiskit/circuit/library/generalized_gates/isometry.py:112, in Isometry.__init__(self, isometry, num_ancillas_zero, num_ancillas_dirty, epsilon)
    108     raise QiskitError(
    109         "The input matrix has more columns than rows and hence it can't be an isometry."
    110     )
    111 if not is_isometry(isometry, self._epsilon):
--> 112     raise QiskitError(
    113         "The input matrix has non orthonormal columns and hence it is not an isometry."
    114     )
    116 num_qubits = int(n) + num_ancillas_zero + num_ancillas_dirty
    118 super().__init__("isometry", num_qubits, 0, [isometry])

QiskitError: 'The input matrix has non orthonormal columns and hence it is not an isometry.'

As far as I remember, similar code used to work on previous versions of Qiskit.

How can we reproduce the issue?

Here is a minimal code snippet to reproduce the error:

from qiskit import QuantumCircuit, __version__ as qversion
from qiskit.circuit.library import StatePreparation
from qiskit_aer import AerSimulator, __version__ as qaversion
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager

print(qversion, '/', qaversion) # 1.2.0 / 0.14.2

pm = generate_preset_pass_manager(backend=AerSimulator(), optimization_level=3)

qc =  QuantumCircuit(1)
qc.compose(StatePreparation([1, 1], normalize=True), range(1), inplace=True)

pm.run(qc)

What should happen?

The transpilation of the StatePreparation gate :)

Any suggestions?

No response

@mmlouamri mmlouamri added the bug Something isn't working label Aug 19, 2024
@Cryoris
Copy link
Contributor

Cryoris commented Aug 19, 2024

That's indeed a bug -- the StatePreparation code passes the unnormalized vector to Isometry, even though normalize is set to True.

Edit: #12988 should fix it

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
Development

Successfully merging a pull request may close this issue.

2 participants