Source code for geqo.algorithms.risk_model
import math
import numpy as np
from geqo.core.quantum_circuit import Sequence
from geqo.gates import Ry
from geqo.operations.controls import QuantumControl
"""def getRY(phi):
return 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
phi = 2 * math.asin(math.sqrt(mat[target, target]))
# newValue = getRY(phi)
gatelist.append((Ry(f"Φ{target}"), [str(target)], []))
collectedValues[f"Φ{target}"] = phi
# 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
phi = 2 * math.asin(math.sqrt(mat[target, target]))
gatelist.append((Ry(f"Φ{target}"), [str(target)], []))
collectedValues[f"Φ{target}"] = phi
# 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
theta = 2 * math.asin(math.sqrt(1 - pTargetOff)) - 2 * math.asin(
math.sqrt(mat[target, target])
)
gatelist.append(
(
QuantumControl(
[int(s) for s in cts],
Ry(f"θ{target}"),
),
[str(x) for x in controllist],
[],
)
)
collectedValues[f"θ{target}"] = theta
return Sequence(
[str(x) for x in list(range(len(nodes)))], [], gatelist, "Risk"
), collectedValues