নোট
এই পৃষ্ঠাটি docs/tutorials/03_minimum_eigen_optimizer.ipynb -থেকে বানানো হয়েছে।
ন্যূনতম আইজেন অপটিমাইজার¶
ভূমিকা¶
An interesting class of optimization problems to be addressed by quantum computing are Quadratic Unconstrained Binary Optimization (QUBO) problems. Finding the solution to a QUBO is equivalent to finding the ground state of a corresponding Ising Hamiltonian, which is an important problem not only in optimization, but also in quantum chemistry and physics. For this translation, the binary variables taking values in \(\{0, 1\}\) are replaced by spin variables taking values in \(\{-1, +1\}\), which allows one to replace the resulting spin variables by Pauli Z matrices, and thus, an Ising Hamiltonian. For more details on this mapping we refer to [1].
Qiskit provides automatic conversion from a suitable QuadraticProgram
to an Ising Hamiltonian, which then allows leveraging all the SamplingMinimumEigensolver
implementations, such as
SamplingVQE
,QAOA
, orNumpyMinimumEigensolver
(classical exact method).
Note 1: MinimumEigenOptimizer
does not support qiskit.algorithms.minimum_eigensolver.VQE
. But qiskit.algorithms.minimum_eigensolver.SamplingVQE
can be used instead.
Note 2: MinimumEigenOptimizer
can use NumpyMinimumEigensolver
as an exception case though it inherits MinimumEigensolver
(not SamplingMinimumEigensolver
).
Qiskit Optimization provides a the MinimumEigenOptimizer
class, which wraps the translation to an Ising Hamiltonian (in Qiskit Terra also called Operator
), the call to a MinimumEigensolver
, and the translation of the results back to an OptimizationResult
.
In the following we first illustrate the conversion from a QuadraticProgram
to an Operator
and then show how to use the MinimumEigenOptimizer
with different MinimumEigensolver
s to solve a given QuadraticProgram
. The algorithms in Qiskit automatically try to convert a given problem to the supported problem class if possible, for instance, the MinimumEigenOptimizer
will automatically translate integer variables to binary variables or add linear equality constraints as a
quadratic penalty term to the objective. It should be mentioned that a QiskitOptimizationError
will be thrown if conversion of a quadratic program with integer variables is attempted.
QAOA
এর সার্কিট গভীরতা সম্ভাব্যভাবে সমস্যার আকারের সাথে বৃদ্ধি করতে হবে, যা নিকট-মেয়াদী কোয়ান্টাম ডিভাইসের জন্য নিষিদ্ধ হতে পারে। একটি সম্ভাব্য সমাধান হল পুনরাবৃত্তিমূলক QAOA, যা [২] -এ চালু করা হয়েছে। কিস্কিট এই ধারণাকে RecursiveMinimumEigenOptimizer
এ সাধারণ করে, যা এই টিউটোরিয়ালের শেষে চালু করা হয়েছে।
তথ্যসূত্র (রেফারেন্স)¶
[১] A. Lucas, Ising formulations of many NP problems, Front. Phys., 12 (2014).
একটি QUBO কে অপারেটরে রূপান্তর করা¶
[1]:
from qiskit.utils import algorithm_globals
from qiskit.algorithms.minimum_eigensolvers import QAOA, NumPyMinimumEigensolver
from qiskit.algorithms.optimizers import COBYLA
from qiskit.primitives import Sampler
from qiskit_optimization.algorithms import (
MinimumEigenOptimizer,
RecursiveMinimumEigenOptimizer,
SolutionSample,
OptimizationResultStatus,
)
from qiskit_optimization import QuadraticProgram
from qiskit.visualization import plot_histogram
from typing import List, Tuple
import numpy as np
[2]:
# create a QUBO
qubo = QuadraticProgram()
qubo.binary_var("x")
qubo.binary_var("y")
qubo.binary_var("z")
qubo.minimize(linear=[1, -2, 3], quadratic={("x", "y"): 1, ("x", "z"): -1, ("y", "z"): 2})
print(qubo.prettyprint())
Problem name:
Minimize
x*y - x*z + 2*y*z + x - 2*y + 3*z
Subject to
No constraints
Binary variables (3)
x y z
Next we translate this QUBO into an Ising operator. This results not only in an Operator
but also in a constant offset to be taken into account to shift the resulting value.
[3]:
op, offset = qubo.to_ising()
print("offset: {}".format(offset))
print("operator:")
print(op)
offset: 1.5
operator:
-0.5 * IIZ
+ 0.25 * IZI
- 1.75 * ZII
+ 0.25 * IZZ
- 0.25 * ZIZ
+ 0.5 * ZZI
Sometimes a QuadraticProgram
might also directly be given in the form of an Operator
. For such cases, Qiskit also provides a translator from an Operator
back to a QuadraticProgram
, which we illustrate in the following.
[4]:
qp = QuadraticProgram()
qp.from_ising(op, offset, linear=True)
print(qp.prettyprint())
Problem name:
Minimize
x0*x1 - x0*x2 + 2*x1*x2 + x0 - 2*x1 + 3*x2
Subject to
No constraints
Binary variables (3)
x0 x1 x2
This translator allows, for instance, one to translate an Operator
to a QuadraticProgram
and then solve the problem with other algorithms that are not based on the Ising Hamiltonian representation, such as the GroverOptimizer
.
MinimumEigenOptimizer দিয়ে একটি QUBO সমাধান করা¶
আমরা "MinimumEigensolver" দিয়ে শুরু করি যা আমরা ব্যবহার করতে চাই।
[5]:
algorithm_globals.random_seed = 10598
qaoa_mes = QAOA(sampler=Sampler(), optimizer=COBYLA(), initial_point=[0.0, 0.0])
exact_mes = NumPyMinimumEigensolver()
তারপরে, আমরা "MinimumEigenOptimizer" তৈরি করতে "MinimumEigensolver" ব্যবহার করি।
[6]:
qaoa = MinimumEigenOptimizer(qaoa_mes) # using QAOA
exact = MinimumEigenOptimizer(exact_mes) # using the exact classical numpy minimum eigen solver
এই ছোট উদাহরণের জন্য সর্বোত্তম মানদণ্ড সমাধান পেতে আমরা প্রথমে শাস্ত্রীয় সঠিক NumPyMinimumEigensolver
এর উপর ভিত্তি করে MinimumEigenOptimizer
ব্যবহার করি।
[7]:
exact_result = exact.solve(qubo)
print(exact_result.prettyprint())
objective function value: -2.0
variable values: x=0.0, y=1.0, z=0.0
status: SUCCESS
পরবর্তীতে আমরা একই সমস্যার জন্য QAOA
এর উপর ভিত্তি করে MinimumEigenOptimizer
প্রয়োগ করি।.
[8]:
qaoa_result = qaoa.solve(qubo)
print(qaoa_result.prettyprint())
objective function value: -2.0
variable values: x=0.0, y=1.0, z=0.0
status: SUCCESS
নমুনা (স্যাম্পল) এর বিশ্লেষণ¶
OptimizationResult
provides useful information in the form of SolutionSample
s (here denoted as samples). Each SolutionSample
contains information about the input values (x
), the corresponding objective function value (fval
), the fraction of samples corresponding to that input (probability
), and the solution status
(SUCCESS
, FAILURE
, INFEASIBLE
). Multiple samples corresponding to the same input are consolidated into a single SolutionSample
(with its
probability
attribute being the aggregate fraction of samples represented by that SolutionSample
).
[9]:
print("variable order:", [var.name for var in qaoa_result.variables])
for s in qaoa_result.samples:
print(s)
variable order: ['x', 'y', 'z']
SolutionSample(x=array([0., 1., 0.]), fval=-2.0, probability=0.4410306097905226, status=<OptimizationResultStatus.SUCCESS: 0>)
SolutionSample(x=array([0., 0., 0.]), fval=0.0, probability=0.22763693649873265, status=<OptimizationResultStatus.SUCCESS: 0>)
SolutionSample(x=array([1., 1., 0.]), fval=0.0, probability=0.14136368254300133, status=<OptimizationResultStatus.SUCCESS: 0>)
SolutionSample(x=array([1., 0., 0.]), fval=1.0, probability=0.12574358779906872, status=<OptimizationResultStatus.SUCCESS: 0>)
SolutionSample(x=array([0., 0., 1.]), fval=3.0, probability=0.020510231887331747, status=<OptimizationResultStatus.SUCCESS: 0>)
SolutionSample(x=array([1., 0., 1.]), fval=3.0, probability=0.030444770051099967, status=<OptimizationResultStatus.SUCCESS: 0>)
SolutionSample(x=array([0., 1., 1.]), fval=3.0, probability=0.012349858838771063, status=<OptimizationResultStatus.SUCCESS: 0>)
SolutionSample(x=array([1., 1., 1.]), fval=4.0, probability=0.0009203225914718031, status=<OptimizationResultStatus.SUCCESS: 0>)
আমরা তাদের অবস্থা বা সম্ভাব্যতা অনুযায়ী নমুনাগুলি ফিল্টার করতে চাই।
[10]:
def get_filtered_samples(
samples: List[SolutionSample],
threshold: float = 0,
allowed_status: Tuple[OptimizationResultStatus] = (OptimizationResultStatus.SUCCESS,),
):
res = []
for s in samples:
if s.status in allowed_status and s.probability > threshold:
res.append(s)
return res
[11]:
filtered_samples = get_filtered_samples(
qaoa_result.samples, threshold=0.005, allowed_status=(OptimizationResultStatus.SUCCESS,)
)
for s in filtered_samples:
print(s)
SolutionSample(x=array([0., 1., 0.]), fval=-2.0, probability=0.4410306097905226, status=<OptimizationResultStatus.SUCCESS: 0>)
SolutionSample(x=array([0., 0., 0.]), fval=0.0, probability=0.22763693649873265, status=<OptimizationResultStatus.SUCCESS: 0>)
SolutionSample(x=array([1., 1., 0.]), fval=0.0, probability=0.14136368254300133, status=<OptimizationResultStatus.SUCCESS: 0>)
SolutionSample(x=array([1., 0., 0.]), fval=1.0, probability=0.12574358779906872, status=<OptimizationResultStatus.SUCCESS: 0>)
SolutionSample(x=array([0., 0., 1.]), fval=3.0, probability=0.020510231887331747, status=<OptimizationResultStatus.SUCCESS: 0>)
SolutionSample(x=array([1., 0., 1.]), fval=3.0, probability=0.030444770051099967, status=<OptimizationResultStatus.SUCCESS: 0>)
SolutionSample(x=array([0., 1., 1.]), fval=3.0, probability=0.012349858838771063, status=<OptimizationResultStatus.SUCCESS: 0>)
যদি আমরা ফলাফলের একটি ভাল ধারণা পেতে চাই, পরিসংখ্যান খুব সহায়ক, উভয় নৈর্ব্যক্তিক অন্বয় (অব্জেক্টিভ ফাংশন) মান এবং তাদের নিজ নিজ সম্ভাবনার ক্ষেত্রে। সুতরাং, ফলাফল বোঝার জন্য গড় এবং মান বিচ্যুতি খুবই মৌলিক।
[12]:
fvals = [s.fval for s in qaoa_result.samples]
probabilities = [s.probability for s in qaoa_result.samples]
[13]:
np.mean(fvals)
[13]:
1.5
[14]:
np.std(fvals)
[14]:
1.9364916731037085
Finally, despite all the number-crunching, visualization is usually the best early-analysis approach.
[15]:
samples_for_plot = {
" ".join(f"{qaoa_result.variables[i].name}={int(v)}" for i, v in enumerate(s.x)): s.probability
for s in filtered_samples
}
samples_for_plot
[15]:
{'x=0 y=1 z=0': 0.4410306097905226,
'x=0 y=0 z=0': 0.22763693649873265,
'x=1 y=1 z=0': 0.14136368254300133,
'x=1 y=0 z=0': 0.12574358779906872,
'x=0 y=0 z=1': 0.020510231887331747,
'x=1 y=0 z=1': 0.030444770051099967,
'x=0 y=1 z=1': 0.012349858838771063}
[16]:
plot_histogram(samples_for_plot)
[16]:

RecursiveMinimumEigenOptimizer¶
RecursiveMinimumEigenOptimizer
একটি MinimumEigenOptimizer
কে ইনপুট হিসেবে নেয় এবং সমস্যাটির আকার কমিয়ে আনার জন্য পুনরাবৃত্তিমূলক অপ্টিমাইজেশন স্কিম প্রয়োগ করে। একবার উৎপন্ন মধ্যবর্তী সমস্যার আকার একটি নির্দিষ্ট ক্রান্তিমান (min_num_vars
) এর নিচে হয়ে গেলে, RecursiveMinimumEigenOptimizer
অন্য সমাধানকারী (min_num_vars_optimizer
) ব্যবহার করে, যেমন, একটি সঠিক শাস্ত্রীয় সমাধানকারী যেমন NumPyMinimumEigensolver
এর উপর ভিত্তি করে CPLEX বা MinimumEigenOptimizer
।
In the following, we show how to use the RecursiveMinimumEigenOptimizer
using the two MinimumEigenOptimizer
s introduced before.
প্রথমে আমরা RecursiveMinimumEigenOptimizer
তৈরি করবো এমন ভাবে যাতে সমস্যাটা ৩ টি চল রাশি থেকে ১ টা চল রাশি এ নেমে আসে তারপর আমরা ঐ সলভারটাই ব্যবহার করি অন্তিম চল রাশি টার জন্যে। তারপর আমরা solve
কে ডাকি এই সমস্যাটাকে অনুকূলিতকরণ করার জন্যে।
[17]:
rqaoa = RecursiveMinimumEigenOptimizer(qaoa, min_num_vars=1, min_num_vars_optimizer=exact)
[18]:
rqaoa_result = rqaoa.solve(qubo)
print(rqaoa_result.prettyprint())
objective function value: -2.0
variable values: x=0.0, y=1.0, z=0.0
status: SUCCESS
[19]:
filtered_samples = get_filtered_samples(
rqaoa_result.samples, threshold=0.005, allowed_status=(OptimizationResultStatus.SUCCESS,)
)
[20]:
samples_for_plot = {
" ".join(f"{rqaoa_result.variables[i].name}={int(v)}" for i, v in enumerate(s.x)): s.probability
for s in filtered_samples
}
samples_for_plot
[20]:
{'x=0 y=1 z=0': 1.0}
[21]:
plot_histogram(samples_for_plot)
[21]:

[22]:
import qiskit.tools.jupyter
%qiskit_version_table
%qiskit_copyright
Version Information
Qiskit Software | Version |
---|---|
qiskit-terra | 0.23.0 |
qiskit-aer | 0.11.1 |
qiskit-optimization | 0.5.0 |
qiskit-machine-learning | 0.6.0 |
System information | |
Python version | 3.9.15 |
Python compiler | Clang 14.0.0 (clang-1400.0.29.102) |
Python build | main, Oct 11 2022 22:27:25 |
OS | Darwin |
CPUs | 4 |
Memory (Gb) | 16.0 |
Mon Dec 05 22:42:36 2022 JST |
This code is a part of Qiskit
© Copyright IBM 2017, 2022.
This code is licensed under the Apache License, Version 2.0. You may
obtain a copy of this license in the LICENSE.txt file in the root directory
of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
Any modifications or derivative works of this code must retain this
copyright notice, and modified files need to carry a notice indicating
that they have been altered from the originals.
[ ]: