Example #1
0
    def test_ecev(self):
        """ European Call Expected Value test """
        bounds = np.array([0., 7.])
        num_qubits = [3]
        entangler_map = []
        for i in range(sum(num_qubits)):
            entangler_map.append([i, int(np.mod(i + 1, sum(num_qubits)))])

        g_params = [
            0.29399714, 0.38853322, 0.9557694, 0.07245791, 6.02626428,
            0.13537225
        ]
        # Set an initial state for the generator circuit
        init_dist = NormalDistribution(int(sum(num_qubits)),
                                       mu=1.,
                                       sigma=1.,
                                       low=bounds[0],
                                       high=bounds[1])
        init_distribution = np.sqrt(init_dist.probabilities)
        init_distribution = Custom(num_qubits=sum(num_qubits),
                                   state_vector=init_distribution)
        var_form = TwoLocal(int(np.sum(num_qubits)),
                            'ry',
                            'cz',
                            reps=1,
                            initial_state=init_distribution,
                            entanglement=entangler_map)

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

        strike_price = 2
        c_approx = 0.25
        european_call = EuropeanCallExpectedValue(uncertainty_model,
                                                  strike_price=strike_price,
                                                  c_approx=c_approx)

        uncertainty_model.set_probabilities(
            QuantumInstance(BasicAer.get_backend('statevector_simulator')))

        algo = AmplitudeEstimation(5, european_call)
        result = algo.run(
            quantum_instance=BasicAer.get_backend('statevector_simulator'))
        self.assertAlmostEqual(result['estimation'], 1.2580, places=4)
        self.assertAlmostEqual(result['max_probability'], 0.8785, places=4)
Example #2
0
    def test_ecev(self, use_circuits):
        """ European Call Expected Value test """
        if not use_circuits:
            # ignore deprecation warnings from the deprecation of VariationalForm as input for
            # the univariate variational distribution
            warnings.filterwarnings("ignore", category=DeprecationWarning)

        bounds = np.array([0., 7.])
        num_qubits = [3]
        entangler_map = []
        for i in range(sum(num_qubits)):
            entangler_map.append([i, int(np.mod(i + 1, sum(num_qubits)))])

        g_params = [
            0.29399714, 0.38853322, 0.9557694, 0.07245791, 6.02626428,
            0.13537225
        ]
        # Set an initial state for the generator circuit
        init_dist = NormalDistribution(int(sum(num_qubits)),
                                       mu=1.,
                                       sigma=1.,
                                       low=bounds[0],
                                       high=bounds[1])
        init_distribution = np.sqrt(init_dist.probabilities)
        init_distribution = Custom(num_qubits=sum(num_qubits),
                                   state_vector=init_distribution)
        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,
                                                  strike_price=strike_price,
                                                  c_approx=c_approx)

        uncertainty_model.set_probabilities(
            QuantumInstance(BasicAer.get_backend('statevector_simulator')))

        algo = AmplitudeEstimation(5, european_call)
        result = algo.run(
            quantum_instance=BasicAer.get_backend('statevector_simulator'))
        self.assertAlmostEqual(result['estimation'], 1.2580, places=4)
        self.assertAlmostEqual(result['max_probability'], 0.8785, places=4)

        if not use_circuits:
            warnings.filterwarnings(action="always",
                                    category=DeprecationWarning)
Example #3
0
    def __init__(self, n_normal, normal_max_value, p_zeros, rhos, i_normal=None, i_ps=None):
        """
        Constructor.

        The Gaussian Conditional Independence Model for Credit Risk
        Reference: https://arxiv.org/abs/1412.1183

        Args:
            n_normal (int): number of qubits to represent the latent normal random variable Z
            normal_max_value (float): min/max value to truncate the latent normal random variable Z
            p_zeros (list or array): standard default probabilities for each asset
            rhos (list or array): sensitivities of default probability of assets with respect to latent variable Z
            i_normal (list or array): indices of qubits to represent normal variable
            i_ps (list or array): indices of qubits to represent asset defaults
        """
        self.n_normal = n_normal
        self.normal_max_value = normal_max_value
        self.p_zeros = p_zeros
        self.rhos = rhos
        self.K = len(p_zeros)
        num_qubits = [n_normal] + [1]*self.K

        # set and store indices
        if i_normal is not None:
            self.i_normal = i_normal
        else:
            self.i_normal = range(n_normal)

        if i_ps is not None:
            self.i_ps = i_ps
        else:
            self.i_ps = range(n_normal, n_normal + self.K)

        # get normal (inverse) CDF and pdf
        def F(x): return norm.cdf(x)
        def F_inv(x): return norm.ppf(x)
        def f(x): return norm.pdf(x)

        # set low/high values
        low = [-normal_max_value] + [0]*self.K
        high = [normal_max_value] + [1]*self.K

        # call super constructor
        super().__init__(num_qubits, low=low, high=high)

        # create normal distribution
        self._normal = NormalDistribution(n_normal, 0, 1, -normal_max_value, normal_max_value)

        # create linear rotations for conditional defaults
        self._slopes = np.zeros(self.K)
        self._offsets = np.zeros(self.K)
        self._rotations = []
        for k in range(self.K):

            psi = F_inv(p_zeros[k]) / np.sqrt(1 - rhos[k])

            # compute slope / offset
            slope = -np.sqrt(rhos[k]) / np.sqrt(1 - rhos[k])
            slope *= f(psi) / np.sqrt(1 - F(psi)) / np.sqrt(F(psi))
            offset = 2*np.arcsin(np.sqrt(F(psi)))

            # adjust for integer to normal range mapping
            offset += slope * (-normal_max_value)
            slope *= 2*normal_max_value / (2**n_normal - 1)

            self._offsets[k] = offset
            self._slopes[k] = slope

            lry = LinearYRotation(slope, offset, n_normal, i_state=self.i_normal, i_target=self.i_ps[k])
            self._rotations += [lry]
Example #4
0
class GaussianConditionalIndependenceModel(MultivariateDistribution):
    """
    The Gaussian Conditional Independence Model for Credit Risk
    Reference: https://arxiv.org/abs/1412.1183
    Dependency between individual risk variabels and latent variable is approximated linearly.
    """

    CONFIGURATION = {
        'name': 'GaussianConditionalIndependenceModel',
        'description': 'Gaussian Conditional Independence Model',
        'input_schema': {
            '$schema': 'http://json-schema.org/schema#',
            'id': 'GaussianConditionalIndependenceModel_schema',
            'type': 'object',
            'properties': {
                'n_normal': {
                    'type': 'number'
                },
                'normal_max_value': {
                    "type": "number"
                },
                'p_zeros': {
                    'type': ['array'],
                    "items": {
                        "type": "number"
                    }
                },
                'rhos': {
                    'type': ['array'],
                    "items": {
                        "type": "number"
                    }
                },
                'i_normal': {
                    'type': ['array', 'null'],
                    "items": {
                        "type": "number"
                    },
                    'default': None
                },
                'i_ps': {
                    'type': ['array', 'null'],
                    "items": {
                        "type": "number"
                    },
                    'default': None
                }
            },
            'additionalProperties': False
        }
    }

    def __init__(self, n_normal, normal_max_value, p_zeros, rhos, i_normal=None, i_ps=None):
        """
        Constructor.

        The Gaussian Conditional Independence Model for Credit Risk
        Reference: https://arxiv.org/abs/1412.1183

        Args:
            n_normal (int): number of qubits to represent the latent normal random variable Z
            normal_max_value (float): min/max value to truncate the latent normal random variable Z
            p_zeros (list or array): standard default probabilities for each asset
            rhos (list or array): sensitivities of default probability of assets with respect to latent variable Z
            i_normal (list or array): indices of qubits to represent normal variable
            i_ps (list or array): indices of qubits to represent asset defaults
        """
        self.n_normal = n_normal
        self.normal_max_value = normal_max_value
        self.p_zeros = p_zeros
        self.rhos = rhos
        self.K = len(p_zeros)
        num_qubits = [n_normal] + [1]*self.K

        # set and store indices
        if i_normal is not None:
            self.i_normal = i_normal
        else:
            self.i_normal = range(n_normal)

        if i_ps is not None:
            self.i_ps = i_ps
        else:
            self.i_ps = range(n_normal, n_normal + self.K)

        # get normal (inverse) CDF and pdf
        def F(x): return norm.cdf(x)
        def F_inv(x): return norm.ppf(x)
        def f(x): return norm.pdf(x)

        # set low/high values
        low = [-normal_max_value] + [0]*self.K
        high = [normal_max_value] + [1]*self.K

        # call super constructor
        super().__init__(num_qubits, low=low, high=high)

        # create normal distribution
        self._normal = NormalDistribution(n_normal, 0, 1, -normal_max_value, normal_max_value)

        # create linear rotations for conditional defaults
        self._slopes = np.zeros(self.K)
        self._offsets = np.zeros(self.K)
        self._rotations = []
        for k in range(self.K):

            psi = F_inv(p_zeros[k]) / np.sqrt(1 - rhos[k])

            # compute slope / offset
            slope = -np.sqrt(rhos[k]) / np.sqrt(1 - rhos[k])
            slope *= f(psi) / np.sqrt(1 - F(psi)) / np.sqrt(F(psi))
            offset = 2*np.arcsin(np.sqrt(F(psi)))

            # adjust for integer to normal range mapping
            offset += slope * (-normal_max_value)
            slope *= 2*normal_max_value / (2**n_normal - 1)

            self._offsets[k] = offset
            self._slopes[k] = slope

            lry = LinearYRotation(slope, offset, n_normal, i_state=self.i_normal, i_target=self.i_ps[k])
            self._rotations += [lry]

    def build(self, qc, q, q_ancillas=None, params=None):

        self._normal.build(qc, q, q_ancillas)
        for lry in self._rotations:
            lry.build(qc, q, q_ancillas)
from qiskit.tools.monitor import job_monitor
from qiskit.aqua.components.uncertainty_models import NormalDistribution, UniformDistribution, LogNormalDistribution

IBMQ.enable_account('Enter API key')
provider = IBMQ.get_provider(hub='ibm-q')

backend = provider.get_backend('ibmq_qasm_simulator')

q = QuantumRegister(5, 'q')
c = ClassicalRegister(5, 'c')

print("\n Normal Distribution")
print("-----------------")

circuit = QuantumCircuit(q, c)
normal = NormalDistribution(num_target_qubits=5, mu=0, sigma=1, low=-1, high=1)
normal.build(circuit, q)
circuit.measure(q, c)

circuit.draw(output='mpl', filename='normal.png')

job = execute(circuit, backend, shots=8192)
job_monitor(job)
counts = job.result().get_counts()

print(counts)
sortedcounts = []
sortedkeys = sorted(counts)

for i in sortedkeys:
    for j in counts:
Example #6
0
# Set upper and lower data values
bounds = np.array([0.,7.])
# Set number of qubits used in the uncertainty model
num_qubits = [3]

# Set entangler map
entangler_map = []
for i in range(sum(num_qubits)):
    entangler_map.append([i, int(np.mod(i+1, sum(num_qubits)))])

# Load the trained circuit parameters
g_params = [0.29399714, 0.38853322, 0.9557694, 0.07245791, 6.02626428, 0.13537225]

# Set an initial state for the generator circuit
init_dist = NormalDistribution(sum(num_qubits), mu=1., sigma=1., low=bounds[0], high=bounds[1])
init_distribution = np.sqrt(init_dist.probabilities)
init_distribution = Custom(num_qubits=sum(num_qubits), state_vector=init_distribution)

# construct the variational form
var_form = RealAmplitudes(sum(num_qubits), entanglement=entangler_map, reps=1, initial_state=init_distribution)
var_form.entanglement_blocks = 'cz'
theta = ParameterVector('θ', var_form.num_parameters)
var_form = var_form.assign_parameters(theta)

# Set generator circuit
g_circuit = UnivariateVariationalDistribution(sum(num_qubits), var_form, g_params,
                                              low=bounds[0], high=bounds[1])
g_circuit._var_form_params = theta

# construct circuit factory for uncertainty model