diff --git a/.github/workflows/ci_chemistry_psi4.yml b/.github/workflows/ci_chemistry_psi4.yml index ef9c1e3a..98481972 100644 --- a/.github/workflows/ci_chemistry_psi4.yml +++ b/.github/workflows/ci_chemistry_psi4.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [3.8] + python-version: [3.9] steps: - uses: actions/checkout@v2 @@ -50,7 +50,7 @@ jobs: source $HOME/.bashrc source $CONDABASE/bin/activate conda activate test_psi4 - conda install psi4 python=3.8 -c psi4 + conda install psi4 python=3.9 -c conda-forge python -m pip install --upgrade pip python -m pip install -r requirements.txt python -m pip install -e . diff --git a/README.md b/README.md index 3cec3281..b415c3f3 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Tequila can execute the underlying quantum expectation values on state of the ar - [talks and slides](https://kottmanj.github.io/talks_and_material/) # Installation -Recommended Python version is 3.8-3.9. +Recommended Python version is 3.9 - 3.10. Tequila supports linux, osx and windows. However, not all optional dependencies are supported on windows. ## Install from PyPi @@ -267,7 +267,7 @@ Currently supported ### [Psi4](https://github.com/psi4/psi4). In a conda environment this can be installed with ```bash -conda install psi4 -c psi4 +conda install psi4 -c conda-forge ``` Here is a small [tutorial](https://nbviewer.org/github/tequilahub/tequila-tutorials/blob/main/chemistry/ChemistryModule.ipynb) that illustrates the usage. diff --git a/src/tequila/circuit/qasm.py b/src/tequila/circuit/qasm.py index 65878f76..16a35b57 100644 --- a/src/tequila/circuit/qasm.py +++ b/src/tequila/circuit/qasm.py @@ -313,19 +313,33 @@ def parse_command(command: str, custom_gates_map: Dict[str, QCircuit], qregister return apply_custom_gate(custom_circuit=custom_circuit, qregisters_values=qregisters_values) if name in ("x", "y", "z", "h", "cx", "cy", "cz", "ch"): - return QCircuit.wrap_gate(gates.impl.QGateImpl(name=(name[1] if name[0] == 'c' else name).upper(), - control=get_qregister(args[0], qregisters) if name[0] == 'c' else None, - target=get_qregister(args[1 if name[0] == 'c' else 0], qregisters))) + target = get_qregister(args[0], qregisters) + control = None + if name[0].lower() == 'c': + control = get_qregister(args[0], qregisters) + target = get_qregister(args[1], qregisters) + name = name[1] + G = getattr(gates, name.upper()) + return G(control=control, target=target) + if name in ("ccx", "ccy", "ccz"): - return QCircuit.wrap_gate(gates.impl.QGateImpl(name=name.upper()[2], - control=[get_qregister(args[0], qregisters), get_qregister(args[1], qregisters)], - target=get_qregister(args[2], qregisters))) + G = getattr(gates, name[2].upper()) + control = [get_qregister(args[0], qregisters), get_qregister(args[1], qregisters)] + target = get_qregister(args[2], qregisters) + return G(control=control, target=target) + if name.startswith("rx(") or name.startswith("ry(") or name.startswith("rz(") or \ name.startswith("crx(") or name.startswith("cry(") or name.startswith("crz("): - return QCircuit.wrap_gate(gates.impl.RotationGateImpl(axis=name[2 if name[0] == 'c' else 1], - angle=get_angle(name)[0], - control=get_qregister(args[0], qregisters) if name[0] == 'c' else None, - target=get_qregister(args[1 if name[0] == 'c' else 0], qregisters))) + angle = get_angle(name)[0] + i = name.find('(') + name = name[0:i] + name = name.upper() + name = [x for x in name] + name[-1] = name[-1].lower() + name = "".join(name) + G = getattr(gates, name) + return G(angle=angle,control=get_qregister(args[0], qregisters) if name[0] == 'C' else None,target=get_qregister(args[1 if name[0] == 'C' else 0], qregisters)) + if name.startswith("U("): angles = get_angle(name) return gates.U(theta=angles[0], phi=angles[1], lambd=angles[2], @@ -362,7 +376,7 @@ def parse_command(command: str, custom_gates_map: Dict[str, QCircuit], qregister control=get_qregister(args[0], qregisters), target=get_qregister(args[1], qregisters)) if name in ("s", "t", "sdg", "tdg"): - g = gates.Phase(pi / (2 if name.startswith("s") else 4), + g = gates.Phase(angle=pi / (2 if name.startswith("s") else 4), control=None, target=get_qregister(args[0], qregisters)) if name.find("dg") != -1: diff --git a/src/tequila/quantumchemistry/qc_base.py b/src/tequila/quantumchemistry/qc_base.py index cd828641..617b68f6 100644 --- a/src/tequila/quantumchemistry/qc_base.py +++ b/src/tequila/quantumchemistry/qc_base.py @@ -646,6 +646,68 @@ def n_electrons(self) -> int: """ return 2 * len(self.integral_manager.active_reference_orbitals) + def make_annihilation_op(self, orbital, coefficient=1.0): + """ + Compute annihilation operator on spin-orbital in qubit representation + Spin-orbital order is always (up,down,up,down,...) + """ + assert orbital<=self.n_orbitals*2 + aop = openfermion.ops.FermionOperator(f'{orbital}', coefficient) + return self.transformation(aop) + + def make_creation_op(self, orbital, coefficient=1.0): + """ + Compute creation operator on spin-orbital in qubit representation + Spin-orbital order is always (up,down,up,down,...) + """ + assert orbital<=self.n_orbitals*2 + cop = openfermion.ops.FermionOperator(f'{orbital}^', coefficient) + return self.transformation(cop) + + def make_number_op(self, orbital): + """ + Compute number operator on spin-orbital in qubit representation + Spin-orbital order is always (up,down,up,down,...) + """ + num_op = self.make_creation_op(orbital) * self.make_annihilation_op(orbital) + return num_op + + def make_sz_op(self): + """ + Compute the spin_z operator of the molecule in qubit representation + """ + sz = QubitHamiltonian() + for i in range(0, self.n_orbitals * 2, 2): + one = 0.5 * self.make_creation_op(i) * self.make_annihilation_op(i) + two = 0.5 * self.make_creation_op(i+1) * self.make_annihilation_op(i+1) + sz += (one - two) + return sz + + def make_sp_op(self): + """ + Compute the spin+ operator of the molecule in qubit representation + """ + sp = QubitHamiltonian() + for i in range(self.n_orbitals): + sp += self.make_creation_op(i*2) * self.make_annihilation_op(i*2 + 1) + return sp + + def make_sm_op(self): + """ + Compute the spin- operator of the molecule in qubit representation + """ + sm = QubitHamiltonian() + for i in range(self.n_orbitals): + sm += self.make_creation_op(i*2 + 1) * self.make_annihilation_op(i*2) + return sm + + def make_s2_op(self): + """ + Compute the spin^2 operator of the molecule in qubit representation + """ + s2_op = self.make_sm_op() * self.make_sp_op() + self.make_sz_op() * (self.make_sz_op() + 1) + return s2_op + def make_hamiltonian(self, *args, **kwargs) -> QubitHamiltonian: """ Parameters diff --git a/src/tequila/version.py b/src/tequila/version.py index 74bd1fb8..a54a7564 100644 --- a/src/tequila/version.py +++ b/src/tequila/version.py @@ -1,2 +1,2 @@ -__version__ = "1.9.4.dev" +__version__ = "1.9.4" __author__ = "Tequila Developers "