Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
3945892
fix unittest of grover optimizer
a-matsuo Apr 22, 2021
784cf7c
fix
a-matsuo Apr 22, 2021
546265a
fix lint
a-matsuo Apr 22, 2021
92b87ee
fix bit ordering
a-matsuo Apr 22, 2021
0ad49c1
added unittest
a-matsuo Apr 22, 2021
1c3dcb5
fix bitordering for statevector
a-matsuo Apr 22, 2021
066f54a
fix unittest and timing of updating samples
a-matsuo Apr 23, 2021
8781488
clean up
a-matsuo Apr 23, 2021
e9c4f05
fix lint
a-matsuo Apr 23, 2021
393b6b5
fix grover_optimizer as well
a-matsuo Apr 23, 2021
a710d74
added test for samples
a-matsuo Apr 23, 2021
70a8bff
fix lint
a-matsuo Apr 23, 2021
f8c8272
changed to use assert_array_almost_equal
a-matsuo Apr 23, 2021
cef9a89
fix slice
a-matsuo Apr 23, 2021
73861a6
remove change of #96
a-matsuo Apr 23, 2021
62e00fc
remove change of #96 for unittest
a-matsuo Apr 23, 2021
f8a65c8
Merge branch 'main' into fix_bit_order
t-imamichi Apr 24, 2021
1374675
Update qiskit_optimization/algorithms/grover_optimizer.py
t-imamichi Apr 24, 2021
7543f8f
Revert "Update qiskit_optimization/algorithms/grover_optimizer.py"
t-imamichi Apr 24, 2021
0aea59b
Merge branch 'main' into fix_bit_order
t-imamichi Apr 25, 2021
586851d
fix grover opt's bit ordering
a-matsuo Apr 26, 2021
06e8d1e
Merge branch 'fix_bit_order' of github.com:a-matsuo/qiskit-optimizati…
a-matsuo Apr 26, 2021
ebf9de5
fix linting
a-matsuo Apr 26, 2021
3244a60
clean test
a-matsuo Apr 26, 2021
26274da
add print
a-matsuo Apr 26, 2021
7ac3aeb
skip test temporarily. I will fix it
a-matsuo Apr 26, 2021
94e4a7c
removed temporarily
a-matsuo Apr 26, 2021
0797640
merge from main, fix conflicts
manoelmarques Apr 26, 2021
dfc8ef9
add print
a-matsuo Apr 26, 2021
c2b3847
add print int_v
a-matsuo Apr 26, 2021
e9d5ba9
align print samples
a-matsuo Apr 26, 2021
80a2afb
remove sqrt
a-matsuo Apr 27, 2021
1653b6e
move print eigen_vector
a-matsuo Apr 27, 2021
cee591d
move circuit results print
a-matsuo Apr 27, 2021
465fc0a
modified seed
a-matsuo Apr 27, 2021
76307cd
move raw_samples____print
a-matsuo Apr 27, 2021
433ba37
remove print
a-matsuo Apr 27, 2021
168fd22
changed to use basic aer
a-matsuo Apr 27, 2021
1abd994
remove print2
a-matsuo Apr 27, 2021
f3f6f5e
fix style
a-matsuo Apr 27, 2021
e3fa646
changed to use Aer
a-matsuo Apr 27, 2021
ced7129
print count_ops()
a-matsuo Apr 27, 2021
9d0482b
Merge branch 'main' into fix_bit_order
manoelmarques Apr 27, 2021
709a39a
check statevector as well
a-matsuo Apr 28, 2021
e6eeb82
Merge branch 'fix_bit_order' of github.com:a-matsuo/qiskit-optimizati…
a-matsuo Apr 28, 2021
3a5682d
remove print
a-matsuo Apr 28, 2021
43a5489
revert seed
a-matsuo Apr 28, 2021
dfc9f5c
remove print
a-matsuo Apr 28, 2021
84de846
add print
a-matsuo Apr 28, 2021
4d8af9d
remove print, change seed and increase # of trials
a-matsuo Apr 28, 2021
1d0cab5
fix lint
a-matsuo Apr 28, 2021
1858917
add more tests for grover_opt
a-matsuo Apr 28, 2021
615fa98
more unittests
a-matsuo Apr 30, 2021
30679f2
fix linting
a-matsuo Apr 30, 2021
9db6d03
Merge branch 'main' into fix_bit_order
a-matsuo May 6, 2021
3d69a72
clear prints and fix formatting
a-matsuo May 6, 2021
8d46427
fix formatting
a-matsuo May 6, 2021
89c7814
fix
a-matsuo May 7, 2021
f87606a
Merge branch 'main' into fix_bit_order
a-matsuo May 7, 2021
7599c4c
fix black
a-matsuo May 7, 2021
1723f5f
add comments and rename eigenvector
a-matsuo May 7, 2021
c2e5342
add bit ordering test case for QAOA
a-matsuo May 7, 2021
417144c
fix lint
a-matsuo May 7, 2021
6dda6ed
Merge branch 'main' into fix_bit_order
t-imamichi May 9, 2021
9a64cd4
Merge branch 'main' into fix_bit_order
t-imamichi May 10, 2021
adc3280
remove some pylint directives and clarify qubit order in from_ising a…
t-imamichi May 12, 2021
4518f7e
add reno
t-imamichi May 12, 2021
ef22a05
Merge branch 'main' into fix_bit_order
t-imamichi May 12, 2021
59f7149
Merge branch 'main' into fix_bit_order
t-imamichi May 12, 2021
6aa059e
fix mypy
t-imamichi May 13, 2021
311d648
fix spell
t-imamichi May 13, 2021
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 .pylintdict
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ qp
quadratically
quadraticconstraint
quadraticprogram
quantuminstance
qubit
qubits
qubo
Expand Down
14 changes: 7 additions & 7 deletions qiskit_optimization/algorithms/grover_optimizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,10 @@ def __init__(
TypeError: When there one of converters is an invalid type.
"""
self._num_value_qubits = num_value_qubits
self._num_key_qubits = None
self._num_key_qubits = 0
self._n_iterations = num_iterations
self._quantum_instance = None
self._circuit_results = {} # type: ignore
self._quantum_instance = None # type: Optional[QuantumInstance]
self._circuit_results = {} # type: dict

if quantum_instance is not None:
self.quantum_instance = quantum_instance
Expand Down Expand Up @@ -184,7 +184,7 @@ def solve(self, problem: QuadraticProgram) -> OptimizationResult:
problem_.objective.linear[i] = -val
for (i, j), val in problem_.objective.quadratic.to_dict().items():
problem_.objective.quadratic[i, j] = -val
self._num_key_qubits = len(problem_.objective.linear.to_array()) # type: ignore
self._num_key_qubits = len(problem_.objective.linear.to_array())

# Variables for tracking the optimum.
optimum_found = False
Expand Down Expand Up @@ -256,13 +256,13 @@ def solve(self, problem: QuadraticProgram) -> OptimizationResult:
threshold = optimum_value

# trace out work qubits and store samples
Comment thread
t-imamichi marked this conversation as resolved.
if self._quantum_instance.is_statevector: # type: ignore
if self._quantum_instance.is_statevector:
indices = list(range(n_key, len(outcome)))
rho = partial_trace(self._circuit_results, indices)
self._circuit_results = np.diag(rho.data) ** 0.5
else:
self._circuit_results = {
i[0:n_key]: v for i, v in self._circuit_results.items()
i[-1 * n_key :]: v for i, v in self._circuit_results.items()
}

raw_samples = self._eigenvector_to_solutions(
Expand Down Expand Up @@ -347,7 +347,7 @@ def _get_probs(self, qc: QuantumCircuit) -> Dict[str, float]:
state = result.get_counts(qc)
shots = self.quantum_instance.run_config.shots
hist = {key[::-1]: val / shots for key, val in state.items() if val > 0}
self._circuit_results = {b[::-1]: np.sqrt(v / shots) for (b, v) in state.items()}
self._circuit_results = {b: (v / shots) ** 0.5 for (b, v) in state.items()}
return hist

@staticmethod
Expand Down
13 changes: 7 additions & 6 deletions qiskit_optimization/algorithms/optimization_algorithm.py
Original file line number Diff line number Diff line change
Expand Up @@ -535,12 +535,12 @@ def _eigenvector_to_solutions(
TypeError: If the type of eigenvector is not supported.
"""
if isinstance(eigenvector, DictStateFn):
eigenvector = {bitstr: val ** 2 for (bitstr, val) in eigenvector.primitive.items()}
eigenvector = eigenvector.primitive
elif isinstance(eigenvector, StateFn):
eigenvector = eigenvector.to_matrix()

def generate_solution(bitstr, qubo, probability):
x = np.fromiter(list(bitstr), dtype=int)
x = np.fromiter(list(bitstr[::-1]), dtype=int)
fval = qubo.objective.evaluate(x)
return SolutionSample(
x=x,
Expand All @@ -551,10 +551,11 @@ def generate_solution(bitstr, qubo, probability):

solutions = []
if isinstance(eigenvector, dict):
all_counts = sum(eigenvector.values())
# When eigenvector is a dict, square the values since the values are normalized.
# See https://github.com/Qiskit/qiskit-terra/pull/5496 for more details.
probabilities = {bitstr: val ** 2 for (bitstr, val) in eigenvector.items()}
# iterate over all samples
for bitstr, count in eigenvector.items():
sampling_probability = count / all_counts
for bitstr, sampling_probability in probabilities.items():
# add the bitstring, if the sampling probability exceeds the threshold
if sampling_probability >= min_probability:
solutions.append(generate_solution(bitstr, qubo, sampling_probability))
Expand All @@ -567,7 +568,7 @@ def generate_solution(bitstr, qubo, probability):
for i, sampling_probability in enumerate(probabilities):
# add the i-th state if the sampling probability exceeds the threshold
if sampling_probability >= min_probability:
bitstr = "{:b}".format(i).rjust(num_qubits, "0")[::-1]
bitstr = "{:b}".format(i).rjust(num_qubits, "0")
solutions.append(generate_solution(bitstr, qubo, sampling_probability))

else:
Expand Down
12 changes: 10 additions & 2 deletions qiskit_optimization/problems/quadratic_program.py
Original file line number Diff line number Diff line change
Expand Up @@ -1221,7 +1221,7 @@ def substitute_variables(
Returns:
An optimization problem by substituting variables with constants or other variables.
If the substitution is valid, `QuadraticProgram.status` is still
`QuadraticProgram.Status.VALIAD`.
`QuadraticProgram.Status.VALID`.
Otherwise, it gets `QuadraticProgram.Status.INFEASIBLE`.

Raises:
Expand All @@ -1234,6 +1234,10 @@ def substitute_variables(
def to_ising(self) -> Tuple[OperatorBase, float]:
"""Return the Ising Hamiltonian of this problem.

Variables are mapped to qubits in the same order, i.e.,
i-th variable is mapped to i-th qubit.
See https://github.com/Qiskit/qiskit-terra/issues/1148 for details.

Returns:
qubit_op: The qubit operator for the problem
offset: The constant value in the Ising Hamiltonian.
Expand Down Expand Up @@ -1339,6 +1343,10 @@ def from_ising(
) -> None:
r"""Create a quadratic program from a qubit operator and a shift value.

Variables are mapped to qubits in the same order, i.e.,
i-th variable is mapped to i-th qubit.
See https://github.com/Qiskit/qiskit-terra/issues/1148 for details.

Args:
qubit_op: The qubit operator of the problem.
offset: The constant value in the Ising Hamiltonian.
Expand Down Expand Up @@ -1542,7 +1550,7 @@ def substitute_variables(
Returns:
An optimization problem by substituting variables with constants or other variables.
If the substitution is valid, `QuadraticProgram.status` is still
`QuadraticProgram.Status.VALIAD`.
`QuadraticProgram.Status.VALID`.
Otherwise, it gets `QuadraticProgram.Status.INFEASIBLE`.

Raises:
Expand Down
8 changes: 8 additions & 0 deletions releasenotes/notes/fix-bit-ordering-e807ec9f4b206ec3.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
fixes:
- |
Fix bit ordering in :class`qiskit_optimization.algorithms.minimum_eigen_optimizer.MinimumEigenOptimizer`
with qasm_simulator.
- |
Fix probabilities of solution samples with qasm_simulator.
See https://github.com/Qiskit/qiskit-optimization/pull/97 for details.
67 changes: 49 additions & 18 deletions test/algorithms/test_grover_optimizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ def validate_results(self, problem, results):
# Get expected value.
solver = MinimumEigenOptimizer(NumPyMinimumEigensolver())
comp_result = solver.solve(problem)

# Validate results.
np.testing.assert_array_almost_equal(comp_result.x, results.x)
self.assertEqual(comp_result.fval, results.fval)
Expand Down Expand Up @@ -145,6 +144,7 @@ def test_qubo_gas_int_paper_example(self, simulator):
def test_converter_list(self):
"""Test converters list"""
# Input.

model = Model()
x_0 = model.binary_var(name="x0")
x_1 = model.binary_var(name="x1")
Expand All @@ -164,6 +164,7 @@ def test_converter_list(self):
)
results = gmf.solve(op)
self.validate_results(op, results)

# a list of converters
ineq2eq = InequalityToEquality()
int2bin = IntegerToBinary()
Expand All @@ -187,32 +188,62 @@ def test_converter_list(self):
converters=invalid,
)

def test_samples_and_raw_samples(self):
@data("sv", "qasm")
def test_samples_and_raw_samples(self, simulator):
"""Test samples and raw_samples"""
op = QuadraticProgram()
op.integer_var(0, 3, "x")
op.binary_var("y")
op.minimize(linear={"x": 1, "y": 2})
op.linear_constraint(linear={"x": 1, "y": 1}, sense=">=", rhs=1, name="xy")
q_instance = self.sv_simulator if simulator == "sv" else self.qasm_simulator
grover_optimizer = GroverOptimizer(8, num_iterations=10, quantum_instance=q_instance)
opt_sol = 1
success = OptimizationResultStatus.SUCCESS
algorithm_globals.random_seed = 1
grover_optimizer = GroverOptimizer(
8, num_iterations=5, quantum_instance=self.qasm_simulator
)
result = grover_optimizer.solve(op)
self.assertEqual(len(result.samples), 8)
self.assertEqual(len(result.raw_samples), 32)
self.assertAlmostEqual(sum(s.probability for s in result.samples), 1)
self.assertAlmostEqual(sum(s.probability for s in result.raw_samples), 1)
self.assertAlmostEqual(min(s.fval for s in result.samples), 0)
self.assertAlmostEqual(min(s.fval for s in result.samples if s.status == success), opt_sol)
self.assertAlmostEqual(min(s.fval for s in result.raw_samples), opt_sol)
for sample in result.raw_samples:
results = grover_optimizer.solve(op)
self.assertEqual(len(results.samples), 8)
self.assertEqual(len(results.raw_samples), 32)
self.assertAlmostEqual(sum(s.probability for s in results.samples), 1)
self.assertAlmostEqual(sum(s.probability for s in results.raw_samples), 1)
self.assertAlmostEqual(min(s.fval for s in results.samples), 0)
self.assertAlmostEqual(min(s.fval for s in results.samples if s.status == success), opt_sol)
self.assertAlmostEqual(min(s.fval for s in results.raw_samples), opt_sol)
for sample in results.raw_samples:
self.assertEqual(sample.status, success)
np.testing.assert_array_almost_equal(results.x, results.samples[0].x)
self.assertAlmostEqual(results.fval, results.samples[0].fval)
self.assertEqual(results.status, results.samples[0].status)
self.assertAlmostEqual(results.fval, results.raw_samples[0].fval)
self.assertEqual(results.status, results.raw_samples[0].status)
np.testing.assert_array_almost_equal([1, 0, 0, 0, 0], results.raw_samples[0].x)

@data("sv", "qasm")
def test_bit_ordering(self, simulator):
"""Test bit ordering"""
# test minimize
algorithm_globals.random_seed = 2
q_instance = self.sv_simulator if simulator == "sv" else self.qasm_simulator
mdl = Model("docplex model")
x = mdl.binary_var("x")
y = mdl.binary_var("y")
mdl.minimize(x - 2 * y)
op = QuadraticProgram()
op.from_docplex(mdl)
opt_sol = -2
success = OptimizationResultStatus.SUCCESS
grover_optimizer = GroverOptimizer(3, num_iterations=10, quantum_instance=q_instance)
results = grover_optimizer.solve(op)
self.assertEqual(results.fval, opt_sol)
np.testing.assert_array_almost_equal(results.x, [0, 1])
self.assertEqual(results.status, success)
results.raw_samples.sort(key=lambda x: x.probability, reverse=True)
self.assertAlmostEqual(sum(s.probability for s in results.samples), 1, delta=1e-5)
self.assertAlmostEqual(sum(s.probability for s in results.raw_samples), 1, delta=1e-5)
self.assertAlmostEqual(min(s.fval for s in results.samples), -2)
self.assertAlmostEqual(min(s.fval for s in results.samples if s.status == success), opt_sol)
self.assertAlmostEqual(min(s.fval for s in results.raw_samples), opt_sol)
for sample in results.raw_samples:
self.assertEqual(sample.status, success)
np.testing.assert_array_almost_equal(result.x, result.raw_samples[0].x[0:2])
self.assertAlmostEqual(result.fval, result.raw_samples[0].fval)
self.assertEqual(result.status, result.raw_samples[0].status)


if __name__ == "__main__":
Expand Down
Loading