Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hotfix qiskit #297

Merged
merged 4 commits into from
Dec 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,4 +128,4 @@
# app.connect(skip)

# pygments_style = 'sphinx'
# suppress_warnings = ["myst_header"]
# suppress_warnings = ["myst_header"]
2 changes: 1 addition & 1 deletion examples/03_qaoa_on_qpus.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@
"outputs": [],
"source": [
"# device. If qpu_crendetials is not specified,the default hub, group and provider is used.\n",
"qiskit_cloud = create_device(location='ibmq', name='ibm_perth', **qpu_credentials, as_emulator=True)\n",
"qiskit_cloud = create_device(location='ibmq', name='ibm_kyoto', **qpu_credentials, as_emulator=True)\n",
"q_qiskit.set_device(qiskit_cloud)\n",
"\n",
"# circuit properties\n",
Expand Down
4 changes: 2 additions & 2 deletions examples/14_qaoa_benchmark.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
"q = QAOA()\n",
"\n",
"# set device and backend properties\n",
"qiskit_cloud = create_device(location='ibmq', name='ibm_perth', **qpu_credentials, as_emulator=True)\n",
"qiskit_cloud = create_device(location='ibmq', name='ibm_kyoto', **qpu_credentials, as_emulator=True)\n",
"q.set_device(qiskit_cloud)\n",
"q.set_backend_properties(n_shots=1000)\n",
"\n",
Expand Down Expand Up @@ -602,7 +602,7 @@
"q_ibm = QAOA()\n",
"\n",
"# set device and backend properties\n",
"qiskit_cloud = create_device(location='ibmq', name='ibm_perth', **qpu_credentials, as_emulator=True)\n",
"qiskit_cloud = create_device(location='ibmq', name='ibm_kyoto', **qpu_credentials, as_emulator=True)\n",
"q_ibm.set_device(qiskit_cloud)\n",
"q_ibm.set_backend_properties(n_shots=1000)\n",
"\n",
Expand Down
268 changes: 151 additions & 117 deletions src/openqaoa-core/openqaoa/problems/bpsp.py

Large diffs are not rendered by default.

54 changes: 36 additions & 18 deletions src/openqaoa-core/tests/test_bpsp.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@ def terms_list_equality(terms_list1, terms_list2):

return bool


def fisher_yates_shuffle(arr, rng):
"""
Perform an in-place shuffle of a list using the Fisher-Yates shuffle algorithm.

This algorithm runs in O(n) time and ensures that every permutation of the array is equally likely.
This algorithm runs in O(n) time and ensures that every permutation of the array is equally likely.
The shuffle is performed in-place, meaning that the input array `arr` is modified directly.

Parameters:
Expand Down Expand Up @@ -59,6 +60,7 @@ def fisher_yates_shuffle(arr, rng):
# Return the shuffled array
return arr


class TestBPSP(unittest.TestCase):
"""
Test suite for the BPSP problem.
Expand All @@ -71,12 +73,14 @@ def test_bpsp_qubo(self):
"""
Test the correct QUBO formation from a provided graph.

This method validates that BPSP creates the expected QUBO by comparing
This method validates that BPSP creates the expected QUBO by comparing
its terms and weights with predefined expected values.
"""
car_sequence = [3, 1, 0, 0, 2, 2, 4, 4, 3, 1]
G = nx.Graph()
G.add_weighted_edges_from([[3, 1, -2], [3, 4, -1], [1, 0, -1], [0, 2, 1], [2, 4, 1]])
G.add_weighted_edges_from(
[[3, 1, -2], [3, 4, -1], [1, 0, -1], [0, 2, 1], [2, 4, 1]]
)

gr_edges = [[3, 1], [3, 4], [1, 0], [0, 2], [2, 4]]
gr_weights = [-2, -1, -1, 1, 1]
Expand All @@ -103,12 +107,12 @@ def test_bpsp_random_instance(self):
"""
Test the random instance generation of the Binary Paint Shop Problem (BPSP).

This test verifies whether the `random_instance` method of the BPSP class
This test verifies whether the `random_instance` method of the BPSP class
correctly creates a randomized car sequence based on a given number of cars and seed.
The car sequence should be a list containing two occurrences of each car ID,
randomly shuffled using the Fisher-Yates shuffle algorithm.

The function asserts that the sequence generated by the BPSP class's method
The function asserts that the sequence generated by the BPSP class's method
is identical to the sequence produced by an explicitly defined Fisher-Yates shuffle process,
ensuring both consistency and correctness in the shuffling method based on a fixed seed.
"""
Expand All @@ -120,16 +124,19 @@ def test_bpsp_random_instance(self):
# Lambda function to create and shuffle car sequence using Fisher-Yates algorithm
# The lambda function first duplicates each car ID using np.tile, then applies the shuffle.
create_car_seq = lambda num_cars, seed: fisher_yates_shuffle(
np.tile(np.arange(num_cars), 2), np.random.default_rng(seed))
np.tile(np.arange(num_cars), 2), np.random.default_rng(seed)
)

# Generating a random BPSP instance using the class method
bpsp = BPSP.random_instance(num_cars=num_cars, seed=seed)

# Asserting if the generated car sequence in BPSP instance is identical
# to the sequence produced by our lambda function.
# This confirms the random instance generation works as expected.
self.assertTrue(all(bpsp.car_sequence == create_car_seq(num_cars, seed)),
"The generated car sequence does not match the expected shuffled sequence.")
self.assertTrue(
all(bpsp.car_sequence == create_car_seq(num_cars, seed)),
"The generated car sequence does not match the expected shuffled sequence.",
)

def test_bpsp_car_pos(self):
"""Test the retrieval of car positions."""
Expand All @@ -140,22 +147,26 @@ def test_bpsp_graph(self):
"""Test the generation of a graph representation of the BPSP instance."""
car_sequence = [3, 1, 0, 0, 2, 2, 4, 4, 3, 1]
G = nx.Graph()
G.add_weighted_edges_from([[3, 1, -2], [3, 4, -1], [1, 0, -1], [0, 2, 1], [2, 4, 1]])
G.add_weighted_edges_from(
[[3, 1, -2], [3, 4, -1], [1, 0, -1], [0, 2, 1], [2, 4, 1]]
)

bpsp_graph = BPSP(car_sequence).graph

assert nx.is_isomorphic(G, bpsp_graph), "The created graph and BPSP graph are not identical,"
assert nx.is_isomorphic(
G, bpsp_graph
), "The created graph and BPSP graph are not identical,"

def test_bpsp_docplex_bpsp_model(self):
"""Test if the docplex model representation of BPSP is generated."""
bpsp = BPSP.random_instance(num_cars=2, seed=1234)

# Obtain the model
mdl = bpsp.docplex_bpsp_model # Access as attribute due to @property decorator

# Verify that the function returns a valid model instance
self.assertIsInstance(mdl, Model, "Model is not an instance of DOcplex Model")

# Manually retrieve binary variables based on their expected names
sequence = bpsp.car_sequence
expected_var_names = [f"w_{w}_{i}" for i, w in enumerate(sequence)]
Expand All @@ -168,13 +179,19 @@ def test_bpsp_docplex_bpsp_model(self):
self.assertTrue(var.is_binary(), f"Variable {var} is not binary")

# Check number of constraints
self.assertEqual(mdl.number_of_constraints, 11, "Unexpected number of constraints")

self.assertEqual(
mdl.number_of_constraints, 11, "Unexpected number of constraints"
)

# Check if objective function exists
self.assertIsNotNone(mdl.objective_expr, "Objective function is missing")

# Check if the objective is to minimize
self.assertEqual(mdl.objective_sense, ObjectiveSense.Minimize, "Objective should be of type 'minimize'")
self.assertEqual(
mdl.objective_sense,
ObjectiveSense.Minimize,
"Objective should be of type 'minimize'",
)

def test_bpsp_solve_cplex(self):
"""
Expand All @@ -191,7 +208,7 @@ def test_bpsp_solve_cplex(self):
def test_bpsp_paintseq_from_bits(self):
"""Test the solution of the BPSP problem using QAOA."""
bpsp = BPSP(np.array([0, 1, 0, 1]))
sequence, color_swaps = bpsp.paintseq_from_bits('10')
sequence, color_swaps = bpsp.paintseq_from_bits("10")
self.assertEqual(sequence, [1, 0, 0, 1])
self.assertEqual(color_swaps, 2)

Expand All @@ -209,5 +226,6 @@ def test_bpsp_solve_greedy(self):
self.assertEqual(sequence, [0, 0, 1, 1])
self.assertEqual(color_swaps, 1)


if __name__ == "__main__":
unittest.main()
7 changes: 6 additions & 1 deletion src/openqaoa-core/tests/test_qubo.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,12 @@ def test_problem_instance(self):
],
"sherrington_kirkpatrick": ["problem_type", "G"],
"k_color": ["problem_type", "G", "k", "penalty"],
"binary_paint_shop_problem": ["problem_type", "car_sequence", "car_positions", "bpsp_graph"],
"binary_paint_shop_problem": [
"problem_type",
"car_sequence",
"car_positions",
"bpsp_graph",
],
"generic_qubo": ["problem_type"],
}

Expand Down
2 changes: 1 addition & 1 deletion src/openqaoa-qiskit/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
qiskit>=0.36.1
qiskit>=0.36.1,<1.0
qiskit-ibm-provider
qiskit-aer
Loading