Skip to content

Commit

Permalink
restructuring
Browse files Browse the repository at this point in the history
  • Loading branch information
kdomino committed Oct 4, 2023
1 parent b83ee01 commit 644786a
Show file tree
Hide file tree
Showing 19 changed files with 137 additions and 388 deletions.
51 changes: 24 additions & 27 deletions AGV_quantum/LinearProg.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import dimod
from cpp_pyqubo import Binary, Constraint, Placeholder
from cpp_pyqubo import Constraint, Placeholder
from pyqubo import LogEncInteger
from pyqubo import Binary

Expand Down Expand Up @@ -48,35 +48,35 @@ def _to_bqm_qubo_ising(self, pdict=None):
)
H = 0
ind = 0
vars = []
for (lb, ub) in self.bounds:
model_vars = []
for (lb, ub) in bounds:
if lb == 0 and ub == 1:
vars.append(Binary(f"x_{ind}"))
model_vars.append(Binary(f"x_{ind}"))
else:
vars.append(LogEncInteger(f"x_{ind}", (lb, ub)))
model_vars.append(LogEncInteger(f"x_{ind}", (lb, ub)))
ind += 1

pyqubo_obj = sum(var * coef for var, coef in zip(vars, c) if coef != 0)
pyqubo_obj = sum(var * coef for var, coef in zip(model_vars, c) if coef != 0)
H += Placeholder("obj") * pyqubo_obj

num_eq = 0
if A_eq is not None:
for i in range(len(A_eq)):
for i, _ in enumerate(A_eq):
expr = sum(
A_eq[i][j] * vars[j] for j in range(self.nvars) if A_eq[i][j] != 0
A_eq[i][j] * model_vars[j] for j in range(self.nvars) if A_eq[i][j] != 0
)
expr -= b_eq[i]
H += Constraint(Placeholder(f"eq_{num_eq}") * expr ** 2, f"eq_{num_eq}")
num_eq += 1
if A_ub is not None:
for i in range(len(A_ub)):
for i, _ in enumerate(A_ub):
expr = sum(
A_ub[i][j] * vars[j] for j in range(self.nvars) if A_ub[i][j] != 0
A_ub[i][j] * model_vars[j] for j in range(self.nvars) if A_ub[i][j] != 0
)
expr -= b_ub[i]
slack = LogEncInteger(
f"eq_{num_eq}_slack",
(0, LinearProg._get_slack_ub(vars, A_ub[i], b_ub[i])),
(0, LinearProg._get_slack_ub(model_vars, A_ub[i], b_ub[i])),
)

H += Constraint(
Expand All @@ -88,9 +88,9 @@ def _to_bqm_qubo_ising(self, pdict=None):

self.num_eq = num_eq
pyqubo_model = H.compile()
if pdict == None:
if pdict is None:
pdict = {f"eq_{i}": 2 for i in range(self.num_eq)}
elif type(pdict) == int or type(pdict) == float:
elif isinstance(pdict, int) or isinstance(pdict, float):
pdict = {f"eq_{i}": pdict for i in range(self.num_eq)}
pdict["obj"] = 1
self.qubo = pyqubo_model.to_qubo(feed_dict=pdict)
Expand Down Expand Up @@ -137,7 +137,7 @@ def _get_slack_ub(vars: list, coefs: list, offset: int) -> int:
"""
ub = 0
for var, coef in zip(vars, coefs):
if type(var) == LogEncInteger:
if isinstance(var, LogEncInteger):
ub += coef * (var.value_range[1] if coef < 0 else var.value_range[0])
else:
ub += coef * (1 if coef < 0 else 0)
Expand All @@ -158,31 +158,31 @@ def _to_cqm(self):
)

ind = 0
vars = []
for (lb, ub) in self.bounds:
model_vars = []
for (lb, ub) in bounds:
if lb == 0 and ub == 1:
vars.append(dimod.Binary(f"x_{ind}"))
model_vars.append(dimod.Binary(f"x_{ind}"))
else:
vars.append(dimod.Integer(f"x_{ind}", lower_bound=lb, upper_bound=ub))
model_vars.append(dimod.Integer(f"x_{ind}", lower_bound=lb, upper_bound=ub))
ind += 1

cqm = dimod.ConstrainedQuadraticModel()
dimod_obj = sum(var * coef for var, coef in zip(vars, c) if coef != 0)
dimod_obj = sum(var * coef for var, coef in zip(model_vars, c) if coef != 0)
cqm.set_objective(dimod_obj)

num_eq = 0
if A_eq is not None:
for i in range(len(A_eq)):
expr = sum(
A_eq[i][j] * vars[j] for j in range(self.nvars) if A_eq[i][j] != 0
A_eq[i][j] * model_vars[j] for j in range(self.nvars) if A_eq[i][j] != 0
)
new_c = expr == b_eq[i]
cqm.add_constraint(new_c, label=f"eq_{num_eq}")
num_eq += 1
if A_ub is not None:
for i in range(len(A_ub)):
expr = sum(
A_ub[i][j] * vars[j] for j in range(self.nvars) if A_ub[i][j] != 0
A_ub[i][j] * model_vars[j] for j in range(self.nvars) if A_ub[i][j] != 0
)
new_c = expr <= b_ub[i]
cqm.add_constraint(new_c, label=f"eq_{num_eq}")
Expand All @@ -191,9 +191,8 @@ def _to_cqm(self):
self.cqm = cqm

def _count_qubits(self):
vars = self.bqm.variables
return len(vars)

model_vars = self.bqm.variables
return len(model_vars)

def _count_quadratic_couplings(self):
"""
Expand All @@ -205,7 +204,6 @@ def _count_quadratic_couplings(self):
count = count + 1
return count


def _count_linear_fields(self):
"""
return number of local fields hs
Expand All @@ -215,6 +213,5 @@ def _count_linear_fields(self):
if h != 0:
count = count + 1
return count




9 changes: 1 addition & 8 deletions AGV_quantum/__init__.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@

from .LinearProg import LinearProg


from .process_results import (
get_results, load_results, store_result, print_results
)

from .quadratic_solver_CPLEX import (
load_linear_prog_object, process_result, quadratic_solve_qubo
get_results, load_results, store_result, get_objective, analyze_constraints, process_result
)


Expand All @@ -17,7 +12,6 @@
create_t_iterator, create_y_iterator, create_z_iterator
)


from .linear_solver import (
LinearAGV, print_ILP_size
)
Expand All @@ -28,6 +22,5 @@
sim_anneal, annealing, constrained_solver, hybrid_anneal
)


from .train_diagram import plot_train_diagram

11 changes: 6 additions & 5 deletions AGV_quantum/linear_solver.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
from curses import A_LEFT
import itertools
import numpy as np
from typing import Callable, Dict, List, Tuple
"""implementation of linear solver on ILP"""

from AGV_quantum import see_non_zero_variables, create_graph, create_iterators, create_agv_list
import itertools
from typing import Optional
import numpy as np
from docplex.mp.model import Model
from docplex.mp.solution import SolveSolution

from AGV_quantum import see_non_zero_variables, create_graph, create_iterators, create_agv_list



class LinearAGV:
"""
Expand Down
42 changes: 17 additions & 25 deletions AGV_quantum/process_results.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""analyse results given quantum/hybrid/simulation approach"""

import os
import pickle
from typing import Any
import dimod
from dimod import SampleSet
from AGV_quantum import LinearProg

Expand Down Expand Up @@ -106,26 +106,18 @@ def analyze_constraints(lp, sample):
result[f"eq_{num_eq}"] = expr <= lp.b_ub[i]
num_eq += 1

return result, sum(x == False for x in result.values())


def print_results(dict_list):
soln = next((l for l in dict_list if l["feasible"]), None)
if soln is not None:
print("obj:", soln["objective"], "x:", list(soln["sample"].values()))
print("First 10 solutions")
for d in dict_list[:10]:
print(d)
else:
print("No feasible solution")
for d in dict_list[:10]:
print(
"Energy:",
d["energy"],
"Objective:",
d["objective"],
"Feasible",
d["feasible"],
"Broken constraints:",
d["feas_constraints"][1],
)
return result, sum(x is False for x in result.values())


def process_result(sampleset: list):
energy = sampleset[0]["energy"]
objective = sampleset[0]["objective"]
feasible = sampleset[0]["feasible"]
broken_constrains = []
if not feasible:
for eq, feas in sampleset[0]["feas_constraints"][0].items():
if not feas:
broken_constrains.append(eq)
num_broken = len(broken_constrains)

return {"energy": energy, "objective": objective, "feasible": feasible, "num_broken": num_broken}
37 changes: 19 additions & 18 deletions AGV_quantum/quadratic_solver.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
""" implementation of quadratic (or D-Wace cqm) solver for quantum, hybrid and simulations """
import dimod
from cpp_pyqubo import Binary, Constraint, Placeholder
from pyqubo import LogEncInteger
Expand All @@ -7,7 +8,7 @@


class QuadraticAGV:

"""class containing quadratic model of the problem i.e. QUBO, bqm or Ising"""
def __init__(self, lin_agv: LinearAGV):
self.lin_agv = lin_agv
self.c = lin_agv.c
Expand Down Expand Up @@ -41,35 +42,35 @@ def to_bqm_qubo_ising(self, pdict=None):
)
H = 0
ind = 0
vars = []
model_vars = []
for (lb, ub) in bounds:
if lb == 0 and ub == 1:
vars.append(Binary(f"x_{ind}"))
model_vars.append(Binary(f"x_{ind}"))
else:
vars.append(LogEncInteger(f"x_{ind}", (lb, ub)))
model_vars.append(LogEncInteger(f"x_{ind}", (lb, ub)))
ind += 1

pyqubo_obj = sum(var * coef for var, coef in zip(vars, c) if coef != 0)
pyqubo_obj = sum(var * coef for var, coef in zip(model_vars, c) if coef != 0)
H += Placeholder("obj") * pyqubo_obj

num_eq = 0
if A_eq is not None:
for i in range(len(A_eq)):
for i, _ in enumerate(A_eq):
expr = sum(
A_eq[i][j] * vars[j] for j in range(self.nvars) if A_eq[i][j] != 0
A_eq[i][j] * model_vars[j] for j in range(self.nvars) if A_eq[i][j] != 0
)
expr -= b_eq[i]
H += Constraint(Placeholder(f"eq_{num_eq}") * expr ** 2, f"eq_{num_eq}")
num_eq += 1
if A_ub is not None:
for i in range(len(A_ub)):
for i, _ in enumerate(A_ub):
expr = sum(
A_ub[i][j] * vars[j] for j in range(self.nvars) if A_ub[i][j] != 0
A_ub[i][j] * model_vars[j] for j in range(self.nvars) if A_ub[i][j] != 0
)
expr -= b_ub[i]
slack = LogEncInteger(
f"eq_{num_eq}_slack",
(0, self._get_slack_ub(vars, A_ub[i], b_ub[i])),
(0, self._get_slack_ub(model_vars, A_ub[i], b_ub[i])),
)

H += Constraint(
Expand All @@ -81,9 +82,9 @@ def to_bqm_qubo_ising(self, pdict=None):

self.num_eq = num_eq
pyqubo_model = H.compile()
if pdict == None:
if pdict is None:
pdict = {f"eq_{i}": 2 for i in range(self.num_eq)}
elif type(pdict) == int or type(pdict) == float:
elif isinstance(pdict, int) or isinstance(pdict, float):
pdict = {f"eq_{i}": pdict for i in range(self.num_eq)}
pdict["obj"] = 1
self.qubo = pyqubo_model.to_qubo(feed_dict=pdict)
Expand Down Expand Up @@ -116,10 +117,10 @@ def interpreter(sampleset: dimod.SampleSet):
self.interpreter = lambda ss: interpreter(ss)

@staticmethod
def _get_slack_ub(vars: list, coefs: list, offset: int) -> int:
def _get_slack_ub(model_vars: list, coefs: list, offset: int) -> int:
"""Returns upper bound for slack variables
:param vars: List of variables (can be integer or binary)
:param model_vars: List of variables (can be integer or binary)
:type vars: list
:param coefs: List of coefficients for the inequality
:type coefs: list
Expand All @@ -129,7 +130,7 @@ def _get_slack_ub(vars: list, coefs: list, offset: int) -> int:
:rtype: int
"""
ub = 0
for var, coef in zip(vars, coefs):
for var, coef in zip(model_vars, coefs):
if type(var) == LogEncInteger:
ub += coef * (var.value_range[1] if coef < 0 else var.value_range[0])
else:
Expand All @@ -152,7 +153,7 @@ def to_cqm(self):

ind = 0
vars = []
for (lb, ub) in self.bounds:
for (lb, ub) in bounds:
if lb == 0 and ub == 1:
vars.append(dimod.Binary(f"x_{ind}"))
else:
Expand Down Expand Up @@ -184,8 +185,8 @@ def to_cqm(self):
self.cqm = cqm

def _count_qubits(self):
vars = self.bqm.variables
return len(vars)
model_vars = self.bqm.variables
return len(model_vars)


def _count_quadratic_couplings(self):
Expand Down
Loading

0 comments on commit 644786a

Please sign in to comment.