Esempio n. 1
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.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:
        if (i == j):