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

Uncertainty models using circuits #908

Merged
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

""" The Multivariate Variational Distribution. """
"""The Multivariate Variational Distribution."""

import warnings
from typing import Optional, List, Union
import numpy as np

Expand All @@ -25,13 +26,11 @@


class MultivariateVariationalDistribution(MultivariateDistribution):
"""
The Multivariate Variational Distribution.
"""
"""The Multivariate Variational Distribution."""

def __init__(self,
num_qubits: Union[List[int], np.ndarray],
var_form: VariationalForm,
var_form: Union[QuantumCircuit, VariationalForm],
params: Union[List[float], np.ndarray],
low: Optional[Union[List[float], np.ndarray]] = None,
high: Optional[Union[List[float], np.ndarray]] = None) -> None:
Expand All @@ -49,26 +48,47 @@ def __init__(self,
high = np.ones(len(num_qubits))
self._num_qubits = num_qubits
self._var_form = var_form
# fix the order of the parameters in the circuit
if isinstance(self._var_form, QuantumCircuit):
self._var_form_params = list(self._var_form.parameters)
else:
warnings.warn('The VariationalForm type is deprecated as argument of the '
'UnivariateVariationalDistribution as of 0.7.0 and will be removed no '
'earlier than 3 months after the release. You should pass an object '
'of type QuantumCircuit instead (see qiskit.circuit.library for a '
'collection of suitable objects).',
DeprecationWarning, stacklevel=2)

self.params = params
probabilities = np.zeros(2 ** sum(num_qubits))
super().__init__(num_qubits, probabilities, low, high)
self._var_form = var_form
self.params = params

def build(self, qc, q, q_ancillas=None, params=None):
circuit_var_form = self._var_form.construct_circuit(self.params)
if isinstance(self._var_form, QuantumCircuit):
param_dict = dict(zip(self._var_form_params, self.params))
circuit_var_form = self._var_form.assign_parameters(param_dict)
else:
circuit_var_form = self._var_form.construct_circuit(self.params)

qc.append(circuit_var_form.to_instruction(), q)

def set_probabilities(self, quantum_instance):
"""
Set Probabilities
"""Set Probabilities

Args:
quantum_instance (QuantumInstance): Quantum Instance
"""
q_ = QuantumRegister(self._num_qubits, name='q')
qc_ = QuantumCircuit(q_)
circuit_var_form = self._var_form.construct_circuit(self.params, q_)
qc_ += circuit_var_form
if isinstance(self._var_form, QuantumCircuit):
param_dict = dict(zip(self._var_form_params, self.params))
circuit_var_form = self._var_form.assign_parameters(param_dict)
else:
circuit_var_form = self._var_form.construct_circuit(self.params)

qc_.append(circuit_var_form.to_instruction(), qc_.qubits)

if quantum_instance.is_statevector:
pass
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,24 @@
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

"""
The Univariate Variational Distribution.
"""
"""The Univariate Variational Distribution."""

import warnings
from typing import Union, List
import numpy as np

from qiskit import ClassicalRegister
from qiskit import ClassicalRegister, QuantumCircuit
from qiskit.aqua.components.variational_forms import VariationalForm
from qiskit.aqua.utils.validation import validate_min
from .univariate_distribution import UnivariateDistribution


class UnivariateVariationalDistribution(UnivariateDistribution):
"""
The Univariate Variational Distribution.
"""
"""The Univariate Variational Distribution."""

def __init__(self,
num_qubits: int,
var_form: VariationalForm,
var_form: Union[QuantumCircuit, VariationalForm],
params: Union[List[float], np.ndarray],
low: float = 0,
high: float = 1) -> None:
Expand All @@ -47,6 +44,18 @@ def __init__(self,
validate_min('num_qubits', num_qubits, 1)
self._num_qubits = num_qubits
self._var_form = var_form

# fix the order of the parameters in the circuit
if isinstance(self._var_form, QuantumCircuit):
self._var_form_params = list(self._var_form.parameters)
else:
warnings.warn('The VariationalForm type is deprecated as argument of the '
'UnivariateVariationalDistribution as of 0.7.0 and will be removed no '
'earlier than 3 months after the release. You should pass an object '
'of type QuantumCircuit instead (see qiskit.circuit.library for a '
'collection of suitable objects).',
DeprecationWarning, stacklevel=2)

self.params = params
if isinstance(num_qubits, int):
probabilities = np.zeros(2 ** num_qubits)
Expand All @@ -57,16 +66,25 @@ def __init__(self,
super().__init__(num_qubits, probabilities, low, high)

def build(self, qc, q, q_ancillas=None, params=None):
circuit_var_form = self._var_form.construct_circuit(self.params)
if isinstance(self._var_form, QuantumCircuit):
param_dict = dict(zip(self._var_form_params, self.params))
circuit_var_form = self._var_form.assign_parameters(param_dict)
else:
circuit_var_form = self._var_form.construct_circuit(self.params)

qc.append(circuit_var_form.to_instruction(), q)

def set_probabilities(self, quantum_instance):
"""
Set Probabilities
"""Set Probabilities
Args:
quantum_instance (QuantumInstance): Quantum instance
"""
qc_ = self._var_form.construct_circuit(self.params)
if isinstance(self._var_form, QuantumCircuit):
param_dict = dict(zip(self._var_form_params, self.params))
qc_ = self._var_form.assign_parameters(param_dict)
else:
qc_ = self._var_form.construct_circuit(self.params)

# q_ = QuantumRegister(self._num_qubits)
# qc_ = QuantumCircuit(q_)
Expand Down
38 changes: 29 additions & 9 deletions test/aqua/test_qgan.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@
# 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.
# =============================================================================

""" Test QGAN """

import unittest
from test.aqua import QiskitAquaTestCase

import unittest
from ddt import ddt, data
from qiskit import QuantumCircuit, QuantumRegister
from qiskit.circuit import ParameterVector
from qiskit.aqua.components.uncertainty_models import (UniformDistribution,
UnivariateVariationalDistribution)
from qiskit.aqua.components.variational_forms import RY
Expand All @@ -28,8 +30,10 @@
from qiskit import BasicAer


@ddt
class TestQGAN(QiskitAquaTestCase):
""" Test QGAN """

def setUp(self):
super().setUp()
self.seed = 7
Expand Down Expand Up @@ -86,23 +90,39 @@ def setUp(self):
# Set generator's initial parameters
init_params = aqua_globals.random.rand(var_form._num_parameters) * 2 * 1e-2
# Set generator circuit
g_circuit = UnivariateVariationalDistribution(sum(num_qubits), var_form, init_params,
low=self._bounds[0],
high=self._bounds[1])
# Set quantum generator
self.qgan.set_generator(generator_circuit=g_circuit)
self.g_var_form = UnivariateVariationalDistribution(sum(num_qubits), var_form, init_params,
low=self._bounds[0],
high=self._bounds[1])

def test_sample_generation(self):
theta = ParameterVector('θ', var_form.num_parameters)
var_form = var_form.construct_circuit(theta)
self.g_circuit = UnivariateVariationalDistribution(sum(num_qubits), var_form, init_params,
low=self._bounds[0],
high=self._bounds[1])

@data(False, True)
def test_sample_generation(self, use_circuits):
""" sample generation test """
if use_circuits:
self.qgan.set_generator(generator_circuit=self.g_circuit)
else:
self.qgan.set_generator(generator_circuit=self.g_var_form)

_, weights_statevector = \
self.qgan._generator.get_output(self.qi_statevector, shots=100)
samples_qasm, weights_qasm = self.qgan._generator.get_output(self.qi_qasm, shots=100)
samples_qasm, weights_qasm = zip(*sorted(zip(samples_qasm, weights_qasm)))
for i, weight_q in enumerate(weights_qasm):
self.assertAlmostEqual(weight_q, weights_statevector[i], delta=0.1)

def test_qgan_training(self):
@data(False, True)
def test_qgan_training(self, use_circuits):
""" qgan training test """
if use_circuits:
self.qgan.set_generator(generator_circuit=self.g_circuit)
else:
self.qgan.set_generator(generator_circuit=self.g_var_form)

trained_statevector = self.qgan.run(self.qi_statevector)
trained_qasm = self.qgan.run(self.qi_qasm)
self.assertAlmostEqual(trained_qasm['rel_entr'], trained_statevector['rel_entr'], delta=0.1)
Expand Down
13 changes: 12 additions & 1 deletion test/finance/test_european_call_expected_value.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@
""" Test European Call Expected Value uncertainty problem """

from test.finance import QiskitFinanceTestCase
from ddt import ddt, data

import numpy as np

from qiskit import BasicAer
from qiskit.circuit import ParameterVector
from qiskit.aqua import aqua_globals, QuantumInstance
from qiskit.aqua.algorithms import AmplitudeEstimation
from qiskit.aqua.components.initial_states import Custom
Expand All @@ -28,6 +30,7 @@
from qiskit.finance.components.uncertainty_problems import EuropeanCallExpectedValue


@ddt
class TestEuropeanCallExpectedValue(QiskitFinanceTestCase):
"""Tests European Call Expected Value uncertainty problem """

Expand All @@ -36,7 +39,8 @@ def setUp(self):
self.seed = 457
aqua_globals.random_seed = self.seed

def test_ecev(self):
@data(False, True)
def test_ecev(self, use_circuits):
""" European Call Expected Value test """
bounds = np.array([0., 7.])
num_qubits = [3]
Expand All @@ -54,10 +58,17 @@ def test_ecev(self):
var_form = RY(int(np.sum(num_qubits)), depth=1,
initial_state=init_distribution,
entangler_map=entangler_map, entanglement_gate='cz')
if use_circuits:
theta = ParameterVector('θ', var_form.num_parameters)
var_form = var_form.construct_circuit(theta)

uncertainty_model = UnivariateVariationalDistribution(
int(sum(num_qubits)), var_form, g_params,
low=bounds[0], high=bounds[1])

if use_circuits:
uncertainty_model._var_form_params = theta

strike_price = 2
c_approx = 0.25
european_call = EuropeanCallExpectedValue(uncertainty_model,
Expand Down