Skip to content
This repository has been archived by the owner on Dec 7, 2021. It is now read-only.

Commit

Permalink
Refactor Chemistry Drivers
Browse files Browse the repository at this point in the history
  • Loading branch information
manoelmarques committed Oct 1, 2020
1 parent b45f952 commit 1266023
Show file tree
Hide file tree
Showing 17 changed files with 669 additions and 91 deletions.
3 changes: 3 additions & 0 deletions qiskit/chemistry/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@
BosonicOperator
FermionicOperator
Molecule
QMolecule
MP2Info
Expand All @@ -155,6 +156,7 @@
"""

from .qiskit_chemistry_error import QiskitChemistryError
from .molecule import Molecule
from .qmolecule import QMolecule
from .bosonic_operator import BosonicOperator
from .fermionic_operator import FermionicOperator
Expand All @@ -163,6 +165,7 @@
set_qiskit_chemistry_logging)

__all__ = ['QiskitChemistryError',
'Molecule',
'QMolecule',
'BosonicOperator',
'FermionicOperator',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@
from qiskit.chemistry.components.variational_forms import UCCSD
from qiskit.chemistry.core import (Hamiltonian, TransformationType, QubitMappingType,
ChemistryOperator, MolecularGroundStateResult)
from qiskit.chemistry.drivers import BaseDriver
from qiskit.chemistry.drivers import IntegralsDriver


class MolecularGroundStateEnergy:
""" Molecular ground state energy chemistry application """

def __init__(self,
driver: BaseDriver,
driver: IntegralsDriver,
solver: Optional[MinimumEigensolver] = None,
transformation: TransformationType = TransformationType.FULL,
qubit_mapping: QubitMappingType = QubitMappingType.PARITY,
Expand Down Expand Up @@ -68,12 +68,12 @@ def __init__(self,
self._z2symmetry_reduction = z2symmetry_reduction

@property
def driver(self) -> BaseDriver:
def driver(self) -> IntegralsDriver:
""" Returns chemistry driver """
return self._driver

@driver.setter
def driver(self, driver: BaseDriver) -> None:
def driver(self, driver: IntegralsDriver) -> None:
self._driver = driver

@property
Expand Down
12 changes: 8 additions & 4 deletions qiskit/chemistry/drivers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
:nosignatures:
BaseDriver
IntegralsDriver
Driver Common
=============
Expand All @@ -59,8 +60,8 @@
:toctree: ../stubs/
:nosignatures:
UnitsType
HFMethodType
UnitsType
BasisType
InitialGuess
Expand Down Expand Up @@ -111,17 +112,20 @@
"""
from ._basedriver import BaseDriver, UnitsType, HFMethodType

from .base_driver import BaseDriver
from .integrals_driver import IntegralsDriver, UnitsType, HFMethodType
from .fcidumpd import FCIDumpDriver
from .gaussiand import GaussianDriver, GaussianLogDriver, GaussianLogResult
from .hdf5d import HDF5Driver
from .psi4d import PSI4Driver
from .pyquanted import PyQuanteDriver, BasisType
from .pyscfd import PySCFDriver, InitialGuess

__all__ = ['BaseDriver',
__all__ = ['HFMethodType',
'BaseDriver',
'IntegralsDriver',
'UnitsType',
'HFMethodType',
'FCIDumpDriver',
'GaussianDriver',
'GaussianLogDriver',
Expand Down
23 changes: 23 additions & 0 deletions qiskit/chemistry/drivers/base_driver.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# This code is part of Qiskit.
#
# (C) Copyright IBM 2018, 2020.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

"""
This module implements the abstract base class for driver modules.
"""

from abc import ABC


class BaseDriver(ABC):
"""
Base class for Qiskit's chemistry drivers.
"""
7 changes: 4 additions & 3 deletions qiskit/chemistry/drivers/fcidumpd/fcidumpdriver.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@
"""FCIDump Driver."""

from typing import List, Optional
from qiskit.chemistry.drivers import BaseDriver
from qiskit.chemistry import QiskitChemistryError, QMolecule
from ..base_driver import BaseDriver
from ...qiskit_chemistry_error import QiskitChemistryError
from ...qmolecule import QMolecule
from .dumper import dump
from .parser import parse

Expand Down Expand Up @@ -70,7 +71,7 @@ def run(self) -> QMolecule:
q_mol.nuclear_repulsion_energy = fcidump_data.get('ecore', None)
q_mol.num_orbitals = fcidump_data.get('NORB')
q_mol.multiplicity = fcidump_data.get('MS2', 0) + 1
q_mol.charge = 0 # ensures QMolecule.log() works
q_mol.molecular_charge = 0 # ensures QMolecule.log() works
q_mol.num_beta = (fcidump_data.get('NELEC') - (q_mol.multiplicity - 1)) // 2
q_mol.num_alpha = fcidump_data.get('NELEC') - q_mol.num_beta
if self.atoms is not None:
Expand Down
5 changes: 3 additions & 2 deletions qiskit/chemistry/drivers/gaussiand/gaussian_log_driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,15 @@
from typing import Union, List
import logging

from qiskit.chemistry import QiskitChemistryError
from ..base_driver import BaseDriver
from ...qiskit_chemistry_error import QiskitChemistryError
from .gaussian_utils import check_valid, run_g16
from .gaussian_log_result import GaussianLogResult

logger = logging.getLogger(__name__)


class GaussianLogDriver:
class GaussianLogDriver(BaseDriver):
""" Gaussian™ 16 log driver.
Qiskit chemistry driver using the Gaussian™ 16 program that provides the log
Expand Down
36 changes: 28 additions & 8 deletions qiskit/chemistry/drivers/gaussiand/gaussiandriver.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,16 @@
import os
import tempfile
import numpy as np
from qiskit.chemistry import QMolecule, QiskitChemistryError
from qiskit.chemistry.drivers import BaseDriver
from ..integrals_driver import IntegralsDriver
from ...qiskit_chemistry_error import QiskitChemistryError
from ...molecule import Molecule
from ...qmolecule import QMolecule
from .gaussian_utils import check_valid, run_g16

logger = logging.getLogger(__name__)


class GaussianDriver(BaseDriver):
class GaussianDriver(IntegralsDriver):
"""
Qiskit chemistry driver using the Gaussian™ 16 program.
Expand All @@ -40,17 +42,20 @@ class GaussianDriver(BaseDriver):
"""

def __init__(self,
config: Union[str, List[str]] =
config: Union[str, List[str], Molecule] =
'# rhf/sto-3g scf(conventional)\n\n'
'h2 molecule\n\n0 1\nH 0.0 0.0 0.0\nH 0.0 0.0 0.735\n\n') -> None:
"""
Args:
config: A molecular configuration conforming to Gaussian™ 16 format
config: A molecular configuration conforming to Gaussian™ 16 format or
a molecule object
Raises:
QiskitChemistryError: Invalid Input
"""
GaussianDriver._check_valid()
if not isinstance(config, list) and not isinstance(config, str):
if not isinstance(config, str) and \
not isinstance(config, list) and \
not isinstance(config, Molecule):
raise QiskitChemistryError("Invalid input for Gaussian Driver '{}'".format(config))

if isinstance(config, list):
Expand All @@ -63,8 +68,23 @@ def __init__(self,
def _check_valid():
check_valid()

@staticmethod
def _from_molecule_to_str(mol: Molecule) -> str:
cfg1 = '# {}/{} scf(conventional)\n\n'.format(
mol.hf_method, mol.basis_set)
name = ''.join([name for (name, _) in mol.geometry])
geom = '\n'.join([name + ' ' + ' '.join(map(str, coord))
for (name, coord) in mol.geometry])
cfg2 = '{} molecule\n\n{} {}\n{}\n\n'.format(
name, mol.charge, mol.multiplicity, geom)
return cfg1 + cfg2

def run(self) -> QMolecule:
cfg = self._config
if isinstance(self._config, Molecule):
cfg = GaussianDriver._from_molecule_to_str(self._config)
else:
cfg = self._config

while not cfg.endswith('\n\n'):
cfg += '\n'

Expand Down Expand Up @@ -93,7 +113,7 @@ def run(self) -> QMolecule:
logger.warning("Failed to remove MatrixElement file %s", fname)

q_mol.origin_driver_name = 'GAUSSIAN'
q_mol.origin_driver_config = self._config
q_mol.origin_driver_config = cfg
return q_mol

@staticmethod
Expand Down
13 changes: 11 additions & 2 deletions qiskit/chemistry/drivers/hdf5d/hdf5driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@

import os
import logging
from qiskit.chemistry.drivers import BaseDriver
from qiskit.chemistry import QMolecule
from ..base_driver import BaseDriver
from ...qmolecule import QMolecule

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -48,6 +48,15 @@ def work_path(self, new_work_path):
self._work_path = new_work_path

def run(self) -> QMolecule:
"""
Runs driver to produce a QMolecule output.
Returns:
A QMolecule containing the molecular data.
Raises:
LookupError: file not found.
"""
hdf5_file = self._hdf5_input
if self.work_path is not None and not os.path.isabs(hdf5_file):
hdf5_file = os.path.abspath(os.path.join(self.work_path, hdf5_file))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This code is part of Qiskit.
#
# (C) Copyright IBM 2018, 2020.
# (C) Copyright IBM 2020.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
Expand All @@ -11,13 +11,14 @@
# that they have been altered from the originals.

"""
This module implements the abstract base class for driver modules.
This module implements the abstract base class for integral driver modules.
"""

from abc import ABC, abstractmethod
from abc import abstractmethod
from enum import Enum

from qiskit.chemistry import QMolecule
from ..qmolecule import QMolecule
from .base_driver import BaseDriver


class UnitsType(Enum):
Expand All @@ -33,15 +34,11 @@ class HFMethodType(Enum):
UHF = 'uhf'


class BaseDriver(ABC):
class IntegralsDriver(BaseDriver):
"""
Base class for Qiskit's chemistry drivers.
Base class for Qiskit's chemistry integral drivers.
"""

@abstractmethod
def __init__(self):
pass

@abstractmethod
def run(self) -> QMolecule:
"""
Expand Down
37 changes: 29 additions & 8 deletions qiskit/chemistry/drivers/psi4d/psi4driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@
import logging
import sys
from shutil import which
from qiskit.chemistry import QMolecule, QiskitChemistryError
from qiskit.chemistry.drivers import BaseDriver
from ..integrals_driver import IntegralsDriver
from ...qiskit_chemistry_error import QiskitChemistryError
from ...molecule import Molecule
from ...qmolecule import QMolecule

logger = logging.getLogger(__name__)

Expand All @@ -29,25 +31,28 @@
PSI4_APP = which(PSI4)


class PSI4Driver(BaseDriver):
class PSI4Driver(IntegralsDriver):
"""
Qiskit chemistry driver using the PSI4 program.
See http://www.psicode.org/
"""

def __init__(self,
config: Union[str, List[str]] =
config: Union[str, List[str], Molecule] =
'molecule h2 {\n 0 1\n H 0.0 0.0 0.0\n H 0.0 0.0 0.735\n}\n\n'
'set {\n basis sto-3g\n scf_type pk\n reference rhf\n') -> None:
"""
Args:
config: A molecular configuration conforming to PSI4 format
config: A molecular configuration conforming to PSI4 format or
a molecule object
Raises:
QiskitChemistryError: Invalid Input
"""
self._check_valid()
if not isinstance(config, list) and not isinstance(config, str):
if not isinstance(config, str) and \
not isinstance(config, list) and \
not isinstance(config, Molecule):
raise QiskitChemistryError("Invalid input for PSI4 Driver '{}'".format(config))

if isinstance(config, list):
Expand All @@ -61,14 +66,30 @@ def _check_valid():
if PSI4_APP is None:
raise QiskitChemistryError("Could not locate {}".format(PSI4))

@staticmethod
def _from_molecule_to_str(mol: Molecule) -> str:
name = ''.join([name for (name, _) in mol.geometry])
geom = '\n'.join([name + ' ' + ' '.join(map(str, coord))
for (name, coord) in mol.geometry])
cfg1 = 'molecule {} {{\n {} {}\n {}\nno_com\nno_reorient\n}}\n\n'.format(
name, mol.charge, mol.multiplicity, geom)
cfg2 = 'set {{\n basis {}\n scf_type pk\n reference {}\n}}'.format(
mol.basis_set, mol.hf_method)
return cfg1 + cfg2

def run(self) -> QMolecule:
if isinstance(self._config, Molecule):
cfg = PSI4Driver._from_molecule_to_str(self._config)
else:
cfg = self._config

psi4d_directory = os.path.dirname(os.path.realpath(__file__))
template_file = psi4d_directory + '/_template.txt'
qiskit_chemistry_directory = os.path.abspath(os.path.join(psi4d_directory, '../..'))

molecule = QMolecule()

input_text = self._config + '\n'
input_text = cfg + '\n'
input_text += 'import sys\n'
syspath = '[\'' + qiskit_chemistry_directory + '\',\'' + '\',\''.join(sys.path) + '\']'

Expand Down Expand Up @@ -116,7 +137,7 @@ def run(self) -> QMolecule:
# remove internal file
_q_molecule.remove_file()
_q_molecule.origin_driver_name = 'PSI4'
_q_molecule.origin_driver_config = self._config
_q_molecule.origin_driver_config = cfg
return _q_molecule

@staticmethod
Expand Down
Loading

0 comments on commit 1266023

Please sign in to comment.