Skip to content

Commit

Permalink
new interim result syntax (Qiskit#39)
Browse files Browse the repository at this point in the history
  • Loading branch information
jyu00 authored and GitHub Enterprise committed Apr 22, 2021
1 parent 49041c9 commit 88be738
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 170 deletions.
143 changes: 8 additions & 135 deletions QKA_demo_outer.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -2,135 +2,19 @@
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"slideshow": {
"slide_type": "skip"
}
},
"outputs": [],
"source": [
"import os\n",
"os.environ[\"PYTHON_EXEC\"] = \"/Users/jessieyu/.pyenv/versions/qka-demo/bin/python3\"\n",
"os.environ[\"NTC_DOC_FILE\"] = \"runtime/program_doc.json\"\n",
"os.environ[\"NTC_PROGRAM_FILE\"] = \"runtime/qka_runtime_outer.py\""
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# List available quantum programs"
]
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": null,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"==================================================\n",
"Quantum-Kernel-Alignment:\n",
" Description: Quantum kernel alignment algorithm that learns, on a given dataset, a quantum kernel maximizing the SVM classification margin.\n",
" Parameters:\n",
" - feature_map:\n",
" Description: An instance of FeatureMapACME in dictionary format used to map classical data into a quantum state space.\n",
" Type: dict\n",
" Required: True\n",
" - data:\n",
" Description: NxD array of training data, where N is the number of samples and D is the feature dimension.\n",
" Type: numpy.ndarray\n",
" Required: True\n",
" - labels:\n",
" Description: Nx1 array of +/-1 labels of the N training samples.\n",
" Type: numpy.ndarray\n",
" Required: True\n",
" - initial_kernel_parameters:\n",
" Description: Initial parameters of the quantum kernel. If not specified, an array of randomly generated numbers is used.\n",
" Type: numpy.ndarray\n",
" Required: False\n",
" - maxiters:\n",
" Description: Number of SPSA optimization steps. Default is 10.\n",
" Type: int\n",
" Required: False\n",
" - C:\n",
" Description: Penalty parameter for the soft-margin support vector machine. Default is 1.\n",
" Type: float\n",
" Required: False\n",
" Returns:\n",
" - aligned_kernel_parameters:\n",
" Description: The optimized kernel parameters found from quantum kernel alignment.\n",
" Type: numpy.ndarray\n",
" - aligned_kernel_matrix:\n",
" Description: The aligned quantum kernel matrix evaluated with the optimized kernel parameters on the training data.\n",
" Type: numpy.ndarray\n",
"==================================================\n",
"Circuit-Runner:\n",
" Description: A runtime program that takes one or more circuits, compiles them, executes them on the selected backend, and returns the results.\n",
" Parameters:\n",
" - circuits:\n",
" Description: A circuit or a list of circuits to compile and execute.\n",
" Type: A QuantumCircuit or a list of QuantumCircuits.\n",
" Required: True\n",
" - initial_layout:\n",
" Description: Initial position of virtual qubits on physical qubits.\n",
" Type: dict or list\n",
" Required: False\n",
" - layout_method:\n",
" Description: Name of layout selection pass ('trivial', 'dense', 'noise_adaptive', 'sabre')\n",
" Type: string\n",
" Required: False\n",
" - routing_method:\n",
" Description: Name of routing pass ('basic', 'lookahead', 'stochastic', 'sabre').\n",
" Type: string\n",
" Required: False\n",
" - translation_method:\n",
" Description: Name of translation pass ('unroller', 'translator', 'synthesis').\n",
" Type: string\n",
" Required: False\n",
" - scheduling_method:\n",
" Description: Name of scheduling pass ('as_soon_as_possible', 'as_late_as_possible').\n",
" Type: string\n",
" Required: False\n",
" - instruction_durations:\n",
" Description: Durations of instructions.\n",
" Type: A list of tuples: [(instruction_name, qubits, duration, unit), ...].\n",
" Required: False\n",
" - dt:\n",
" Description: Backend sample time (resolution) in seconds.\n",
" Type: float\n",
" Required: False\n",
" - seed_transpiler:\n",
" Description: Sets random seed for the stochastic parts of the transpiler.\n",
" Type: int\n",
" Required: False\n",
" - optimization_level:\n",
" Description: How much optimization to perform on the circuits (0-3). Higher levels generate more optimized circuits. Default is 1.\n",
" Type: int\n",
" Required: False\n",
" Returns:\n",
" - results:\n",
" Description: Circuit execution results.\n",
" Type: qiskit.result.Result object\n"
]
}
],
"outputs": [],
"source": [
"from qiskit import IBMQ\n",
"\n",
"provider = IBMQ.load_account()\n",
"provider.runtime.programs()"
"IBMQ.load_account()\n",
"provider = IBMQ.get_provider(project='qiskit-runtime')\n",
"backend = provider.get_backend('ibmq_montreal')"
]
},
{
Expand Down Expand Up @@ -180,9 +64,7 @@
"\n",
"# Define the feature map and its initial parameters:\n",
"initial_kernel_parameters = [0.1] # np.pi/2 should yield 100% test accuracy\n",
"fm = FeatureMapACME(feature_dimension=num_features, entangler_map=entangler_map)\n",
"\n",
"backend = provider.backend.ibmq_qasm_simulator"
"fm = FeatureMapACME(feature_dimension=num_features, entangler_map=entangler_map)"
]
},
{
Expand All @@ -195,7 +77,7 @@
},
"outputs": [],
"source": [
"def interim_result_callback(interim_result):\n",
"def interim_result_callback(job_id, interim_result):\n",
" print(f\"interim result: {interim_result}\\n\")"
]
},
Expand Down Expand Up @@ -268,7 +150,7 @@
" 'C': C\n",
"}\n",
"options = {'backend_name': backend.name()}\n",
"result = provider.runtime.run(program_id=\"Quantum-Kernel-Alignment\",\n",
"result = provider.runtime.run(program_id=\"quantum-kernel-alignment\",\n",
" options=options,\n",
" inputs=runtime_inputs,\n",
" callback=interim_result_callback,\n",
Expand Down Expand Up @@ -386,15 +268,6 @@
"# Test the aligned kernel"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"os.environ[\"NTC_PROGRAM_FILE\"] = \"runtime/circuit_runner.py\""
]
},
{
"cell_type": "code",
"execution_count": 8,
Expand Down
11 changes: 5 additions & 6 deletions qka/kernel_matrix.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import numpy as np
import itertools

from qiskit.compiler import transpile, assemble
from qiskit.compiler import transpile


class KernelMatrix:
Expand Down Expand Up @@ -96,14 +96,13 @@ def _run_circuits(self, circuits):
"""Execute the input circuits."""
try:
provider = self._backend.provider()
runtime_params = {'circuits': circuits}
runtime_params = {'circuits': circuits, 'shots': 8192}
options = {'backend_name': self._backend.name()}
return provider.runtime.run(program_name="Circuit-Runner",
return provider.runtime.run(program_id="circuit-runner",
options=options,
params=runtime_params,
inputs=runtime_params,
).result()
except Exception:
# Fall back to run without runtime.
transpiled = transpile(circuits, backend=self._backend)
qobj = assemble(transpiled, backend=self._backend, shots=8192)
return self._backend.run(qobj).result()
return self._backend.run(transpiled, shots=8192).result()
39 changes: 10 additions & 29 deletions runtime/qka_runtime_outer.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@
from qiskit import QuantumCircuit, QuantumRegister
from qiskit.compiler import transpile, assemble
from cvxopt import matrix, solvers
from typing import Any

import sys
import json
from qiskit.providers.ibmq.runtime.utils import RuntimeEncoder, RuntimeDecoder
from qiskit.providers.ibmq.runtime.utils import RuntimeEncoder

from qiskit import Aer
import warnings
warnings.simplefilter("ignore")


class FeatureMapACME:
Expand All @@ -36,7 +35,6 @@ def __init__(self, feature_dimension, entangler_map=None):

self._num_parameters = self._num_qubits


def construct_circuit(self, x=None, parameters=None, q=None, inverse=False, name=None):
"""Construct the feature map circuit.
Expand Down Expand Up @@ -107,7 +105,6 @@ def __init__(self, feature_map, backend):
self._backend = backend
self.results = {} # store the results object (program_data)


def construct_kernel_matrix(self, x1_vec, x2_vec, parameters=None):
"""Create the kernel matrix for a given feature map and input data.
Expand Down Expand Up @@ -191,13 +188,14 @@ def construct_kernel_matrix(self, x1_vec, x2_vec, parameters=None):
class QKA:
"""The quantum kernel alignment algorithm."""

def __init__(self, feature_map, backend, verbose=True):
def __init__(self, feature_map, backend, verbose=True, user_messenger=None):
"""Constructor.
Args:
feature_map (partial obj): the quantum feature map object
backend (Backend): the backend instance
verbose (bool): print output during course of algorithm
user_messenger (UserMessenger): used to publish interim results.
"""

self.feature_map = feature_map
Expand All @@ -209,6 +207,7 @@ def __init__(self, feature_map, backend, verbose=True):
self.num_parameters = self.feature_map._num_parameters # number of parameters (lambdas) in the feature map

self.verbose = verbose
self._user_messenger = user_messenger
self.result = {}

self.kernel_matrix = KernelMatrix(feature_map=self.feature_map, backend=self.backend)
Expand Down Expand Up @@ -365,7 +364,6 @@ def align_kernel(self, data, labels, initial_kernel_parameters=None, maxiters=10
cost_minus_save = [] # (-) cost at each spsa step
program_data = []


# #####################
# Start the alignment:

Expand Down Expand Up @@ -411,7 +409,7 @@ def align_kernel(self, data, labels, initial_kernel_parameters=None, maxiters=10
# intrim_result = {'cost': cost_final,
# 'lambda': lambdas, 'cost_plus': cost_plus,
# 'cost_minus': cost_minus, 'cost_final': cost_final}
post_interim_result(intrim_result)
self._user_messenger.publish(intrim_result)

lambda_save.append(lambdas)
cost_plus_save.append(cost_plus)
Expand Down Expand Up @@ -444,30 +442,13 @@ def align_kernel(self, data, labels, initial_kernel_parameters=None, maxiters=10
return self.result


def post_interim_result(text):
print(json.dumps({'post': text}, cls=RuntimeEncoder))


def main(backend, *args, **kwargs):
def main(backend, user_messenger, **kwargs):
"""Entry function."""

# Reconstruct the feature map object.
feature_map = kwargs.pop('feature_map')
fm = FeatureMapACME.from_json(**feature_map)
qka = QKA(feature_map=fm, backend=backend)
qka = QKA(feature_map=fm, backend=backend, user_messenger=user_messenger)
qka_results = qka.align_kernel(**kwargs)

print(json.dumps({'results': qka_results}, cls=RuntimeEncoder))


if __name__ == '__main__':
# provider = QuantumProgramProvider()
# backend = provider.backends()[0]

# the code currently uses Aer instead of runtime provider
backend = Aer.get_backend('qasm_simulator')
user_params = {}
if len(sys.argv) > 1:
# If there are user parameters.
user_params = json.loads(sys.argv[1], cls=RuntimeDecoder)
main(backend, **user_params)
print(json.dumps(qka_results, cls=RuntimeEncoder))

0 comments on commit 88be738

Please sign in to comment.