注釈
このページは docs/tutorials/01_portfolio_optimization.ipynb から生成されました。
ポートフォリオの最適化#
はじめに#
このチュートリアルでは、
ここで、次の表記を使用します。
は、バイナリー決定変数のベクトルを示し、ピックする資産 ( ) と、ピックしない資産 ( ) を示します。 は、資産のリターンの期待値を定義します。 は、資産間の共分散を指定します は、意思決定者のリスク選好度を制御します。 は予算、つまり の中から選択するアセットの数を表します。
ここで、次の簡略化を想定します。すべての資産は同じ価格 ( 1に正規化 ) を持ち、全予算
等価制約 SamplingVQE
) または Quantum Approximate Optimization Algorithm (QAOA
) を使用する方法について説明します。
この問題に対する実際の量子ハードウェアに関する実験については、例えば以下の論文で報告しています。Improving Variational Quantum Optimization using CVaR. Barkoutsos et al. 2019.
[1]:
from qiskit.circuit.library import TwoLocal
from qiskit.result import QuasiDistribution
from qiskit_aer.primitives import Sampler
from qiskit_algorithms import NumPyMinimumEigensolver, QAOA, SamplingVQE
from qiskit_algorithms.optimizers import COBYLA
from qiskit_finance.applications.optimization import PortfolioOptimization
from qiskit_finance.data_providers import RandomDataProvider
from qiskit_optimization.algorithms import MinimumEigenOptimizer
import numpy as np
import matplotlib.pyplot as plt
import datetime
問題のインスタンスを定義#
ここで、Operatorインスタンスがこのハミルトニアン用に作成されます。 ここでのパウリ項は、ポートフォリオ問題から変換されたイジング・ハミルトニアンからのものです。このノートブックではランダムなポートフォリオ問題を使用します。Loading and Processing Stock-Market Time-Series Data で示されるように、実際の金融データに容易に適用することができます。
[2]:
# set number of assets (= number of qubits)
num_assets = 4
seed = 123
# Generate expected return and covariance matrix from (random) time-series
stocks = [("TICKER%s" % i) for i in range(num_assets)]
data = RandomDataProvider(
tickers=stocks,
start=datetime.datetime(2016, 1, 1),
end=datetime.datetime(2016, 1, 30),
seed=seed,
)
data.run()
mu = data.get_period_return_mean_vector()
sigma = data.get_period_return_covariance_matrix()
[3]:
# plot sigma
plt.imshow(sigma, interpolation="nearest")
plt.show()

[4]:
q = 0.5 # set risk factor
budget = num_assets // 2 # set budget
penalty = num_assets # set parameter to scale the budget penalty term
portfolio = PortfolioOptimization(
expected_returns=mu, covariances=sigma, risk_factor=q, budget=budget
)
qp = portfolio.to_quadratic_program()
qp
[4]:
<QuadraticProgram: minimize 0.001270694296030004*x_0^2 + 7.340221669347328e-05..., 4 variables, 1 constraints, 'Portfolio optimization'>
整ったフォーマットで出力するためのユーティリティー・メソッドをいくつか定義します。
[5]:
def print_result(result):
selection = result.x
value = result.fval
print("Optimal: selection {}, value {:.4f}".format(selection, value))
eigenstate = result.min_eigen_solver_result.eigenstate
probabilities = (
eigenstate.binary_probabilities()
if isinstance(eigenstate, QuasiDistribution)
else {k: np.abs(v) ** 2 for k, v in eigenstate.to_dict().items()}
)
print("\n----------------- Full result ---------------------")
print("selection\tvalue\t\tprobability")
print("---------------------------------------------------")
probabilities = sorted(probabilities.items(), key=lambda x: x[1], reverse=True)
for k, v in probabilities:
x = np.array([int(i) for i in list(reversed(k))])
value = portfolio.to_quadratic_program().objective.evaluate(x)
print("%10s\t%.4f\t\t%.4f" % (x, value, v))
NumPyMinimumEigensolver (古典の参照として)#
まず最初に古典的な手法で問題を解いてみます。
これで、上記で構築したOperatorを、どのように作成されたか、細かいことは気にせず使用できるようになりました。 NumPyMinimumEigensolver のアルゴリズムを設定することで、古典的な参照を行うことができます。 問題は 『ising』 に設定されています。量子計算を使わず古典的に計算しているので、バックエンドは不要です。 結果は辞書として返されます。
[6]:
exact_mes = NumPyMinimumEigensolver()
exact_eigensolver = MinimumEigenOptimizer(exact_mes)
result = exact_eigensolver.solve(qp)
print_result(result)
Optimal: selection [1. 0. 0. 1.], value -0.0149
----------------- Full result ---------------------
selection value probability
---------------------------------------------------
[1 0 0 1] -0.0149 1.0000
SamplingVQE
を使用したソリューション#
これで、 Sampling Variational Quantum Eigensolver (SamplingVQE
) を使用して問題を解くことができます。 使用する最適化プログラムおよび変分フォームを指定します。
[7]:
from qiskit_algorithms.utils import algorithm_globals
algorithm_globals.random_seed = 1234
cobyla = COBYLA()
cobyla.set_options(maxiter=500)
ry = TwoLocal(num_assets, "ry", "cz", reps=3, entanglement="full")
svqe_mes = SamplingVQE(sampler=Sampler(), ansatz=ry, optimizer=cobyla)
svqe = MinimumEigenOptimizer(svqe_mes)
result = svqe.solve(qp)
print_result(result)
Optimal: selection [1. 0. 0. 1.], value -0.0149
----------------- Full result ---------------------
selection value probability
---------------------------------------------------
[0 1 1 0] 0.0008 0.8525
[1 0 0 1] -0.0149 0.0410
[0 0 1 1] -0.0010 0.0312
[0 0 0 1] -0.0008 0.0215
[1 0 1 1] -0.0150 0.0195
[1 0 0 0] -0.0140 0.0088
[0 1 1 1] -0.0000 0.0078
[0 1 0 1] 0.0002 0.0078
[0 1 0 0] 0.0009 0.0059
[1 0 1 0] -0.0140 0.0020
[1 1 0 1] -0.0139 0.0010
[0 0 0 0] 0.0000 0.0010
QAOA
を使用したソリューション#
また、Quantum Approximate Optimization Algorithm (QAOA
) を使用した結果も示します。 これは別の変分アルゴリズムであり、問題に応じて作成される内部の変分フォームを使用します。
[8]:
algorithm_globals.random_seed = 1234
cobyla = COBYLA()
cobyla.set_options(maxiter=250)
qaoa_mes = QAOA(sampler=Sampler(), optimizer=cobyla, reps=3)
qaoa = MinimumEigenOptimizer(qaoa_mes)
result = qaoa.solve(qp)
print_result(result)
Optimal: selection [1. 0. 0. 1.], value -0.0149
----------------- Full result ---------------------
selection value probability
---------------------------------------------------
[1 0 0 1] -0.0149 0.1797
[1 0 1 0] -0.0140 0.1729
[1 1 0 0] -0.0130 0.1641
[0 0 1 1] -0.0010 0.1592
[0 1 1 0] 0.0008 0.1553
[0 1 0 1] 0.0002 0.1445
[0 1 0 0] 0.0009 0.0049
[1 1 0 1] -0.0139 0.0039
[1 1 1 1] -0.0139 0.0039
[0 0 0 0] 0.0000 0.0029
[1 0 0 0] -0.0140 0.0029
[0 0 1 0] -0.0001 0.0020
[0 1 1 1] -0.0000 0.0010
[1 1 1 0] -0.0130 0.0010
[0 0 0 1] -0.0008 0.0010
[1 0 1 1] -0.0150 0.0010
[9]:
import qiskit.tools.jupyter
%qiskit_version_table
%qiskit_copyright
Version Information
Software | Version |
---|---|
qiskit | 0.45.0.dev0+ea871e0 |
qiskit_optimization | 0.6.0 |
qiskit_finance | 0.4.0 |
qiskit_aer | 0.12.2 |
qiskit_ibm_provider | 0.7.0 |
qiskit_algorithms | 0.3.0 |
System information | |
Python version | 3.9.7 |
Python compiler | GCC 7.5.0 |
Python build | default, Sep 16 2021 13:09:58 |
OS | Linux |
CPUs | 2 |
Memory (Gb) | 5.7784271240234375 |
Tue Sep 05 15:03:52 2023 EDT |
This code is a part of Qiskit
© Copyright IBM 2017, 2023.
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.
[ ]: