mindquantum.ansatz

Implementation of different ansatz.

class mindquantum.ansatz.Ansatz(name, n_qubits, *args, **kwargs)[source]

Basic class for Ansatz.

Parameters
  • name (str) – The name of this ansatz.

  • n_qubits (int) – How many qubits this ansatz act on.

property circuit

Get the quantum circuit of this ansatz.

Returns

Circuit, the quantum circuit of this ansatz.

class mindquantum.ansatz.MaxCutAnsatz(graph, depth=1)[source]

The MaxCut ansatz. For more detail, please refers to https://arxiv.org/pdf/1411.4028.pdf.

\[U(\beta, \gamma) = e^{-\beta_pH_b}e^{-\gamma_pH_c} \cdots e^{-\beta_0H_b}e^{-\gamma_0H_c}H^{\otimes n}\]

Where,

\[H_b = \sum_{i\in n}X_{i}, H_c = \sum_{(i,j)\in C}Z_iZ_j\]

Here \(n\) is the set of nodes and \(C\) is the set of edges of the graph.

Parameters
  • graph (list[tuple[int]]) – The graph structure. Every element of graph is a edge that constructed by two nodes.

  • depth (int) – The depth of max cut ansatz. Default: 1.

Examples

>>> from mindquantum.ansatz import MaxCutAnsatz
>>> graph = [(0, 1), (1, 2), (0, 2)]
>>> maxcut = MaxCutAnsatz(graph, 2)
>>> maxcut.circuit
H(0)
H(1)
H(2)
ZZ(beta_0|0 1)
ZZ(beta_0|1 2)
ZZ(beta_0|0 2)
RX(alpha_0|0)
RX(alpha_0|1)
RX(alpha_0|2)
ZZ(beta_1|0 1)
ZZ(beta_1|1 2)
ZZ(beta_1|0 2)
RX(alpha_1|0)
RX(alpha_1|1)
RX(alpha_1|2)
>>> maxcut.hamiltonian
1.5 [] +
-0.5 [Z0 Z1] +
-0.5 [Z0 Z2] +
-0.5 [Z1 Z2]
property hamiltonian

Get the hamiltonian of this max cut problem.

Returns

QubitOperator, hamiltonian of this max cut problem.

class mindquantum.ansatz.Max2SATAnsatz(clauses, depth=1)[source]

The Max-2-SAT ansatz. For more detail, please refers to https://arxiv.org/pdf/1906.11259.pdf.

\[U(\beta, \gamma) = e^{-\beta_pH_b}e^{-\gamma_pH_c} \cdots e^{-\beta_0H_b}e^{-\gamma_0H_c}H^{\otimes n}\]

Where,

\[H_b = \sum_{i\in n}X_{i}, H_c = \sum_{l\in m}P(l)\]

Here \(n\) is the number of Boolean variables and \(m\) is the number of total clauses and \(P(l)\) is rank-one projector.

Parameters
  • graph (list[tuple[int]]) – The Max-2-SAT structure. Every element of list is a clause represented by a tuple with length two. The element of tuple must be non-zero integer. For example, (2, -3) stands for clause \(x_2\lor\lnot x_3\).

  • depth (int) – The depth of Max-2-SAT ansatz. Default: 1.

Examples

>>> from mindquantum.ansatz import Max2SATAnsatz
>>> clauses = [(1, 2), (2, -3)]
>>> max2sat = Max2SATAnsatz(clauses, 2)
>>> max2sat.circuit
H(0)
H(1)
H(2)
RZ(0.25*beta_0|0)
RZ(0.5*beta_0|1)
X(1 <-: 0)
RZ(0.5*beta_0|1)
X(1 <-: 0)
RZ(-0.25*beta_0|2)
X(2 <-: 1)
RZ(-0.5*beta_0|2)
X(2 <-: 1)
RX(alpha_0|0)
RX(alpha_0|1)
RX(alpha_0|2)
RZ(0.25*beta_1|0)
RZ(0.5*beta_1|1)
X(1 <-: 0)
RZ(0.5*beta_1|1)
X(1 <-: 0)
RZ(-0.25*beta_1|2)
X(2 <-: 1)
RZ(-0.5*beta_1|2)
X(2 <-: 1)
RX(alpha_1|0)
RX(alpha_1|1)
RX(alpha_1|2)
>>> max2sat.hamiltonian
0.5 [] +
0.25 [Z0] +
0.25 [Z0 Z1] +
0.5 [Z1] +
-0.25 [Z1 Z2] +
-0.25 [Z2]
property hamiltonian

Get the hamiltonian of this max 2 sat problem.

Returns

QubitOperator, hamiltonian of this max 2 sat problem.

class mindquantum.ansatz.HardwareEfficientAnsatz(n_qubits, single_rot_gate_seq, entangle_gate=X, entangle_mapping="linear", depth=1)[source]

Hardware efficient ansatz is a kind of ansatz that can be easily implement on quantum chip.

The hardware efficient is constructed by a layer of single qubit rotation gate and a layer of two qubits entanglement gate. The single qubit rotation gate layer is constructed by one or several rotation gate that act on every qubit. The two qubits entanglement gate layer is constructed by CNOT, CZ, XX, YY, ZZ, etc. acting on entangle_mapping. For more detail, please refers https://www.nature.com/articles/nature23879.

Parameters
  • n_qubits (int) – number of qubit that this ansatz act on.

  • single_rot_gate_seq (list[BasicGate]) – A list of parameterized rotation gate that act on each qubit.

  • entangle_gate (BasicGate) – The non parameterized entanglement gate. If it is a single qubit gate, than the control version will be used. Default: XGate.

  • entangle_mapping (Union[str, list[tuple[int]]]) – The entanglement mapping of entanglement gate. ‘linear’ means the entanglement gate will be act on every neighboring qubits. ‘all’ means the entanglemtn gate will be act on any two qbuits. Besides, you can specific which two qubits you want to do entanglement by setting the entangle_mapping to a list of two qubits tuple. Default: “linear”.

  • depth (int) – Repeat the entanglement gate layer and single_rot_gate_seq in depth times. Default: 1.

Examples

>>> from mindquantum.ansatz import HardwareEfficientAnsatz
>>> from mindquantum import RY, RZ, Z
>>> hea = HardwareEfficientAnsatz(3, [RY, RZ], Z, [(1, 0), (2, 0)])
>>> hea.circuit
RY(d0_n0_0|0)
RZ(d0_n0_1|0)
RY(d0_n1_0|1)
RZ(d0_n1_1|1)
RY(d0_n2_0|2)
RZ(d0_n2_1|2)
Z(1 <-: 0)
Z(2 <-: 0)
RY(d1_n0_0|0)
RZ(d1_n0_1|0)
RY(d1_n1_0|1)
RZ(d1_n1_1|1)
RY(d1_n2_0|2)
RZ(d1_n2_1|2)
class mindquantum.ansatz.UCCAnsatz(n_qubits=None, n_electrons=None, occ_orb=None, vir_orb=None, generalized=False, trotter_step=1)[source]

The unitary coupled-cluster ansatz for molecular simulations.

\[U(\vec{\theta}) = \prod_{j=1}^{N(N\ge1)}{\prod_{i=0}^{N_{j}}{\exp{(\theta_{i}\hat{\tau}_{i})}}}\]

where \(\hat{\tau}\) are anti-Hermitian operators.

Note

Currently, the circuit is construncted using JW transformation. In addition, the reference state wave function (Hartree-Fock) will NOT be included.

Parameters
  • n_qubits (int) – Number of qubits (spin-orbitals). Default: None.

  • n_electrons (int) – Number of electrons (occupied spin-orbitals). Default: None.

  • occ_orb (list) – Indices of manually assigned occupied spatial orbitals, for ansatz construction only. Default: None.

  • vir_orb (list) – Indices of manually assigned virtual spatial orbitals, for ansatz construction only. Default: None.

  • generalized (bool) – Whether to use generalized excitations which do not distinguish occupied or virtual orbitals (UCCGSD). Default: False.

  • trotter_step (int) – The order of Trotterization step. Default: 1.

Examples

>>> from mindquantum.ansatz import UCCAnsatz
>>> ucc = UCCAnsatz(12, 4, occ_orb=[1],
...                 vir_orb=[2, 3],
...                 generalized=True,
...                 trotter_step=2)
>>> circuit_list = list(ucc.circuit)
>>> len(circuit_list)
3624
>>> params_list = ucc.circuit.para_name
>>> len(params_list)
40
>>> for i in range(10):
...     print(circuit_list[i])
...
RX(1.571|2)
H(4)
X(3 <-: 2)
X(4 <-: 3)
RZ(-1.0*t_0_d0_s_0|4)
X(4 <-: 3)
X(3 <-: 2)
H(4)
RX(10.996|2)
H(2)
class mindquantum.ansatz.QubitUCCAnsatz(n_qubits=None, n_electrons=None, occ_orb=None, vir_orb=None, generalized=False, trotter_step=1)[source]

Qubit Unitary Coupled-Cluster (qUCC) ansatz is a variant of unitary coupled-cluster ansatz which uses qubit excitation operators instead of Fermion excitation operators. The Fock space spanned by qubit excitation operators is equivalent as Fermion operators, therefore the exact wave function can be approximated using qubit excitation operators at the expense of a higher order of Trotterization.

The greatest advantange of qUCC is that the number of CNOT gates is much smaller than the original version of UCC, even using a 3rd or 4th order Trotterization. Also, the accuracy is greatly improved despite that the number of variational parameters is increased.

Note

The Hartree-Fock circuit is not included. Currently, generalized=True is not allowed since the theory needs verification. Reference: Yordan S. Yordanov et al. Phys. Rev. A, 102, 062612 (2020)

Parameters
  • n_qubits (int) – The number of qubits (spin-orbitals) in the simulation. Default: None.

  • n_electrons (int) – The number of electrons of the given molecule. Default: None.

  • occ_orb (list) – Indices of manually assigned occupied spatial orbitals. Default: None.

  • vir_orb (list) – Indices of manually assigned virtual spatial orbitals. Default: None.

  • generalized (bool) – Whether to use generalized excitations which do not distinguish occupied or virtual orbitals (qUCCGSD). Currently, generalized=True is not allowed since the theory needs verification. Default: False.

  • trotter_step (int) – The number of Trotter steps. Default is one. It is recommended to set a value larger than or equal to 2 to achieve a good accuracy. Default: 1.

Examples

>>> from mindquantum.ansatz import QubitUCCAnsatz
>>> QubitUCCAnsatz().n_qubits
0
>>> qucc = QubitUCCAnsatz(4, 2, trotter_step=2)
>>> qucc.circuit[:10]
CNOT(0 <-: 2)
RY(t_0_q_s_0|2 <-: 0)
CNOT(0 <-: 2)
CNOT(1 <-: 2)
RY(t_0_q_s_1|2 <-: 1)
CNOT(1 <-: 2)
CNOT(0 <-: 3)
RY(t_0_q_s_2|3 <-: 0)
CNOT(0 <-: 3)
CNOT(1 <-: 3)
>>> qucc.n_qubits
4
>>> qucc_2 = QubitUCCAnsatz(occ_orb=[0, 1], vir_orb=[2])
>>> qucc_2.operator_pool
[-1.0*t_0_q_s_0 [Q0^ Q4] +
1.0*t_0_q_s_0 [Q4^ Q0] , -1.0*t_0_q_s_1 [Q1^ Q4] +
1.0*t_0_q_s_1 [Q4^ Q1] , -1.0*t_0_q_s_2 [Q2^ Q4] +
1.0*t_0_q_s_2 [Q4^ Q2] , -1.0*t_0_q_s_3 [Q3^ Q4] +
1.0*t_0_q_s_3 [Q4^ Q3] , -1.0*t_0_q_s_4 [Q0^ Q5] +
1.0*t_0_q_s_4 [Q5^ Q0] , -1.0*t_0_q_s_5 [Q1^ Q5] +
1.0*t_0_q_s_5 [Q5^ Q1] , -1.0*t_0_q_s_6 [Q2^ Q5] +
1.0*t_0_q_s_6 [Q5^ Q2] , -1.0*t_0_q_s_7 [Q3^ Q5] +
1.0*t_0_q_s_7 [Q5^ Q3] , -1.0*t_0_q_d_0 [Q1^ Q0^ Q5 Q4] +
1.0*t_0_q_d_0 [Q5^ Q4^ Q1 Q0] , -1.0*t_0_q_d_1 [Q2^ Q0^ Q5 Q4] +
1.0*t_0_q_d_1 [Q5^ Q4^ Q2 Q0] , -1.0*t_0_q_d_2 [Q2^ Q1^ Q5 Q4] +
1.0*t_0_q_d_2 [Q5^ Q4^ Q2 Q1] , -1.0*t_0_q_d_3 [Q3^ Q0^ Q5 Q4] +
1.0*t_0_q_d_3 [Q5^ Q4^ Q3 Q0] , -1.0*t_0_q_d_4 [Q3^ Q1^ Q5 Q4] +
1.0*t_0_q_d_4 [Q5^ Q4^ Q3 Q1] , -1.0*t_0_q_d_5 [Q3^ Q2^ Q5 Q4] +
1.0*t_0_q_d_5 [Q5^ Q4^ Q3 Q2] ]