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

Simplify the structure of CircuitSimulator #225

Open
wants to merge 17 commits into
base: master
Choose a base branch
from

Conversation

BoxiLi
Copy link
Member

@BoxiLi BoxiLi commented Dec 10, 2023

Refactor the gate level CircuitSimulator

  • Avoid expanding all propagators and then applying them one by one. Only expand when applying the unitary. This saves memory and also make it easier for further improvement, i.e., exploring other ways to perform the matrix multiplication (e.g. einsum).
  • Switch some public members to private. Those members that track the execution of the circuit evaluation should not be public.
  • Small changes to improve the clarity.

Only expand the propagators when it is applied to the states.
- Remove it from the input parameters, it makes little sense to provide them to the circuit and then do the simulation. If the unitaries are known. it can be trivally multiplied.
- Remove U_list from the properties of CircuitSimulator. It is generated during the process and the dimensions of the unitaries are not determined. It should not be exposed to the the user.
- The method `_process_ops` was executed during the construction, which could be expensive. This is moved to the first execution of the circuit.
- Remove some global members from the class to increase the clearity.
The parameters that will be updated during the circuit simulation are changed to private.
Move all the calculation related to unitary-state multiplication to _evolve_state.
Provide qeye as the input states.
This option computes the full unitary of all the gates, and caches it. It is beneficial if the circuit has a small number of qubits but a very large depth. This is a rare use case.

At the same time, this feature makes the migration to the new efficient circuit evaluation very hard. If the unitary for the circuit is desired, one can just call QubitCircuit.compute_unitary to get the circuit and then apply it to different states.
Use np.einsum to apply the gate matrix directly on the state vector, instead of expanding it first to the full dimension.
- The private member self._state will remain a numpy array during the sequential application of gates.
- If a measurement occurs, the state has to be transformed to a Qobj.
- Returning the state after each step is removed as it inevitably creates Qobj and creates a copy in v4.
@BoxiLi
Copy link
Member Author

BoxiLi commented Dec 18, 2023

Remove the support of precompute_unitary
This option computes the full unitary of all the gates and caches it. It is beneficial if the circuit has a small number of qubits but a very long depth. This feature makes the migration to the new efficient circuit evaluation very hard because the input gates are Qobjs and not gates. If the unitary for the circuit is desired, one can just call QubitCircuit.compute_unitary to get the circuit unitary and then apply it to different states.

Use np.einsum for gate-state multiplication
Use np.einsum to apply the gate matrix directly on the state vector, instead of expanding it first to the full dimension.

  • The private member self._state will remain a numpy array during the sequential application of gates.
  • If a measurement occurs, the state has to be transformed to a Qobj.
  • Returning the state after each step is removed as it inevitably creates Qobj and creates a copy in v4.

Some benchmarking for the circuit simulator after the improvement, with qutip==4.7.3 or qutip==5.0.0a2, using qutip_qip.algorithems.qft:
Note that the circuit simulator in the old version is very inefficient with v5 because qc.propagators() return a list of dense matrix! This needs to be deprecated (or fixed) in a different PR.
image

@BoxiLi BoxiLi added this to the qutip-qip-0.4.0 milestone Dec 18, 2023
Copy link
Contributor

@hodgestar hodgestar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we also add tests (or maybe just parameterize some existing ones) for both the einsum and non-einsum modes?

src/qutip_qip/circuit/circuitsimulator.py Outdated Show resolved Hide resolved
src/qutip_qip/circuit/circuitsimulator.py Outdated Show resolved Hide resolved
src/qutip_qip/circuit/circuitsimulator.py Outdated Show resolved Hide resolved
src/qutip_qip/circuit/circuitsimulator.py Outdated Show resolved Hide resolved
src/qutip_qip/circuit/circuitsimulator.py Outdated Show resolved Hide resolved
for j, k in enumerate(targets_indices):
new_index_list[k] = j + num_site
state = np.einsum(
gate_array,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question for the future -- could one in theory provide multiple gates at once here? Would that potentially be better / faster? Possibly with or without use of np.einsum_path to select an optimal contraction path?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that could be faster if those gates are mostly local. Then it is not that easy to decide unless one first builds the directed graph of the circuit, because gates can be commuting. So instead of this, we should rather try to get tensor network to work and let it does the heavy lifting.

@BoxiLi
Copy link
Member Author

BoxiLi commented Apr 3, 2024

Could we also add tests (or maybe just parameterize some existing ones) for both the einsum and non-einsum modes?

@simon there is no non-einsum mode anymore. There is no need to keep that option. Measurement is not yet compatible with einsum, so in that case it just fails back to normal Qobj.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants