Skip to content

Commit

Permalink
add shor implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
LaviniaStiliadou committed Feb 6, 2024
1 parent 0bb3bee commit 34cd2b7
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 41 deletions.
39 changes: 30 additions & 9 deletions app/controller/objectiveFns/objective_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
KnapsackObjectiveEvaluationRequest,
KnapsackObjectiveEvaluationRequestSchema,
ShorDiscreteLogObjectiveEvaluationRequestSchema,
ShorDiscreteLogObjectiveEvaluationRequest
ShorDiscreteLogObjectiveEvaluationRequest,
)

blp = Blueprint(
Expand Down Expand Up @@ -109,22 +109,43 @@ def max_cut(json: KnapsackObjectiveEvaluationRequest):
"b": 2,
"g": 5,
"p": 7,
"n": -1,
"n": 3,
"counts": {
"10000110000101": 10,
"01100110000110": 20,
"10000011000000": 30,
"01001100000110": 40,
"11000011000000": 50,
"101 101": 4,
"000 100": 17,
"011 111": 15,
"101 001": 13,
"000 000": 12,
"110 010": 1,
"101 110": 3,
"000 101": 1,
"010 011": 2,
"011 011": 5,
"011 110": 3,
"011 010": 2,
"110 001": 2,
"010 111": 3,
"010 110": 1,
"011 100": 3,
"001 011": 2,
"110 101": 2,
"100 111": 2,
"011 101": 1,
"110 000": 1,
"011 101": 1,
"110 000": 1,
"011 001": 1,
"011 000": 1,
"101 010": 1,
},
"objFun": "Expectation",
"visualization": "False",
},
)
@blp.response(200, ObjectiveResponseSchema)
def max_cut(json: ShorDiscreteLogObjectiveEvaluationRequest):
def shor_discrete_log(json: ShorDiscreteLogObjectiveEvaluationRequest):
print(json)
if json:
return objective_service.generate_knapsack_objective_response(
return objective_service.generate_shor_discrete_log_objective_response(
ShorDiscreteLogObjectiveEvaluationRequest(**json)
)
26 changes: 26 additions & 0 deletions app/helperfunctions.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
from fractions import Fraction


def take_first(elem):
return elem[0]

Expand Down Expand Up @@ -39,3 +42,26 @@ def convert_cost_object_to_dict(cost_object):
for tup in sorted_costs
]
return sorted_costs_dict


def find_period(result_list: [(int, int, int)], n: int, p: int, g: int) -> int:
"""The order of the generator is not given, it has to be determined.
The list of results for the whole circuit will be used, since the
measurement of stage1 allows for phase estimation of the operator
(similar to Shor's algorithm for prime factorization)."""
smallest_fitting_denominator = (
p + 1
) # init to p+1 (sth larger than the real result)
for (y1, _, _) in result_list:
meas_div = y1 / (2**n)
frac_meas = Fraction(meas_div).limit_denominator(p - 1)

# check if denominator fits
r_candidate = frac_meas.denominator
if g**r_candidate % p == 1:
# fits
if r_candidate < smallest_fitting_denominator:
smallest_fitting_denominator = r_candidate

print("Found r=", smallest_fitting_denominator)
return smallest_fitting_denominator
75 changes: 58 additions & 17 deletions app/services/objective_service.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
from app.helperfunctions import take_second, convert_cost_object_to_dict
from app.helperfunctions import take_second, convert_cost_object_to_dict, find_period
from app.model.objective_request import (
TSPObjectiveEvaluationRequest,
MaxCutObjectiveEvaluationRequest,
KnapsackObjectiveEvaluationRequest,
ShorDiscreteLogObjectiveEvaluationRequest
ShorDiscreteLogObjectiveEvaluationRequest,
)
from app.model.objective_response import ObjectiveResponse
from app.services.objectiveFunctions import F_CVaR, F_EE, F_Gibbs
from app.services.visualization import TspVisualization, MaxCutVisualization
from app.constants import *
from qiskit_optimization.applications import Knapsack
import math
import numpy as np


def generate_tsp_objective_response(input: TSPObjectiveEvaluationRequest):
Expand Down Expand Up @@ -90,24 +92,63 @@ def generate_knapsack_objective_response(input: KnapsackObjectiveEvaluationReque
return ObjectiveResponse(objective_value, [costs], None)


def generate_shor_discrete_log_objective_response(
input: ShorDiscreteLogObjectiveEvaluationRequest,
):
# objective_function = getObjectiveFunction(
# input.objFun, MAX_CUT, **input.objFun_hyperparameters
# )
# objective_value = objective_function.evaluate(input.counts, input.adj_matrix)
# cost_dict = convert_cost_object_to_dict(objective_function.counts_cost)
if input.n == -1:
n = math.ceil(math.log(input.p, 2))
else:
n = input.n
res = list()
print("executed circuit")
for result in input.counts.keys():
# split result measurements
result_s = result.split(" ")
m_stage1 = int(result_s[1], 2)
m_stage2 = int(result_s[0], 2)

def generate_shor_discrete_log_objective_response(input: ShorDiscreteLogObjectiveEvaluationRequest):
objective_function = getObjectiveFunction(
input.objFun, MAX_CUT, **input.objFun_hyperparameters
)
objective_value = objective_function.evaluate(input.counts, input.adj_matrix)
cost_dict = convert_cost_object_to_dict(objective_function.counts_cost)
res.append((m_stage1, m_stage2, input.counts[result]))

graphic = (
MaxCutVisualization().visualize(
counts=objective_function.counts_cost, problem_instance=input.adj_matrix
)
if input.visualization
else None
)
num_fail = 0
num_success = 0

print("value", objective_value)
return ObjectiveResponse(objective_value, cost_dict, graphic)
correct_m = -1

for (y1, y2, freq) in res:

# period has to be calculated
r = find_period(res, n, input.p, input.g)

# k is inferred from the measurement result from first stage
k = int(round((y1 * r) / (2**n), 0))
print("k = ", k)

# m (the discrete log) is calculated by using the congruence:
# ((km mod r)/r)*2^n = m_stage2
# v = m_stage2*r/2^n
v = (y2 * r) / (2**n)
# print("v=", v) # = km mod r

# k inverse exists?
if np.gcd(k, r) == 1:
kinv = pow(k, -1, r)
# print("kInv=", kinv)
m = int(round(v * kinv % r, 0))
# print("found m=", m)

# check if this m actually fits
if (input.g**m % input.p) == input.b:
correct_m = m

graphic = None

print("calculated m ", correct_m)
return ObjectiveResponse(correct_m, {}, graphic)


def getObjectiveFunction(objFun, costFun, **kwargs):
Expand Down
21 changes: 6 additions & 15 deletions tests/test_costFunctions.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,32 +202,23 @@ def test_knapsack(self):
data=json.dumps(
{
"items": [
{
"value": 5,
"weight": 2
},
{
"value": 2,
"weight": 1
},
{
"value": 3,
"weight": 2
}
{"value": 5, "weight": 2},
{"value": 2, "weight": 1},
{"value": 3, "weight": 2},
],
"max_weights": 20,
"counts": {
"100000": 30,
"100001": 10,
"110000": 50,
"011110": 20,
"010110": 40
"010110": 40,
},
"objFun": "Expectation",
"visualization": "True"
"visualization": "True",
}
),
content_type="application/json",
)
self.assertEqual(response.status_code, 200)
print(response.get_json())
print(response.get_json())

0 comments on commit 34cd2b7

Please sign in to comment.