-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fixed Qiskit QAOA solver (reimplemtented for Qiskit-Optimization-0.6)…
…, refactored Qrisp QAOA (was in the wrong directory)
- Loading branch information
1 parent
c8acdd5
commit 73c114a
Showing
15 changed files
with
249 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
import re | ||
|
||
from qiskit_optimization import QuadraticProgram | ||
|
||
def parse_lp_file(file_path): | ||
# Read the LP file | ||
with open(file_path, 'r') as file: | ||
lines = file.readlines() | ||
|
||
# Initialize components for parsing | ||
objective_sense = 'minimize' # default | ||
objective = '' | ||
constraints = [] | ||
variable_types = {} | ||
in_objective_section = False | ||
in_constraints_section = False | ||
in_binary_section = False | ||
|
||
# Parsing logic | ||
for line in lines: | ||
line = line.strip() | ||
|
||
# Objective function | ||
if line.lower().startswith('minimize') or line.lower().startswith('maximize'): | ||
in_objective_section = True | ||
objective_sense = line.split()[0].lower() | ||
continue | ||
|
||
if in_objective_section and (line.lower().startswith('subject to') or line.lower().startswith('binary')): | ||
in_objective_section = False | ||
continue | ||
|
||
if in_objective_section: | ||
objective += line | ||
continue | ||
|
||
# Constraints (no constraints in this example, but you may extend it later) | ||
if line.lower().startswith('subject to'): | ||
in_constraints_section = True | ||
continue | ||
elif in_constraints_section and line.lower().startswith('binary'): | ||
in_constraints_section = False | ||
|
||
# Binary variables | ||
if line.lower().startswith('binary'): | ||
in_binary_section = True | ||
continue | ||
|
||
if in_binary_section: | ||
variables = line.split() | ||
for var in variables: | ||
variable_types[var] = 'binary' | ||
|
||
return objective_sense, objective, constraints, variable_types | ||
|
||
|
||
def parse_objective(objective_str): | ||
""" Parse the objective function to extract linear and quadratic coefficients """ | ||
# Remove the 'obj:' prefix | ||
objective_str = re.sub(r'^obj:\s*', '', objective_str) | ||
|
||
# Extract and remove the division factor (e.g., "/ 2", "/ 3", "/ 10") | ||
division_factor_match = re.search(r'/\s*([\d\.]+)', objective_str) | ||
division_factor = float(division_factor_match.group(1)) if division_factor_match else 1.0 | ||
objective_str = re.sub(r'/\s*[\d\.]+', '', objective_str) | ||
|
||
# Remove square brackets | ||
objective_str = objective_str.replace('[', '').replace(']', '') | ||
|
||
# Extract terms using regular expression | ||
term_pattern = re.compile(r'([+-]?\s*\d*\.?\d+(?:e[+-]?\d+)?)\s*\*?\s*([\w\d]+)\s*(?:\*\s*([\w\d]+))?') | ||
terms = term_pattern.findall(objective_str) | ||
linear = {} | ||
quadratic = {} | ||
|
||
# Parse each term | ||
for coeff_str, var1, var2 in terms: | ||
coeff = float(coeff_str.replace(' ', '')) # Remove any spaces in coefficient | ||
|
||
if var2: # Quadratic term | ||
if (var1, var2) in quadratic: | ||
quadratic[(var1, var2)] += coeff | ||
else: | ||
quadratic[(var1, var2)] = coeff | ||
else: # Linear term | ||
if var1 in linear: | ||
linear[var1] += coeff | ||
else: | ||
linear[var1] = coeff | ||
|
||
# Apply division factor | ||
if division_factor != 1.0 and division_factor != 0: | ||
for key in linear: | ||
linear[key] /= division_factor | ||
for key in quadratic: | ||
quadratic[key] /= division_factor | ||
|
||
return linear, quadratic | ||
|
||
|
||
def convert_to_quadratic_program(lp_file_path): | ||
# Parse the LP file | ||
objective_sense, objective, constraints, variable_types = parse_lp_file(lp_file_path) | ||
|
||
# Parse objective components | ||
linear, quadratic = parse_objective(objective) | ||
|
||
# Create an instance of QuadraticProgram | ||
qp = QuadraticProgram() | ||
|
||
# Add variables | ||
for var in variable_types: | ||
if variable_types[var] == 'binary': | ||
qp.binary_var(var) | ||
|
||
# Set the objective sense | ||
if objective_sense == 'minimize': | ||
qp.minimize(linear=linear, quadratic=quadratic) | ||
else: | ||
qp.maximize(linear=linear, quadratic=quadratic) | ||
|
||
# Add constraints (empty in this example) | ||
# You can extend this logic to handle any constraints | ||
|
||
return qp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
import numpy as np | ||
from qrisp import QuantumArray, QuantumFloat | ||
from qrisp.core import demux | ||
from qrisp.environments import invert | ||
|
||
|
||
# Create a function that generates a state of superposition of all permutations | ||
def swap_to_front(qa, index): | ||
with invert(): | ||
# The keyword ctrl_method = "gray_pt" allows the controlled swaps to be synthesized | ||
# using Margolus gates. These gates perform the same operation as a regular Toffoli | ||
# but add a different phase for each input. This phase will not matter though, | ||
# since it will be reverted once the ancilla values of the oracle are uncomputed. | ||
demux(qa[0], index, qa, permit_mismatching_size=True) | ||
|
||
|
||
def eval_perm(perm_specifiers, city_amount, qa=None): | ||
N = len(perm_specifiers) | ||
|
||
# To filter out the cyclic permutations, we impose that the first city is always city 0 | ||
# We will have to consider this assumption later when calculating the route distance | ||
# by manually adding the trip distance of the first trip (from city 0) and the | ||
# last trip (to city 0) | ||
if qa is None: | ||
qa = QuantumArray( | ||
QuantumFloat(int(np.ceil(np.log2(city_amount)))), city_amount - 1 | ||
) | ||
|
||
for i in range(city_amount - 1): | ||
qa[i] += i + 1 | ||
|
||
for i in range(N): | ||
swap_to_front(qa[i:], perm_specifiers[i]) | ||
|
||
return qa | ||
|
||
|
||
def eval_perm_backward(perm_specifiers, city_amount, qa=None): | ||
N = len(perm_specifiers) | ||
|
||
# To filter out the cyclic permutations, we impose that the first city is always city 0 | ||
# We will have to consider this assumption later when calculating the route distance | ||
# by manually adding the trip distance of the first trip (from city 0) and the | ||
# last trip (to city 0) | ||
|
||
for i in reversed(range(N)): | ||
demux(qa[i], perm_specifiers[i], qa[i:], permit_mismatching_size=True) | ||
|
||
for i in range(city_amount - 1): | ||
qa[i] -= i + 1 | ||
|
||
return qa | ||
|
||
|
||
def eval_perm_old(perm_specifiers, city_amount, qa=None): | ||
N = len(perm_specifiers) | ||
|
||
# To filter out the cyclic permutations, we impose that the first city is always city 0 | ||
# We will have to consider this assumption later when calculating the route distance | ||
# by manually adding the trip distance of the first trip (from city 0) and the | ||
# last trip (to city 0) | ||
if qa is None: | ||
qa = QuantumArray(QuantumFloat(int(np.ceil(np.log2(city_amount)))), city_amount) | ||
|
||
add = np.arange(0, city_amount) | ||
|
||
for i in range(city_amount): | ||
qa[i] += int(add[i]) | ||
|
||
for i in range(N): | ||
swap_to_front(qa[i:], perm_specifiers[i]) | ||
|
||
return qa | ||
|
||
|
||
# Create function that returns QuantumFloats specifying the permutations (these will be in uniform superposition) | ||
def create_perm_specifiers(city_amount, init_seq=None) -> list[QuantumFloat]: | ||
perm_specifiers = [] | ||
|
||
for i in range(city_amount - 1): | ||
qf_size = int(np.ceil(np.log2(city_amount - i))) | ||
|
||
if i == 0: | ||
continue | ||
|
||
temp_qf = QuantumFloat(qf_size) | ||
|
||
if not init_seq is None: | ||
temp_qf[:] = init_seq[i - 1] | ||
|
||
perm_specifiers.append(temp_qf) | ||
|
||
return perm_specifiers |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6 changes: 0 additions & 6 deletions
6
src/main/resources/edu/kit/provideq/toolbox/qubo/linear-problem.txt
This file was deleted.
Oops, something went wrong.
7 changes: 7 additions & 0 deletions
7
src/main/resources/edu/kit/provideq/toolbox/qubo/quadratic-problem.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
Minimize | ||
obj: 0 + [ -32.984845004941285 x1 * x1 + 32.984845004941285 x1 * x2 + 32.984845004941285 x1 * x3 + 8.246211251235321 x1 * x4 - 32.984845004941285 x2 * x2 + 8.246211251235321 x2 * x3 + 32.984845004941285 x2 * x4 - 32.984845004941285 x3 * x3 + 32.984845004941285 x3 * x4 - 32.984845004941285 x4 * x4 ] / 2 | ||
|
||
Subject To | ||
|
||
Binary | ||
x1 x2 x3 x4 |