Source code for geqo.algorithms.risk_model

import numpy as np
import math
from geqo.operations.controls import QuantumControl
from geqo.core.quantum_circuit import Sequence
from geqo.core.basic import BasicGate
import sympy as sym


def getRY(phi):
    return BasicGate("ry(" + str(phi) + ")", 1), sym.Matrix(
        [
            [sym.cos(phi / 2), -sym.sin(phi / 2)],
            [sym.sin(phi / 2), sym.cos(phi / 2)],
        ]
    )


[docs] def RiskModel( node_probs: dict, edge_probs: dict, ): """Creates a quantum circuit implementation of the business risk model defined by a probabilistic network. The underlying graph of the network has to be a directed acyclic graph. Input: node_probs: dictionary with the nodes as keys and their intrinsic probabilities as values edge_probs: dictionary with edges as keys and the corresponding transition probabilities as values Output: Quantum circuit implementation of the network and dictionary to prepare the SymPy simulator. """ collectedValues = {} nodes = list(node_probs.keys()) gatelist = [] # Write probabilities for nodes and edges into matrix mat = np.zeros((len(nodes), len(nodes))) for i in range(len(nodes)): mat[i][i] = node_probs[nodes[i]] for i in range(len(nodes)): for j in range(len(nodes)): if (nodes[i], nodes[j]) in edge_probs: mat[i][j] = edge_probs[(nodes[i], nodes[j])] # Main processing loop. indicesProcessed = [] while len(indicesProcessed) < len(nodes): # Find the first unprocessed node that has no unprocessed parents. target = None for i in range(len(nodes)): allParentsAlreadyProcessed = True for j in range(len(nodes)): if not (i == j) and (mat[j][i] != 0) and j not in indicesProcessed: allParentsAlreadyProcessed = False if i not in indicesProcessed and allParentsAlreadyProcessed is True: target = i break indicesProcessed.append(target) # In case of a cycle if target is None: raise BaseException("""Network may not have cycles.""") # collecting all parant nodes of the current target foundControllers = False collectedControllerIndices = [] for y in range(len(nodes)): if mat[y, target] != 0 and not (y == target): foundControllers = True collectedControllerIndices.append(y) if foundControllers is False: # This risk item is not triggered by transitions. # Just put an uncontrolled gate in for it. newGate, newValue = getRY(2 * math.asin(math.sqrt(mat[target, target]))) gatelist.append((newGate, [str(target)])) collectedValues[newGate.name] = newValue # qc.ry(2 * math.asin(math.sqrt(mat[target, target])), qr[target]) else: # This risk item is triggered by one or more other risk items. controllist = [] for i in range(len(collectedControllerIndices)): controllist.append(collectedControllerIndices[i]) controllist.append(target) # initializing at inherent probability newGate, newValue = getRY(2 * math.asin(math.sqrt(mat[target, target]))) gatelist.append((newGate, [str(target)])) collectedValues[newGate.name] = newValue # Iterate over all subsets of control qubits using binary configurations for i in range(1, 2 ** len(collectedControllerIndices)): cts = format(i, "0" + str(len(collectedControllerIndices)) + "b") # calculate the probability that the target node is not triggered # given that all nodes in the subset have been triggered and all other # control qubits have not pTargetOff = 1 - mat[target, target] for j in range(len(collectedControllerIndices)): if cts[j] == "1": pTargetOff = pTargetOff * ( 1 - mat[collectedControllerIndices[j], target] ) # For this configuration of control qubits, turn the qubit on with # the probability 1-pTargetOff, but substract the angle it was # initialized in newGate, newValue = getRY( 2 * math.asin(math.sqrt(1 - pTargetOff)) - 2 * math.asin(math.sqrt(mat[target, target])) ) gatelist.append( ( QuantumControl( [int(s) for s in cts], newGate, ), [str(x) for x in controllist], ) ) collectedValues[newGate.name] = newValue return Sequence( [], [str(x) for x in list(range(len(nodes)))], gatelist ), collectedValues