Skip to content
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ This repository is still in development: new functionality is being added and th
| 11 | Bug fix in train pre-processing data | #24 |
| 12 | More data in result saving in train.py | #26 |
| 13 | Create PPEvaluator from configs | #25 |
| 14 | Custom ansatz operator to state vector | #29 |

## IBM Public Repository Disclosure

Expand Down
21 changes: 16 additions & 5 deletions qaoa_training_pipeline/evaluation/statevector_evaluator.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

"""Statevector-based QAOA evaluator."""

from typing import Dict, List, Optional
from typing import Dict, List, Optional, Union

from qiskit import QuantumCircuit
from qiskit.circuit.library import qaoa_ansatz
Expand Down Expand Up @@ -43,7 +43,7 @@ def evaluate(
params: List[float],
mixer: Optional[QuantumCircuit] = None,
initial_state: Optional[QuantumCircuit] = None,
ansatz_circuit: Optional[QuantumCircuit] = None,
ansatz_circuit: Optional[Union[QuantumCircuit, SparsePauliOp]] = None,
) -> float:
"""Evaluate the expectation value of a cost operator given a set of parameters.

Expand All @@ -56,16 +56,27 @@ def evaluate(
initial_state (Optional[QuantumCircuit], optional): the initial state of the QAOA.
"""

if ansatz_circuit is not None:
raise NotImplementedError("Custom ansatz circuits are not yet supported.")
if isinstance(ansatz_circuit, SparsePauliOp):
ansatz_op = ansatz_circuit
elif ansatz_circuit is None:
ansatz_op = cost_op
else:
raise NotImplementedError(
"Custom ansatz circuits in format"
f"{ansatz_circuit.__class__.__name__} are not yet supported."
)

circuit = qaoa_ansatz(
cost_op,
ansatz_op,
reps=len(params) // 2,
mixer_operator=mixer,
initial_state=initial_state,
)

# Prevents the edge case where the cost op is the identity.
if len(circuit.parameters) != len(params):
raise ValueError("The QAOA Circuit does not have the correct number of parameters. ")

result = self.primitive.run([(circuit, cost_op, params)]).result()

return float(result[0].data.evs)
Expand Down
2 changes: 1 addition & 1 deletion qaoa_training_pipeline/training/param_result.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def __init__(
"system": platform.system(),
"processor": platform.processor(),
"platform": platform.platform(),
"qaoa_training_pipeline_version": 13,
"qaoa_training_pipeline_version": 14,
}

# Convert, e.g., np.float to float
Expand Down
16 changes: 16 additions & 0 deletions test/evaluation/test_statevector.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,19 @@ def test_optimize(self):
result = trainer.train(cost_op=self.cost_op, params0=[0.2, 0.3])

self.assertGreaterEqual(len(result["energy_history"]), 3)

def test_custom_ansatz(self):
"""Test that we can construct the ansatz from a different operator."""
ansatz_op = SparsePauliOp.from_list([("ZI", 1)])

angles = [1.2, 1.3]

energy1 = self.evaluator.evaluate(self.cost_op, params=angles, ansatz_circuit=ansatz_op)
energy2 = self.evaluator.evaluate(self.cost_op, params=angles)

self.assertTrue(abs(energy1 - energy2) > 0.1)

energy1 = self.evaluator.evaluate(self.cost_op, params=angles, ansatz_circuit=self.cost_op)
energy2 = self.evaluator.evaluate(self.cost_op, params=angles)

self.assertAlmostEqual(energy1, energy2, places=6)
Loading