Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/develop' into autocas.
Browse files Browse the repository at this point in the history
  • Loading branch information
alexfleury-sb committed Nov 21, 2023
2 parents bcae466 + b2adf9d commit 0d707f8
Show file tree
Hide file tree
Showing 61 changed files with 33,732 additions and 376 deletions.
8 changes: 7 additions & 1 deletion .github/workflows/continuous_integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
with:
python-version: ${{ matrix.python-version }}

- name: Install pip, wheel, pytest, jupyter
- name: Install pip, wheel, pytest, jupyter, pyqsp
run: |
python -m pip install --upgrade pip
pip install wheel
Expand Down Expand Up @@ -77,6 +77,12 @@ jobs:
python -m pip install git+https://github.com/pyscf/semiempirical
if: always()

- name: Install rdkit, openbabel-wheel
run: |
python -m pip install rdkit
python -m pip install openbabel-wheel
if: always()

- name: tangelo tests
run: |
cd tangelo
Expand Down
5 changes: 4 additions & 1 deletion .github/workflows/run_psi4_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,15 @@ jobs:
conda init
if: always()

- name: Install pip, wheel, pytest, jupyter
- name: Install pip, wheel, pytest, jupyter, openbabel, rdkit, openmm
run: |
python -m pip install --upgrade pip
pip install wheel
pip install pytest
pip install pytest-cov
pip install rdkit
pip install openbabel-wheel
conda install -c conda-forge openmm
- name: Install qulacs
run: |
Expand Down
26 changes: 26 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,32 @@
This file documents the main changes between versions of the code.


## [0.4.1] - 2023-10-18

### Added

- QM/MM problem decomposition
- QPE framework
- Truncated taylor series function returning qubits
- simplify method on Circuit

### Changed

- Automated testing currently covering python 3.8, 3.9, 3.10, 3.11 (#333)
- Installation: pyscf removed from requirements
- Performance improvement: combinatorial mapping
- Feature: ILC iteration now implements exact expansion / parameters
- Feature: VQE-like algorithms verbose mode now prints and tracks energies, for users interested in the convergence of the algorithm.
- Bugfix: Combinatorial mapping now handles spin != 0 (#330)
- Bugfix: get_expectation_value takes into account n_shots for all backends supporting the option.
- Bugfix: Fix corner case of FCI and CCSD solvers calculations (mo coefficients were occasionally recomputed differently).
- Bugfix: Updates in IBMConnection to keep up with changes in qiskit-runtime.


### Deprecatedv / Removed



## [0.4.0] - 2023-06-29

### Added
Expand Down
17 changes: 14 additions & 3 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,19 @@ The contribution process is detailed in the `contributions <./CONTRIBUTIONS.rst>
Citations
---------

If you use Tangelo in your research, please cite:

Valentin Senicourt, James Brown, Alexandre Fleury, Ryan Day, Erika Lloyd, Marc P. Coons, Krzysztof Bieniasz, Lee Huntington, Alejandro J. Garza, Shunji Matsuura, Rudi Plesch, Takeshi Yamazaki, and Arman Zaribafiyan Tangelo: An Open-source Python Package for End-to-end Chemistry Workflows on Quantum Computers 2022 arXiv:2206.12424
If you use Tangelo in your research, please cite the `Tangelo release paper <https://arxiv.org/abs/2206.12424>`_ and consider mentioning Tangelo in your talks.

.. code-block:: latex

@article{tangelo,
author = {Valentin Senicourt and James Brown and Alexandre Fleury and Ryan Day and Erika Lloyd and Marc P. Coons and Krzysztof Bieniasz and Lee Huntington and Alejandro J. Garza and Shunji Matsuura and Rudi Plesch and Takeshi Yamazaki and Arman Zaribafiyan},
title = {Tangelo: An Open-source Python Package for End-to-end Chemistry Workflows on Quantum Computers},
year = {2022},
url= {https://arxiv.org/abs/2206.12424},
number = {arXiv:2206.12424},
eprint = {arXiv:2206.12424},
publisher = {{arXiv}},
doi = {10.48550/arXiv.2206.12424}
}

© Good Chemistry Company 2023. This software is released under the Apache Software License version 2.0.
7 changes: 4 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,23 @@
with open("tangelo/_version.py") as f:
version = f.readlines()[-1].split()[-1].strip("\"'")

# Ignoring this currently, the content of the README is very complex.
with open('README.rst', 'r') as f:
long_description = f.read()

description = "Maintained by Good Chemistry Company, focusing on the development of end-to-end materials simulation workflows on quantum computers."
description = "Tangelo is an open-source Python package maintained by Good Chemistry Company, focusing on the development of quantum chemistry simulation workflows on quantum computers. It was developed as an engine to accelerate research, and leverages other popular frameworks to harness the innovation in our field."

setuptools.setup(
name="tangelo-gc",
author="The Tangelo developers",
version=version,
description=description,
long_description=long_description,
long_description=description,
url="https://github.com/goodchemistryco/Tangelo",
packages=setuptools.find_packages(),
test_suite="tangelo",
install_requires=['h5py', 'bitarray', 'openfermion'],
extras_require={
'pyscf': ['pyscf', 'pyscf-semiempirical @ git+https://github.com/pyscf/[email protected]'], # pyscf-semiempirical PyPI sdist is missing C extension files
'pyscf': ['pyscf'] #'pyscf-semiempirical @ git+https://github.com/pyscf/[email protected]'], # pyscf-semiempirical PyPI sdist is missing C extension files
}
)
2 changes: 1 addition & 1 deletion tangelo/_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@

""" Define version number here. It is read in setup.py, and bumped automatically
when using the new release Github action. """
__version__ = "0.4.0"
__version__ = "0.4.1"
18 changes: 13 additions & 5 deletions tangelo/algorithms/classical/ccsd_solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from sympy.combinatorics.permutations import Permutation

from tangelo.toolboxes.molecular_computation.molecule import SecondQuantizedMolecule
from tangelo.toolboxes.molecular_computation import IntegralSolverPsi4, IntegralSolverPySCF
from tangelo.toolboxes.molecular_computation import IntegralSolverPsi4, IntegralSolverPySCF, IntegralSolverPsi4QMMM
from tangelo.algorithms.electronic_structure_solver import ElectronicStructureSolver
from tangelo.helpers.utils import installed_chem_backends, is_package_installed

Expand Down Expand Up @@ -161,17 +161,20 @@ def __init__(self, molecule: SecondQuantizedMolecule):
f"with a UHF reference in {self.__class__.__name__}")

# Frozen orbitals must be declared before calling compute_mean_field to be saved in ref_wfn for Psi4 ccsd.
intsolve = IntegralSolverPsi4()
intsolve = IntegralSolverPsi4() if not hasattr(molecule.solver, "charges") else IntegralSolverPsi4QMMM(molecule.solver.combinedcharges)
self.backend.set_options({'basis': molecule.basis, 'frozen_docc': [self.n_frozen_occ], 'frozen_uocc': [self.n_frozen_vir],
'reference': self.ref})

self.molecule = SecondQuantizedMolecule(xyz=molecule.xyz, q=molecule.q, spin=molecule.spin,
solver=intsolve,
basis=molecule.basis,
ecp=molecule.ecp,
symmetry=False,
uhf=molecule.uhf,
frozen_orbitals=molecule.frozen_orbitals)

self.init_mo_coeff = molecule.mo_coeff
self.extra_nuc_energy = 0. if not hasattr(molecule.solver, "charges") else self.molecule.solver.ext_pot.computeNuclearEnergy(self.molecule.solver.mol)
self.basis = molecule.basis

def simulate(self):
Expand Down Expand Up @@ -212,9 +215,14 @@ def simulate(self):

self.backend.set_options({'basis': self.basis, 'frozen_docc': [self.n_frozen_occ], 'frozen_uocc': [self.n_frozen_vir],
'qc_module': 'ccenergy', 'reference': self.ref})
energy, self.ccwfn = self.backend.energy('ccsd', molecule=self.molecule.solver.mol,
basis=self.basis, return_wfn=True, ref_wfn=wfn)
return energy
if hasattr(self.molecule, "charges") and self.backend.__version__ >= "1.6":
energy, self.ccwfn = self.backend.energy('ccsd', molecule=self.molecule.solver.mol,
basis=self.basis, return_wfn=True, ref_wfn=wfn,
external_potentials=self.molecule.solver.external_potentials)
else:
energy, self.ccwfn = self.backend.energy('ccsd', molecule=self.molecule.solver.mol,
basis=self.basis, return_wfn=True, ref_wfn=wfn)
return energy + self.extra_nuc_energy

def get_rdm(self):
"""Compute the Full CI 1- and 2-particle reduced density matrices.
Expand Down
16 changes: 15 additions & 1 deletion tangelo/algorithms/classical/fci_solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,12 @@ def __init__(self, molecule: SecondQuantizedMolecule):
self.backend.core.clean_variables()
self.ciwfn = None
self.degenerate_mo_energies = False
self.extra_nuc_energy = 0
if isinstance(molecule.solver, IntegralSolverPsi4) and not molecule.symmetry:
self.molecule = molecule
if hasattr(molecule.solver, "chrgfield"):
self.chrgfield = molecule.solver.chrgfield
self.extra_nuc_energy = self.molecule.solver.ext_pot.computeNuclearEnergy(self.molecule.solver.mol)
else:
self.degenerate_mo_energies = np.any(np.isclose(molecule.mo_energies[1:], molecule.mo_energies[:-1]))
self.molecule = SecondQuantizedMolecule(xyz=molecule.xyz, q=molecule.q, spin=molecule.spin,
Expand Down Expand Up @@ -210,10 +214,20 @@ def simulate(self):
for swap_op in swap_ops:
wfn.Ca().rotate_columns(0, swap_op[0], swap_op[1], np.deg2rad(90))

if hasattr(self, "chrgfield"):
# TODO: Remove support for older version.
if self.backend.__version__ < "1.6":
self.backend.core.set_global_option_python('EXTERN', self.chrgfield.extern)
else:
energy, self.ciwfn = self.backend.energy('fci', molecule=self.molecule.solver.mol,
basis=self.basis, return_wfn=True,
ref_wfn=wfn, external_potentials=self.molecule.solver.external_potentials)
return energy + self.extra_nuc_energy

energy, self.ciwfn = self.backend.energy('fci', molecule=self.molecule.solver.mol,
basis=self.basis, return_wfn=True,
ref_wfn=wfn)
return energy
return energy + self.extra_nuc_energy

def get_rdm(self):
"""Compute the Full CI 1- and 2-particle reduced density matrices.
Expand Down
9 changes: 3 additions & 6 deletions tangelo/algorithms/projective/quantum_imaginary_time.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
from tangelo.toolboxes.operators.operators import FermionOperator, QubitOperator
from tangelo.toolboxes.qubit_mappings.mapping_transform import fermion_to_qubit_mapping
from tangelo.toolboxes.ansatz_generator._general_unitary_cc import uccgsd_generator as uccgsd_pool
from tangelo.toolboxes.operators import qubitop_to_qubitham
from tangelo.toolboxes.qubit_mappings.statevector_mapping import get_reference_circuit
from tangelo.linq import Circuit, get_backend

Expand Down Expand Up @@ -128,7 +127,7 @@ def build(self):
up_then_down=self.up_then_down,
spin=0)

self.qubit_hamiltonian = qubitop_to_qubitham(qubit_op, self.qubit_mapping, self.up_then_down)
self.qubit_hamiltonian = qubit_op

# Getting the pool of operators for the ansatz. If more functionalities
# are added, this part must be modified and generalized.
Expand Down Expand Up @@ -179,10 +178,8 @@ def build(self):
for term in self.pool_operators:
self.pool_qubit_op += term

self.qubit_operator = self.qubit_hamiltonian.to_qubitoperator()

# Obtain all qubit terms that need to be measured
self.pool_h = [element*self.qubit_operator for element in self.pool_operators]
self.pool_h = [element*self.qubit_hamiltonian for element in self.pool_operators]
self.pool_pool = [[element1*element2 for element2 in self.pool_operators] for element1 in self.pool_operators]

# Obtain initial state preparation circuit
Expand Down Expand Up @@ -294,7 +291,7 @@ def energy_expectation(self, backend):
float: energy computed by the backend
"""
circuit = Circuit(n_qubits=self.final_circuit.width) if self.use_statevector else self.final_circuit
energy = backend.get_expectation_value(self.qubit_hamiltonian.to_qubitoperator(),
energy = backend.get_expectation_value(self.qubit_hamiltonian,
circuit,
initial_statevector=self.final_statevector)
return energy
Expand Down
18 changes: 9 additions & 9 deletions tangelo/algorithms/variational/iqcc_ilc_solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,21 +256,21 @@ def _update_ilc_solver(self, e_ilc):
if self.compress_qubit_ham:
self.ilc_ansatz.qubit_ham.frobenius_norm_compression(self.compress_eps, n_qubits)

# set dis, acs, and var_params to none to rebuild the dis & acs and initialize new parameters
self.ilc_ansatz.dis = None
self.ilc_ansatz.acs = None
self.ilc_ansatz.var_params = None
self.ilc_ansatz.build_circuit()

self.vqe_solver.qubit_hamiltonian = self.ilc_ansatz.qubit_ham
self.vqe_solver.initial_var_params = self.ilc_ansatz.var_params

if self.iteration == self.max_ilc_iter:
self.terminate_ilc = True
self.final_optimal_qmf_params = optimal_qmf_var_params
self.final_optimal_ilc_params = optimal_ilc_var_params
if self.verbose:
print(f"Terminating the ILC-VQE solver after {self.max_ilc_iter} iterations.")
else:
# Set dis, acs, and var_params to None to rebuild the dis & acs and initialize new parameters
self.ilc_ansatz.dis = None
self.ilc_ansatz.acs = None
self.ilc_ansatz.var_params = None
self.ilc_ansatz.build_circuit()

self.vqe_solver.qubit_hamiltonian = self.ilc_ansatz.qubit_ham
self.vqe_solver.initial_var_params = self.ilc_ansatz.var_params

def _update_qcc_solver(self, e_iqcc_ilc):
"""Updates after the final QCC energy evaluation with the final ILC dressed
Expand Down
12 changes: 8 additions & 4 deletions tangelo/linq/circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,10 +291,13 @@ def get_entangled_indices(self):

return entangled_indices

def split(self):
def split(self, trim_qubits=True):
""" Split a circuit featuring unentangled qubit subsets into as many circuit objects.
Each circuit only contains the gate operations targeting the qubit indices in its subsets.
Args:
trim_qubits (bool): Trim qubits on each circuit object and reindex to lowest value, Default: True
Returns:
list of Circuit: list of resulting circuits
"""
Expand All @@ -308,9 +311,10 @@ def split(self):
separate_circuits[i].add_gate(g)
break

# Trim unnecessary indices in the new circuits
for c in separate_circuits:
c.trim_qubits()
if trim_qubits:
# Trim unnecessary indices in the new circuits
for c in separate_circuits:
c.trim_qubits()
return separate_circuits

def stack(self, *other_circuits):
Expand Down
5 changes: 3 additions & 2 deletions tangelo/linq/qpu_connection/ibm_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def get_backend_info(self):
""" Return configuration information for each device found on the service """
return {b.name: b.configuration() for b in self.service.backends()}

def job_submit(self, program, backend_name, n_shots, circuits, operators=None, runtime_options=None):
def job_submit(self, program, backend_name, n_shots, circuits, operators=None, runtime_options=None, instance=None):
""" Submit job, return job ID.
Args:
Expand All @@ -55,13 +55,14 @@ def job_submit(self, program, backend_name, n_shots, circuits, operators=None, r
circuits (Circuit | List[Circuit]): Tangelo circuit(s)
operators (QubitOperator | List[QubitOperator]) : Optional, qubit operators for computing expectation values
runtime_options (dict): Optional, extra keyword arguments for options supported in qiskit-runtime.
instance (str): Optional, desired IBM service instance in the "hub/group/project" format. Default is likely to send to "ibm-q/open/main"
Returns:
str: string representing the job id
"""

# Set up options and intermediary Qiskit runtime objects
backend = self.service.backend(backend_name)
backend = self.service.backend(backend_name, instance=instance)
session = Session(service=self.service, backend=backend)

if runtime_options is None:
Expand Down
9 changes: 9 additions & 0 deletions tangelo/linq/tests/test_circuits.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,15 @@ def test_split_circuit(self):
self.assertTrue(c2 == Circuit([Gate("CSWAP", target=[0, 2], control=[1])]))
self.assertTrue(c3 == Circuit([Gate("H", target=0)]))

c = Circuit([Gate("CSWAP", target=[2, 5], control=[0]),
Gate("CSWAP", target=[3, 7], control=[4]),
Gate("H", 6)])
c1, c2, c3 = c.split(trim_qubits=False)

self.assertTrue(c1 == Circuit([Gate("CSWAP", target=[2, 5], control=[0])]))
self.assertTrue(c2 == Circuit([Gate("CSWAP", target=[3, 7], control=[4])]))
self.assertTrue(c3 == Circuit([Gate("H", target=6)]))

def test_stack_circuits(self):
""" Test circuit stacking """

Expand Down
2 changes: 1 addition & 1 deletion tangelo/problem_decomposition/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@

from .dmet.dmet_problem_decomposition import DMETProblemDecomposition
from .oniom.oniom_problem_decomposition import ONIOMProblemDecomposition
from .incremental.mifno_helper import MIFNOHelper
from .incremental.incremental_helper import MethodOfIncrementsHelper
Loading

0 comments on commit 0d707f8

Please sign in to comment.