Skip to content

Commit

Permalink
Use code from README.md in test_readme_sample (#144) (#145)
Browse files Browse the repository at this point in the history
(cherry picked from commit 8d80b2e)

Co-authored-by: Manoel Marques <Manoel.Marques@ibm.com>
  • Loading branch information
mergify[bot] and manoelmarques authored Feb 10, 2022
1 parent 705ba47 commit 57fa857
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 71 deletions.
36 changes: 18 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,39 +34,39 @@ evaluate a fixed income asset with uncertain interest rates.
```python
import numpy as np
from qiskit import BasicAer
from qiskit.algorithms import AmplitudeEstimation, EstimationProblem
from qiskit.algorithms import AmplitudeEstimation
from qiskit_finance.circuit.library import NormalDistribution
from qiskit_finance.applications import FixedIncomeExpectedValue
from qiskit_finance.applications import FixedIncomePricing

# Create a suitable multivariate distribution
num_qubits = [2, 2]
bounds = [(0, 0.12), (0, 0.24)]
mvnd = NormalDistribution(num_qubits,
mu=[0.12, 0.24], sigma=0.01 * np.eye(2),
bounds=bounds)
mvnd = NormalDistribution(
num_qubits, mu=[0.12, 0.24], sigma=0.01 * np.eye(2), bounds=bounds
)

# Create fixed income component
fixed_income = FixedIncomeExpectedValue(num_qubits, np.eye(2), np.zeros(2),
cash_flow=[1.0, 2.0], rescaling_factor=0.125,
bounds=bounds)
fixed_income = FixedIncomePricing(
num_qubits,
np.eye(2),
np.zeros(2),
cash_flow=[1.0, 2.0],
rescaling_factor=0.125,
bounds=bounds,
uncertainty_model=mvnd,
)

# the FixedIncomeExpectedValue provides us with the necessary rescalings

# create the A operator for amplitude estimation by prepending the
# normal distribution to the function mapping
state_preparation = fixed_income.compose(mvnd, front=True)

problem = EstimationProblem(state_preparation=state_preparation,
objective_qubits=[4],
post_processing=fixed_income.post_processing)
# create the A operator for amplitude estimation
problem = fixed_income.to_estimation_problem()

# Set number of evaluation qubits (samples)
num_eval_qubits = 5

# Construct and run amplitude estimation
q_i = BasicAer.get_backend('statevector_simulator')
algo = AmplitudeEstimation(num_eval_qubits=num_eval_qubits,
quantum_instance=q_i)
q_i = BasicAer.get_backend("statevector_simulator")
algo = AmplitudeEstimation(num_eval_qubits=num_eval_qubits, quantum_instance=q_i)
result = algo.estimate(problem)

print(f"Estimated value:\t{fixed_income.interpret(result):.4f}")
Expand Down
114 changes: 61 additions & 53 deletions test/test_readme_sample.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This code is part of Qiskit.
#
# (C) Copyright IBM 2020, 2021.
# (C) Copyright IBM 2020, 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
Expand All @@ -18,6 +18,10 @@

import unittest

import contextlib
import io
from pathlib import Path
import re
from test import QiskitFinanceTestCase


Expand All @@ -26,61 +30,65 @@ class TestReadmeSample(QiskitFinanceTestCase):

def test_readme_sample(self):
"""readme sample test"""
# pylint: disable=import-outside-toplevel,redefined-builtin

def print(*args):
"""overloads print to log values"""
if args:
self.log.debug(args[0], *args[1:])

# --- Exact copy of sample code ----------------------------------------

import numpy as np
from qiskit import BasicAer
from qiskit.algorithms import AmplitudeEstimation
from qiskit_finance.circuit.library import NormalDistribution
from qiskit_finance.applications import FixedIncomePricing

# Create a suitable multivariate distribution
num_qubits = [2, 2]
bounds = [(0, 0.12), (0, 0.24)]
mvnd = NormalDistribution(
num_qubits, mu=[0.12, 0.24], sigma=0.01 * np.eye(2), bounds=bounds
)

# Create fixed income component
fixed_income = FixedIncomePricing(
num_qubits,
np.eye(2),
np.zeros(2),
cash_flow=[1.0, 2.0],
rescaling_factor=0.125,
bounds=bounds,
uncertainty_model=mvnd,
)

# the FixedIncomeExpectedValue provides us with the necessary rescalings

# create the A operator for amplitude estimation
problem = fixed_income.to_estimation_problem()

# Set number of evaluation qubits (samples)
num_eval_qubits = 5

# Construct and run amplitude estimation
q_i = BasicAer.get_backend("statevector_simulator")
algo = AmplitudeEstimation(num_eval_qubits=num_eval_qubits, quantum_instance=q_i)
result = algo.estimate(problem)

print(f"Estimated value:\t{fixed_income.interpret(result):.4f}")
print(f"Probability: \t{result.max_probability:.4f}")

# ----------------------------------------------------------------------
# pylint: disable=exec-used

readme_name = "README.md"
readme_path = Path(__file__).parent.parent.joinpath(readme_name)
if not readme_path.exists() or not readme_path.is_file():
self.fail(msg=f"{readme_name} not found at {readme_path}")
return

# gets the first matched code sample
# assumes one code sample to test per readme
readme_sample = None
with open(readme_path, encoding="UTF-8") as readme_file:
match_sample = re.search(
"```python.*```",
readme_file.read(),
flags=re.S,
)
if match_sample:
# gets the matched string stripping the markdown code block
readme_sample = match_sample.group(0)[9:-3]

if readme_sample is None:
self.skipTest(f"No sample found inside {readme_name}.")
return

with contextlib.redirect_stdout(io.StringIO()) as out:
try:
exec(readme_sample)
except Exception as ex: # pylint: disable=broad-except
self.fail(str(ex))
return

estimation = None
probability = None
str_ref1 = "Estimated value:"
str_ref2 = "Probability:"
texts = out.getvalue().split("\n")
for text in texts:
idx = text.find(str_ref1)
if idx >= 0:
estimation = float(text[idx + len(str_ref1) :])
continue
idx = text.find(str_ref2)
if idx >= 0:
probability = float(text[idx + len(str_ref2) :])
if estimation is not None and probability is not None:
break

if estimation is None:
self.fail(f"Failed to find estimation inside {readme_name}.")
return
if probability is None:
self.fail(f"Failed to find max.probability inside {readme_name}.")
return

with self.subTest("test estimation"):
self.assertAlmostEqual(result.estimation_processed, 2.46, places=4)
self.assertAlmostEqual(estimation, 2.46, places=4)
with self.subTest("test max.probability"):
self.assertAlmostEqual(result.max_probability, 0.8487, places=4)
self.assertAlmostEqual(probability, 0.8487, places=4)


if __name__ == "__main__":
Expand Down

0 comments on commit 57fa857

Please sign in to comment.