mindquantum.simulator.Simulator

View Source On Gitee
class mindquantum.simulator.Simulator(backend, n_qubits=None, *args, seed=None, dtype=None, **kwargs)[source]

Quantum simulator that simulate quantum circuit.

Parameters
  • backend (str) – which backend you want. The supported backend can be found in SUPPORTED_SIMULATOR

  • n_qubits (int) – number of quantum simulator. Default: None.

  • seed (int) – the random seed for this simulator, if None, seed will generate by numpy.random.randint. Default: None.

  • dtype (mindquantum.dtype) – the data type of simulator. Default: None.

Raises

Examples

>>> from mindquantum.algorithm.library import qft
>>> from mindquantum.simulator import Simulator
>>> sim = Simulator('mqvector', 2)
>>> sim.apply_circuit(qft(range(2)))
>>> sim.get_qs()
array([0.5+0.j, 0.5+0.j, 0.5+0.j, 0.5+0.j])
apply_circuit(circuit, pr=None)[source]

Apply a circuit on this simulator.

Parameters
Returns

MeasureResult or None, if the circuit has measure gate, then return a MeasureResult, otherwise return None.

Examples

>>> import numpy as np
>>> from mindquantum.core.circuit import Circuit
>>> from mindquantum.core.gates import H
>>> from mindquantum.simulator import Simulator
>>> sim = Simulator('mqvector', 2)
>>> sim.apply_circuit(Circuit().un(H, 2))
>>> sim.apply_circuit(Circuit().ry('a', 0).ry('b', 1), np.array([1.1, 2.2]))
>>> sim
mqvector simulator with 2 qubits  (little endian).
Current quantum state:
-0.0721702531972066¦00⟩
-0.30090405886869676¦01⟩
0.22178317006196263¦10⟩
0.9246947752567126¦11⟩
>>> sim.apply_circuit(Circuit().measure(0).measure(1))
shots: 1
Keys: q1 q0│0.00     0.2         0.4         0.6         0.8         1.0
───────────┼───────────┴───────────┴───────────┴───────────┴───────────┴
         11│▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓

{'11': 1}
apply_gate(gate, pr=None, diff=False)[source]

Apply a gate on this simulator, can be a quantum gate or a measurement operator.

Parameters
Returns

int or None, if the gate if a measure gate, then return a collapsed state, Otherwise return None.

Raises
  • TypeError – if gate is not a BasicGate.

  • ValueError – if any qubit of gate is higher than simulator qubits.

  • ValueError – if gate is parameterized, but no parameter supplied.

  • TypeError – the pr is not a ParameterResolver if gate is parameterized.

Examples

>>> import numpy as np
>>> from mindquantum.core.gates import RY, Measure
>>> from mindquantum.simulator import Simulator
>>> sim = Simulator('mqvector', 1)
>>> sim.apply_gate(RY('a').on(0), np.pi/2)
>>> sim.get_qs()
array([0.70710678+0.j, 0.70710678+0.j])
>>> sim.apply_gate(Measure().on(0))
1
>>> sim.get_qs()
array([0.+0.j, 1.+0.j])
apply_hamiltonian(hamiltonian: Hamiltonian)[source]

Apply hamiltonian to a simulator, this hamiltonian can be hermitian or non hermitian.

Note

The quantum state may be not a normalized quantum state after apply hamiltonian.

Parameters

hamiltonian (Hamiltonian) – the hamiltonian you want to apply.

Examples

>>> from mindquantum.core.circuit import Circuit
>>> from mindquantum.core.operators import QubitOperator, Hamiltonian
>>> from mindquantum.simulator import Simulator
>>> import scipy.sparse as sp
>>> sim = Simulator('mqvector', 1)
>>> sim.apply_circuit(Circuit().h(0))
>>> sim.get_qs()
array([0.70710678+0.j, 0.70710678+0.j])
>>> ham1 = Hamiltonian(QubitOperator('Z0'))
>>> sim.apply_hamiltonian(ham1)
>>> sim.get_qs()
array([ 0.70710678+0.j, -0.70710678+0.j])
>>> sim.reset()
>>> ham2 = Hamiltonian(sp.csr_matrix([[1, 2], [3, 4]]))
>>> sim.apply_hamiltonian(ham2)
>>> sim.get_qs()
array([1.+0.j, 3.+0.j])
astype(dtype, seed=None)[source]

Convert simulator to other data type.

Note

The quantum state will copied from origin simulator.

Parameters
  • dtype (mindquantum.dtype) – the data type of new simulator.

  • seed (int) – the seed of new simulator. Default: None.

copy()[source]

Copy this simulator.

Returns

Simulator, a copy version of this simulator.

Examples

>>> from mindquantum.core.gates import RX
>>> from mindquantum.simulator import Simulator
>>> sim = Simulator('mqvector', 1)
>>> sim.apply_gate(RX(1).on(0))
>>> sim2 = sim.copy()
>>> sim2.apply_gate(RX(-1).on(0))
>>> sim2
mqvector simulator with 1 qubit (little endian).
Current quantum state:
1¦0⟩
property dtype

Get data type of simulator.

entropy()[source]

Calculate the von Neumann entropy of current quantum state.

Definition of von Neumann entropy \(S\) shown as below.

\[S(\rho) = -\text{tr}(\rho \ln \rho)\]

where \(\rho\) is density matrix.

Returns

numbers.Number, the von Neumann entropy of current quantum state.

Examples

>>> from mindquantum.simulator import Simulator
>>> sim = Simulator('mqmatrix', 1)
>>> sim.set_qs([[0.5, 0], [0, 0.5]])
>>> sim.entropy()
0.6931471805599453
get_expectation(hamiltonian, circ_right=None, circ_left=None, simulator_left=None, pr=None)[source]

Get expectation of the given hamiltonian. The hamiltonian could be non hermitian.

This method is designed to calculate the expectation shown as below.

\[E = \left<\varphi\right|U_l^\dagger H U_r \left|\psi\right>\]

where \(U_l\) is circ_left, \(U_r\) is circ_right, \(H\) is hams and \(\left|\psi\right>\) is the current quantum state of this simulator, and \(\left|\varphi\right>\) is the quantum state of simulator_left.

Note

The input circuits only participate in the expectation calculation and will not change the current quantum state of this simulator.

Parameters
  • hamiltonian (Hamiltonian) – The hamiltonian you want to get expectation.

  • circ_right (Circuit) – The \(U_r\) circuit described above. If it is None, we will use empty circuit. Default: None.

  • circ_left (Circuit) – The \(U_l\) circuit described above. If it is None, then it will be the same as circ_right. Default: None.

  • simulator_left (Simulator) – The simulator that contains \(\left|\varphi\right>\). If None, then \(\left|\varphi\right>\) is assumed to be equals to \(\left|\psi\right>\). Default: None.

  • pr (Union[Dict[str, numbers.Number], ParameterResolver]) – the variable value of circuit. Default: None.

Returns

numbers.Number, the expectation value.

Examples

>>> from mindquantum.core.circuit import Circuit
>>> from mindquantum.core.operators import QubitOperator, Hamiltonian
>>> from mindquantum.simulator import Simulator
>>> sim = Simulator('mqvector', 1)
>>> sim.apply_circuit(Circuit().ry(1.2, 0))
>>> ham = Hamiltonian(QubitOperator('Z0'))
>>> sim.get_expectation(ham)
(0.36235775447667357+0j)
>>> sim.get_expectation(ham, Circuit().rx('a', 0), Circuit().ry(2.3, 0), pr={'a': 2.4})
(-0.25463350745693886+0.8507316752782879j)
>>> sim1, sim2 = Simulator('mqvector', 1), Simulator('mqvector', 1)
>>> sim1.apply_circuit(Circuit().ry(1.2, 0).rx(2.4, 0))
>>> sim2.apply_circuit(Circuit().ry(1.2, 0).ry(2.3, 0))
>>> sim1.apply_hamiltonian(ham)
>>> from mindquantum.simulator import inner_product
>>> inner_product(sim2, sim1)
(-0.25463350745693886+0.8507316752782879j)
get_expectation_with_grad(hams, circ_right, circ_left=None, simulator_left=None, parallel_worker=None, pr_shift=False)[source]

Get a function that return the forward value and gradient w.r.t circuit parameters.

This method is designed to calculate the expectation and its gradient shown as below.

\[E = \left<\varphi\right|U_l^\dagger H U_r \left|\psi\right>\]

where \(U_l\) is circ_left, \(U_r\) is circ_right, \(H\) is hams and \(\left|\psi\right>\) is the current quantum state of this simulator, and \(\left|\varphi\right>\) is the quantum state of simulator_left.

Note

The input circuits only participate in the expectation and gradient calculation and will not change the current quantum state of this simulator.

Parameters
  • hams (Union[Hamiltonian, List[Hamiltonian]]) – A Hamiltonian or a list of Hamiltonian that need to get expectation.

  • circ_right (Circuit) – The \(U_r\) circuit described above.

  • circ_left (Circuit) – The \(U_l\) circuit described above. By default, this circuit will be none, and in this situation, \(U_l\) will be equals to \(U_r\). Default: None.

  • simulator_left (Simulator) – The simulator that contains \(\left|\varphi\right>\). If None, then \(\left|\varphi\right>\) is assumed to be equals to \(\left|\psi\right>\). Default: None.

  • parallel_worker (int) – The parallel worker numbers. The parallel workers can handle batch in parallel threads. Default: None.

  • pr_shift (bool) – Whether or not to use parameter-shift rule. Only available in "mqvector" simulator. It will be enabled automatically when circuit contains noise channel. Noted that not every gate uses the same shift value π/2, so the gradient of FSim gate and parameterized custom gate will be calculated by finite difference method with gap 0.001. Default: False.

Returns

GradOpsWrapper, a grad ops wrapper than contains information to generate this grad ops.

Examples

>>> import numpy as np
>>> from mindquantum.core.circuit import Circuit
>>> from mindquantum.core.operators import QubitOperator, Hamiltonian
>>> from mindquantum.simulator import Simulator
>>> circ = Circuit().ry('a', 0)
>>> ham = Hamiltonian(QubitOperator('Z0'))
>>> sim = Simulator('mqvector', 1)
>>> grad_ops = sim.get_expectation_with_grad(ham, circ)
>>> grad_ops(np.array([1.0]))
(array([[0.54030231+0.j]]), array([[[-0.84147098+0.j]]]))
>>> sim1 = Simulator('mqvector', 1)
>>> prep_circ = Circuit().h(0)
>>> ansatz = Circuit().ry('a', 0).rz('b', 0).ry('c', 0)
>>> sim1.apply_circuit(prep_circ)
>>> sim2 = Simulator('mqvector', 1)
>>> ham = Hamiltonian(QubitOperator(""))
>>> grad_ops = sim2.get_expectation_with_grad(ham, ansatz, Circuit(), simulator_left=sim1)
>>> f, g = grad_ops(np.array([7.902762e-01, 2.139225e-04, 7.795934e-01]))
>>> f
array([[0.99999989-7.52279618e-05j]])
get_partial_trace(qubits_to_trace)[source]

Calculate the partial trace of current density matrix.

Parameters

qubits_to_trace (Union[int, list[int]]) – Specific which qubits (subsystems) to trace over.

Returns

numpy.ndarray, the partial trace of current density matrix.

Examples

>>> from mindquantum.core.circuit import Circuit
>>> from mindquantum.simulator import Simulator
>>> circ = Circuit().h(0).x(1, 0)
>>> sim = Simulator('mqmatrix', 2)
>>> sim.apply_circuit(circ)
>>> mat = sim.get_partial_trace(0)
>>> mat
array([[0.5-0.j, 0. -0.j],
       [0. +0.j, 0.5-0.j]])
get_pure_state_vector()[source]

Get state vector if current density matrix is pure.

The relation between density matrix \(\rho\) and state vector \(\left| \psi \right>\) shown as below.

\[\rho = \left| \psi \right>\!\left< \psi \right|\]

Note that the state vector \(\left| \psi \right>\) may have an arbitrary global phase \(e^{i\phi}\).

Returns

numpy.ndarray, a state vector calculated from current density matrix.

Examples

>>> from mindquantum.simulator import Simulator
>>> sim = Simulator('mqmatrix', 1)
>>> sim.set_qs([[0.5, 0.5], [0.5, 0.5]])
>>> sim.get_pure_state_vector()
array([0.70710678+0.j, 0.70710678+0.j])
get_qs(ket=False)[source]

Get current quantum state of this simulator.

For state vector simulator, returns quantum state in state vector representation. For density matrix simulator, returns quantum state in density matrix representation.

The quantum state can optionally be returned in ket (Dirac notation) format. For mixed states, it will be represented as a probability weighted sum of pure states.

Parameters

ket (bool) – Whether to return the quantum state in ket format or not. Default: False.

Returns

The current quantum state. If ket is True, returns string representation in ket notation. For state vector simulator, returns 1D array or ket string of state vector. For density matrix simulator, returns 2D array or ket string of density matrix.

Return type

Union[numpy.ndarray, str]

Examples

>>> from mindquantum.algorithm.library import qft
>>> from mindquantum.simulator import Simulator
>>> sim = Simulator('mqvector', 2)
>>> sim.apply_circuit(qft(range(2)))
>>> sim.get_qs()
array([0.5+0.j, 0.5+0.j, 0.5+0.j, 0.5+0.j])
get_qs_of_qubits(qubits, ket=False)[source]

Get current reduced quantum state of specified qubits in this simulator.

The reduced quantum state is obtained by performing partial trace over other qubits. If the resulting state is pure, it returns state vector, while for mixed states, it returns density matrix.

It can optionally be returned in ket (Dirac notation) format. For mixed states, it will be represented as a probability weighted sum of pure states.

Note

  • The order of qubits in the input list does not affect the result.

  • The returned quantum state follows little-endian ordering (e.g., in ket notation, ¦01⟩ means q1=0, q0=1).

Parameters
  • qubits (Union[int, List[int]]) – The qubits to observe. Can be a single integer or a list of integers.

  • ket (bool) – Whether to return the quantum state in ket notation string. Default: False.

Returns

If ket is True, return string representation of

quantum state. If ket is False and the state is pure, return state vector as numpy array. If the state is mixed, return density matrix.

Return type

Union[np.ndarray, str]

Examples

>>> from mindquantum.simulator import Simulator
>>> sim = Simulator('mqvector', 2)
>>> sim.apply_circuit(Circuit().h(0).x(1,0))
>>> # Get state vector of qubit 0
>>> state_0 = sim.get_qs_of_qubits(0)
>>> state_0
array([[0.5+0.j, 0. +0.j],
      [0. +0.j, 0.5+0.j]])
>>> # Get ket string representation of qubit 1
>>> state_1 = sim.get_qs_of_qubits(1, ket=True)
>>> state_1
'1/2¦1⟩ + 1/2¦0⟩ (mixed state)'
get_reduced_density_matrix(kept_qubits)[source]

Get the reduced density matrix of specified qubits by performing partial trace over other qubits.

Note

  • The order of qubits in the input list does not affect the result.

  • The returned density matrix follows little-endian ordering (e.g., for a 2-qubit state, the basis states are ordered as ¦00⟩, ¦01⟩, ¦10⟩, ¦11⟩ where ¦01⟩ means q1=0, q0=1).

Parameters

kept_qubits (Union[int, List[int]]) – The indices of qubits to keep, can be a single integer or a list of integers.

Returns

The reduced density matrix of the specified qubits.

Return type

numpy.ndarray

Examples

>>> from mindquantum.simulator import Simulator
>>> sim = Simulator('mqvector', 2)
>>> sim.apply_circuit(Circuit().h(0).x(1,0))
>>> # Get reduced density matrix of qubit 1
>>> rho_1 = sim.get_reduced_density_matrix([1])
>>> print(rho_1)
[[0.5+0.j 0.0+0.j]
 [0.0+0.j 0.5+0.j]]
property n_qubits

Get simulator qubit.

Returns

int, the qubit number of simulator.

purity()[source]

Calculate the purity of current quantum state.

Definition of purity \(\gamma\) shown as below.

\[\gamma \equiv \text{tr}(\rho^2)\]

where \(\rho\) is density matrix.

Returns

numbers.Number, the purity of current quantum state.

Examples

>>> from mindquantum.simulator import Simulator
>>> sim = Simulator('mqmatrix', 1)
>>> sim.set_qs([[0.5, 0], [0, 0.5]])
>>> sim.purity()
0.5
reset()[source]

Reset simulator to zero state.

Examples

>>> from mindquantum.algorithm.library import qft
>>> from mindquantum.simulator import Simulator
>>> sim = Simulator('mqvector', 2)
>>> sim.apply_circuit(qft(range(2)))
>>> sim.reset()
>>> sim.get_qs()
array([1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j])
sampling(circuit, pr=None, shots=1, seed=None)[source]

Sample the measure qubit in circuit.

Note

  • The input circuit only participates in the sampling process and will not change the current quantum state of this simulator.

  • The sampling results are represented in little-endian order by default (e.g., '01' means q1=0, q0=1). If big-endian order is needed, use MeasureResult.reverse_endian() method.

Parameters
  • circuit (Circuit) – The circuit that you want to evolve and sample.

  • pr (Union[None, dict, ParameterResolver]) – The parameter resolver for this circuit, if this circuit is a parameterized circuit. Default: None.

  • shots (int) – How many shots you want to sample this circuit. Default: 1.

  • seed (int) – Random seed for random sampling. If None, seed will be a random int number. Default: None.

Returns

MeasureResult, the measure result of sampling. The bit strings in the result are in little-endian order.

Examples

>>> from mindquantum.core.circuit import Circuit
>>> from mindquantum.core.gates import Measure
>>> from mindquantum.simulator import Simulator
>>> circ = Circuit().ry('a', 0).ry('b', 1)
>>> circ += Measure('q0_0').on(0)
>>> circ += Measure('q0_1').on(0)
>>> circ += Measure('q1').on(1)
>>> sim = Simulator('mqvector', circ.n_qubits)
>>> res = sim.sampling(circ, {'a': 1.1, 'b': 2.2}, shots=100, seed=42)
>>> res
shots: 100
Keys: q1 q0_1 q0_0│0.00   0.122       0.245       0.367        0.49       0.612
──────────────────┼───────────┴───────────┴───────────┴───────────┴───────────┴
               000│▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒

               011│▒▒▒▒▒▒▒▒▒

               100│▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓

               111│▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒

{'000': 18, '011': 9, '100': 49, '111': 24}
set_qs(quantum_state)[source]

Set quantum state for this simulation.

Parameters

quantum_state (numpy.ndarray) – the quantum state that you want.

Examples

>>> import numpy as np
>>> from mindquantum.simulator import Simulator
>>> sim = Simulator('mqvector', 1)
>>> sim.get_qs()
array([1.+0.j, 0.+0.j])
>>> sim.set_qs(np.array([1, 1]))
>>> sim.get_qs()
array([0.70710678+0.j, 0.70710678+0.j])
set_threads_number(number)[source]

Set maximum number of threads.

Parameters

number (int) – The thread number the simulator will use for thread pool.