diff --git a/mindquantum/algorithm/nisq/chem/__init__.py b/mindquantum/algorithm/nisq/chem/__init__.py index 4e4fd4a7e7f1f4641806034fb5bda3bfbf42f5b3..36f293ad4ccc21a5ffa96bd19f825db53db8327f 100644 --- a/mindquantum/algorithm/nisq/chem/__init__.py +++ b/mindquantum/algorithm/nisq/chem/__init__.py @@ -34,6 +34,7 @@ from .qubit_hamiltonian import get_qubit_hamiltonian from .qubit_ucc_ansatz import QubitUCCAnsatz from .quccsd import quccsd_generator from .reference_state import get_reference_circuit +from .sequential_ucc_ansatz import SequentialUCCAnsatz from .transform import Transform from .uccsd import generate_uccsd from .uccsd0 import uccsd0_singlet_generator @@ -50,6 +51,7 @@ __all__ = [ 'HardwareEfficientAnsatz', 'QubitUCCAnsatz', 'generate_uccsd', + 'SequentialUCCAnsatz', 'UCCAnsatz', 'get_reference_circuit', 'RYLinear', diff --git a/mindquantum/algorithm/nisq/chem/sequential_ucc_ansatz.py b/mindquantum/algorithm/nisq/chem/sequential_ucc_ansatz.py new file mode 100644 index 0000000000000000000000000000000000000000..7d3dc609ed364e065fe169ddb8f87226a80029f1 --- /dev/null +++ b/mindquantum/algorithm/nisq/chem/sequential_ucc_ansatz.py @@ -0,0 +1,108 @@ +# Copyright 2025 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +"""Sequential Unitary Coupled-Cluster Ansatz.""" + +from mindquantum.core.circuit import Circuit +from mindquantum.core.operators import FermionOperator +from mindquantum.simulator.mqchem import UCCExcitationGate +from .._ansatz import Ansatz + + +class SequentialUCCAnsatz(Ansatz): + """ + Sequential Unitary Coupled-Cluster (UCC) Ansatz. + + This class allows constructing a UCC ansatz by adding excitation operators sequentially. + Unlike ``FermionOperator`` which merges terms with the same index, this class preserves + the order and distinctness of each added term, enabling the construction of + multi-layer or Trotterized ansatzes where the same excitation operator may appear + multiple times with different parameters. + + Args: + 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``. + + Examples: + >>> from mindquantum.algorithm.nisq import SequentialUCCAnsatz + >>> from mindquantum.core.operators import FermionOperator + >>> ansatz = SequentialUCCAnsatz() + >>> ansatz.append(FermionOperator("3^ 1", "a")) + >>> ansatz.append(FermionOperator("4^ 2", "b")) + >>> ansatz.append(FermionOperator("3^ 1", "c")) + >>> print(len(ansatz.circuit)) + 3 + >>> print(ansatz.circuit.params_name) + ['a', 'b', 'c'] + """ + + def __init__(self, n_qubits=None, n_electrons=None): + """Initialize a SequentialUCCAnsatz object.""" + super().__init__("Sequential UCC", n_qubits, n_qubits, n_electrons) + self._operators = [] + + def _implement(self, n_qubits=None, n_electrons=None): + """Implement the ansatz.""" + # No initial implementation needed as operators are added sequentially. + pass + + def append(self, operator: FermionOperator): + """ + Append a FermionOperator to the ansatz. + + Args: + operator (FermionOperator): The excitation operator to add. Must have exactly one term. + """ + if not isinstance(operator, FermionOperator): + raise TypeError(f"operator must be a FermionOperator, but got {type(operator)}") + + if len(operator.terms) != 1: + raise ValueError("The added FermionOperator must have exactly one term.") + + self._operators.append(operator) + self._circuit += UCCExcitationGate(operator) + + def __iadd__(self, other): + """ + Support the += operator to append an operator. + + Args: + other (FermionOperator): The operator to append. + """ + self.append(other) + return self + + def remove(self, index: int): + """ + Remove an operator from the ansatz at the specified index. + + Args: + index (int): The index of the operator to remove. + """ + if index < 0 or index >= len(self._operators): + raise IndexError("Index out of range.") + + del self._operators[index] + self._rebuild_circuit() + + def _rebuild_circuit(self): + """Reconstruct the circuit from the current list of operators.""" + self._circuit = Circuit() + for op in self._operators: + self._circuit += UCCExcitationGate(op) + + @property + def operators(self): + """Return the list of operators in the ansatz.""" + return list(self._operators)