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

Commit

Permalink
move to circuit.lib and use tuple
Browse files Browse the repository at this point in the history
- move the initial state circuit to chemistry.circuit.library
- globally replace num_particles by a tuple instead of list of integers
  • Loading branch information
Cryoris committed Oct 27, 2020
1 parent 888047a commit 608aade
Show file tree
Hide file tree
Showing 35 changed files with 431 additions and 225 deletions.
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,12 +223,15 @@ from qiskit.aqua.components.optimizers import L_BFGS_B
optimizer = L_BFGS_B()

# setup the initial state for the variational form
from qiskit.chemistry.components.initial_states import HartreeFock
from qiskit.chemistry.circuit.library import HartreeFock
init_state = HartreeFock(num_spin_orbitals, num_particles)

# setup the variational form for VQE
from qiskit.circuit.library import TwoLocal
var_form = TwoLocal(num_qubits, ['ry', 'rz'], 'cz', initial_state=init_state)
var_form = TwoLocal(num_qubits, ['ry', 'rz'], 'cz')

# add the initial state
var_form.compose(init_state, front=True)

# setup and run VQE
from qiskit.aqua.algorithms import VQE
Expand Down
2 changes: 1 addition & 1 deletion qiskit/aqua/operators/legacy/weighted_pauli_operator.py
Original file line number Diff line number Diff line change
Expand Up @@ -1250,7 +1250,7 @@ def two_qubit_reduction(operator, num_particles):
"Return the empty operator back.")
return operator

if isinstance(num_particles, list):
if isinstance(num_particles, (tuple, list)):
num_alpha = num_particles[0]
num_beta = num_particles[1]
else:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from ....components.variational_forms import UCCSD
from ....transformations import Transformation
from ....transformations.fermionic_transformation import FermionicTransformation
from ....components.initial_states import HartreeFock
from ....circuit.library import HartreeFock

from .minimum_eigensolver_factory import MinimumEigensolverFactory

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from qiskit.aqua.algorithms import MinimumEigensolver, VQE
from qiskit.aqua.operators import Z2Symmetries
from qiskit.chemistry import QiskitChemistryError
from qiskit.chemistry.components.initial_states import HartreeFock
from qiskit.chemistry.circuit.library import HartreeFock
from qiskit.chemistry.components.variational_forms import UCCSD
from qiskit.chemistry.core import (Hamiltonian, TransformationType, QubitMappingType,
ChemistryOperator, MolecularGroundStateResult)
Expand Down
39 changes: 39 additions & 0 deletions qiskit/chemistry/circuit/library/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# This code is part of Qiskit.
#
# (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
# 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.

"""
===================================================================
Chemistry Circuit Library (:mod:`qiskit.chemistry.circuit.library`)
===================================================================
A collection of circuits used as building blocks or inputs of algorithms in chemistry.
.. currentmodule:: qiskit.chemistry.circuit.library
Initial states
==============
.. autosummary::
:toctree: ../stubs/
:nosignatures:
HartreeFock
VSCF
"""

from .initial_states import (
HartreeFock,
VSCF
)

__all__ = ['HartreeFock', 'VSCF']
18 changes: 18 additions & 0 deletions qiskit/chemistry/circuit/library/initial_states/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# This code is part of Qiskit.
#
# (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
# 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.

"""Initial state circuits."""

from .hartree_fock import HartreeFock
from .vscf import VSCF

__all__ = ['HartreeFock', 'VSCF']
116 changes: 116 additions & 0 deletions qiskit/chemistry/circuit/library/initial_states/hartree_fock.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# 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.

"""Hartree-Fock initial state."""

import warnings
from typing import Optional, Union, List, Tuple
import logging
import numpy as np
from qiskit import QuantumRegister, QuantumCircuit
from qiskit.aqua.utils.validation import validate_min, validate_in_set

logger = logging.getLogger(__name__)


class HartreeFock(QuantumCircuit):
"""A Hartree-Fock initial state."""

def __init__(self,
num_orbitals: int,
num_particles: Union[Tuple[int, int], int],
qubit_mapping: str = 'parity',
two_qubit_reduction: bool = True,
sq_list: Optional[List[int]] = None) -> None:
"""
Args:
num_orbitals: number of spin orbitals, has a min. value of 1.
num_particles: number of particles, if it is a list, the first number
is alpha and the second number if beta.
qubit_mapping: mapping type for qubit operator
two_qubit_reduction: flag indicating whether or not two qubit is reduced
sq_list: position of the single-qubit operators that
anticommute with the cliffords
Raises:
ValueError: wrong setting in num_particles and num_orbitals.
ValueError: wrong setting for computed num_qubits and supplied num_qubits.
"""
# validate the input
validate_min('num_orbitals', num_orbitals, 1)
validate_in_set('qubit_mapping', qubit_mapping,
{'jordan_wigner', 'parity', 'bravyi_kitaev'})

if qubit_mapping != 'parity' and two_qubit_reduction:
warnings.warn('two_qubit_reduction only works with parity qubit mapping '
'but you have %s. We switch two_qubit_reduction '
'to False.' % qubit_mapping)
two_qubit_reduction = False

# get the bitstring encoding the Hartree Fock state
bitstr = _build_bitstr(num_orbitals, num_particles, qubit_mapping,
two_qubit_reduction, sq_list)

# construct the circuit
qr = QuantumRegister(len(bitstr), 'q')
super().__init__(qr, name='HF')

# add gates in the right positions
for i, bit in enumerate(reversed(bitstr)):
if bit:
self.x(i)


def _build_bitstr(num_orbitals, num_particles, qubit_mapping, two_qubit_reduction=True,
sq_list=None):
if isinstance(num_particles, tuple):
num_alpha, num_beta = num_particles
else:
logger.info('We assume that the number of alphas and betas are the same.')
num_alpha = num_beta = num_particles // 2

num_particles = num_alpha + num_beta

if num_particles > num_orbitals:
raise ValueError('# of particles must be less than or equal to # of orbitals.')

half_orbitals = num_orbitals // 2
bitstr = np.zeros(num_orbitals, np.bool)
bitstr[-num_alpha:] = True
bitstr[-(half_orbitals + num_beta):-half_orbitals] = True

if qubit_mapping == 'parity':
new_bitstr = bitstr.copy()

t_r = np.triu(np.ones((num_orbitals, num_orbitals)))
new_bitstr = t_r.dot(new_bitstr.astype(np.int)) % 2 # pylint: disable=no-member

bitstr = np.append(new_bitstr[1:half_orbitals], new_bitstr[half_orbitals + 1:]) \
if two_qubit_reduction else new_bitstr

elif qubit_mapping == 'bravyi_kitaev':
binary_superset_size = int(np.ceil(np.log2(num_orbitals)))
beta = 1
basis = np.asarray([[1, 0], [0, 1]])
for _ in range(binary_superset_size):
beta = np.kron(basis, beta)
beta[0, :] = 1
start_idx = beta.shape[0] - num_orbitals
beta = beta[start_idx:, start_idx:]
new_bitstr = beta.dot(bitstr.astype(int)) % 2
bitstr = new_bitstr.astype(np.bool)

if sq_list is not None:
sq_list = [len(bitstr) - 1 - position for position in sq_list]
bitstr = np.delete(bitstr, sq_list)

return bitstr.astype(np.bool)
60 changes: 60 additions & 0 deletions qiskit/chemistry/circuit/library/initial_states/vscf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# This code is part of Qiskit.
#
# (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
# 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.

"""Initial state for vibrational modes."""

from typing import List

import numpy as np

from qiskit import QuantumRegister, QuantumCircuit


class VSCF(QuantumCircuit):
r"""Initial state for vibrational modes.
Creates an occupation number vector as defined in [1].
As example, for 2 modes with 4 modals per mode it creates: :math:`|1000 1000\rangle`.
References:
[1] Ollitrault Pauline J., Chemical science 11 (2020): 6842-6855.
"""

def __init__(self, basis: List[int]) -> None:
"""
Args:
basis: Is a list defining the number of modals per mode. E.g. for a 3 modes system
with 4 modals per mode basis = [4,4,4]
"""
# get the bitstring encoding initial state
bitstr = _build_bitstr(basis)

# construct the circuit
qr = QuantumRegister(len(bitstr), 'q')
super().__init__(qr, name='VSCF')

# add gates in the right positions
for i, bit in enumerate(reversed(bitstr)):
if bit:
self.x(i)


def _build_bitstr(basis):
num_qubits = sum(basis)
bitstr = np.zeros(num_qubits, np.bool)
count = 0
for modal in basis:
bitstr[num_qubits - count - 1] = True
count += modal

return bitstr
Loading

0 comments on commit 608aade

Please sign in to comment.