Skip to content

Commit

Permalink
updating README.md, refactoring, modifying request schemas
Browse files Browse the repository at this point in the history
  • Loading branch information
mbeisel committed Apr 1, 2022
1 parent 874059f commit 4878f61
Show file tree
Hide file tree
Showing 11 changed files with 52 additions and 105 deletions.
Binary file modified README.md
Binary file not shown.
8 changes: 4 additions & 4 deletions app/database/minio_db.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import io
import pickle
from minio import Minio
import sys
from app.model.matrix_types import MatrixType
from config import Config
import os
import numpy as np
from datetime import datetime


print(Config.MINIO_ENDPOINT)
client = Minio(
Config.MINIO_ENDPOINT,
access_key=Config.MINIO_USER,
Expand Down Expand Up @@ -70,7 +68,7 @@ def store_matrix_object_in_db(matrix, qpu: str, matrix_type: MatrixType, **kwarg
)
return filename
except:
raise
raise ConnectionError("File could not be stored in DB")


def load_matrix_object_from_db(qpu, matrix_type: MatrixType, **kwargs):
Expand Down Expand Up @@ -170,7 +168,7 @@ def get_time_diff(elem):
matrix_data.seek(0)
matrix = pickle.load(matrix_data)
except:
raise
raise ConnectionError("File could not be loaded")
finally:
response.close()
response.release_conn()
Expand All @@ -197,6 +195,8 @@ def load_mitigator_object_from_db_by_filename(
matrix_data = io.BytesIO(response.data)
matrix_data.seek(0)
matrix = pickle.load(matrix_data)
except:
raise ConnectionError("File could not be loaded")
finally:
response.close()
response.release_conn()
Expand Down
4 changes: 2 additions & 2 deletions app/model/cmgen_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ def _deserialize(self, value, attr, data, **kwargs):
return value
else:
raise ValidationError(
"Field should be list of integers or dict with bitstring as key and counts as measurement, e.g., [{'0': 980, '1': 20}] "
"Field should be list of dicts with bitstring as key and counts as measurement, e.g., [{'0': 980, '1': 20}] "
)
else:
raise ValidationError(
"Field should be list of integers or dict with bitstring as key and counts as measurement, e.g., [{'0': 980, '1': 20}] "
"Field should be list of dicts with bitstring as key and counts as measurement, e.g., [{'0': 980, '1': 20}] "
)


Expand Down
30 changes: 25 additions & 5 deletions app/model/rem_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,23 @@ def __init__(
self.credentials = credentials


class CountsField(fields.Field):
def _deserialize(self, value, attr, data, **kwargs):
if isinstance(value, list):
if all(isinstance(x, dict) for x in value):
return value
else:
raise ValidationError(
"Field should be list of dicts with bitstring as key and counts as measurement, e.g., [{'0': 980, '1': 20}] "
)
elif isinstance(value, dict):
return value
else:
raise ValidationError(
"Field should be list of dicts with bitstring as key and counts as measurement, e.g., [{'0': 980, '1': 20}] "
)


class QubitsArrayField(fields.Field):
def _deserialize(self, value, attr, data, **kwargs):
if isinstance(value, list):
Expand All @@ -48,14 +65,17 @@ def _deserialize(self, value, attr, data, **kwargs):


class REMRequestSchema(ma.Schema):

counts = ma.fields.Raw(required=True)
counts = CountsField(required=True)
cm_gen_method = ma.fields.String(required=False)
mitigation_method = ma.fields.String(required=False)
qpu = ma.fields.String(required=True)
qubits = QubitsArrayField()
qubits = QubitsArrayField(required=True)
max_age = ma.fields.Integer(required=False)
time_of_execution = ma.fields.DateTime("%Y-%m-%d_%H-%M-%S", required=False)
time_of_execution = ma.fields.DateTime(
"%Y-%m-%d_%H-%M-%S", required=False, description="format:Y-m-d_H-M-S"
)
provider = ma.fields.String(required=False)
shots = ma.fields.Integer(required=False)
credentials = ma.fields.Raw(required=False)
credentials = ma.fields.Raw(
required=False, description="Dictionary containing all required credentials"
)
26 changes: 15 additions & 11 deletions app/services/cmgen_services/circuit_executor.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
from abc import ABC, abstractmethod

from qiskit import IBMQ, execute, transpile
from qiskit.providers.ibmq import IBMQBackend, IBMQJobManager
from qiskit import IBMQ, execute
from qiskit_ionq import IonQProvider
from pyquil import get_qc
from qiskit.test.mock import FakeMontreal


class CircuitExecutor(ABC):
Expand All @@ -19,6 +15,7 @@ def execute_circuits(self, circuits, qpu, credentials, shots):
provider = IBMQ.enable_account(**credentials)
backend = provider.get_backend(qpu)
# TODO split when too many circuits
# from qiskit.providers.ibmq import IBMQBackend, IBMQJobManager
# if type(backend) == IBMQBackend:
# jobmanager = IBMQJobManager() # works only with IBMQBackend typed backend, splits experiments into jobs
# bulk_circuits = transpile(circuits, backend=backend)
Expand Down Expand Up @@ -49,9 +46,16 @@ def execute_circuits(self, circuits, qpu, credentials, shots):

class RigettiCircuitExecutor(CircuitExecutor):
def execute_circuits(self, circuits, qpu, credentials, shots):
qc = get_qc(qpu)
# TODO how to handle multiple programs/circuits
executable = qc.compile(circuits)
result = qc.run(executable)
bitstrings = result.readout_data.get("ro")
return bitstrings
#################################################################
# #
# Rigetti does not support API circuit execution yet #
# Generate & Execute circuits via Rigetti Jupyter Lab and #
# import counts into REM Service via the /cm/fromCounts API #
# #
#################################################################
# qc = get_qc(qpu)
# executable = qc.compile(circuits)
# result = qc.run(executable)
# bitstrings = result.readout_data.get("ro")
# return bitstrings
raise NotImplementedError("Rigetti circuits can not be executed via API yet")
4 changes: 1 addition & 3 deletions app/services/cmgen_services/circuit_generator.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
from abc import ABC, abstractmethod

import numpy as np
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
from qiskit.ignis.mitigation import CompleteMeasFitter, tensored_meas_cal
from qiskit.ignis.mitigation import tensored_meas_cal
import qiskit.ignis.mitigation as mit
from sympy.physics.units import bits

from app.services.cmgen_services.sparse_fitter import SparseExpvalMeasMitigatorFitter
from app.utils.helper_functions import ResultsMock
Expand Down
5 changes: 0 additions & 5 deletions app/services/cmgen_services/cmgen_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
CTMPCMGenerator,
TPNMCMGenerator,
)
from app.utils.helper_functions import ResultsMock


def retrieve_executor(provider: str):
Expand Down Expand Up @@ -77,9 +76,6 @@ def generate_cm_from_counts(request: CMGenFromCountsRequest):
if __name__ == "__main__":
from credentials import Credentials as credentials

# Standard
# json = {'cm_gen_method': 'standard', 'qpu': 'ibmq_lima', 'provider': 'IBM', 'shots': 10, 'credentials': credentials.CREDENTIALS_US, 'qubits': [1, 2, 3, 7]}
# TPNM
json = {
"cm_gen_method": "tpnm",
"qpu": "ibmq_lima",
Expand All @@ -90,4 +86,3 @@ def generate_cm_from_counts(request: CMGenFromCountsRequest):
}
req = CMGenRequest(**json)
res = generate_cm(req)
print("test")
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,4 @@ def generate_mitigator(self, cm, *kwargs):

class MatrixInversion(MitigationGenerator):
def generate_mitigator(self, cm, **kwargs):

return np.linalg.inv(cm)
7 changes: 3 additions & 4 deletions app/services/mitigator_gen_services/mmgen_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
from app.model.mmgen_request import MMGenRequest
from app.model.cmgen_request import CMGenRequest
from datetime import datetime
from qiskit.test.mock import FakeMontreal


def mitigation_generator(method):
Expand All @@ -37,6 +36,8 @@ def generate_mthree_mitigator(request: MMGenRequest):
if request.provider == "ibm":
provider = IBMQ.enable_account(**credentials)
backend = provider.get_backend(request.qpu)
# For testing on a fake backend uncomment below
# from qiskit.test.mock import FakeMontreal
# backend = FakeMontreal()
elif request.provider == "ionq":
backend = IonQProvider(request.credentials).get_backend(request.qpu)
Expand Down Expand Up @@ -89,7 +90,7 @@ def generate_mm_from_cm(request: MMGenRequest):
max_age=request.max_age,
)
except:
raise
raise ConnectionError("Could not access DB")

if cm is None:
cmgenrequest = CMGenRequest(
Expand Down Expand Up @@ -146,7 +147,5 @@ def retrieve_mm(req: MMGetRequest):
"shots": 10,
"credentials": credentials.CREDENTIALS_US,
}
# json = {'cm_gen_method': 'tpnm', 'mitigation_method':'tpnm', 'qpu': 'ibmq_lima', 'qubits':[1,2,3,4], 'provider': 'ibm', 'shots': 10, 'credentials': credentials.CREDENTIALS_US}
# json = {'cm_gen_method': 'mthree', 'mitigation_method':'mthree', 'qpu': 'ibmq_lima', 'qubits':[1,2,3,4], 'provider': 'ibm', 'shots': 10, 'credentials': credentials.CREDENTIALS_US}
req = MMGenRequest(**json)
print(generate_mm(req))
37 changes: 0 additions & 37 deletions app/services/rem_services/rem_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ def mitigate_results(request: REMRequest):
if mitigator is not None:
if len(request.counts) != len(request.qubits):
for c in request.counts:
c = c[2]
solution_counts.append(
perform_mitigation(
c, qubits, metadata, application_method, mitigator
Expand Down Expand Up @@ -169,42 +168,6 @@ def mitigate_results(request: REMRequest):
if __name__ == "__main__":
from credentials import Credentials as credentials

json = {
"counts": {
"111": 129,
"000": 131,
"101": 134,
"100": 142,
"011": 97,
"110": 117,
"001": 125,
"010": 125,
},
"mitigation_method": "inversion",
"cm_gen_method": "standard",
"qpu": "ibmq_lima",
"qubits": [3, 1, 2],
"max_age": 1,
}
json = {
"counts": {
"111": 129,
"000": 131,
"101": 134,
"100": 142,
"011": 97,
"110": 117,
"001": 125,
"010": 125,
},
"mitigation_method": "inversion",
"cm_gen_method": "standard",
"qpu": "ibmq_lima",
"qubits": [3, 1, 2],
"max_age": 3,
"credentials": credentials.CREDENTIALS_US,
"provider": "IBM",
}
json = {
"counts": {
"111": 129,
Expand Down
35 changes: 2 additions & 33 deletions app/utils/helper_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def sort_dict_by_qubitorder(
:param counts_dict: dictionary containing measurement counts
:param counts_qubits: list containing qubit order of measurement qubits
:param mitigator_qubits: list containing qubit order when creating mitigator
:return:
:return: counts in qubit order
"""
mapping = []
for i in mitigator_qubits:
Expand All @@ -46,7 +46,7 @@ def restore_dict_by_qubitorder(
):
"""
:param adjusted_counts_dict: dictionary containing measurement counts
:return:
:return: counts in restored qubit order
"""
mapping = []
for i in counts_qubits:
Expand All @@ -60,33 +60,6 @@ def restore_dict_by_qubitorder(
return sorted_dict


# qubits [2,4,1]
# qubits_mm[0,1,2,4,5]
# mapping_to_array_position [2,3,1]
# key = '101'
# position = 011000
# TODO not properly working
def countsdict_to_array(dict, qubits, qubits_mm):
vector = np.zeros(2 ** len(qubits_mm))
indices_mapping = []
for qubit in qubits:
indices_mapping.append(qubits_mm.index(qubit))
for key, val in dict.items():
binary = ""
for i in range(len(qubits_mm)):

if i in indices_mapping:
index_in_qubits = indices_mapping.index(i)
# index = qubits[index_in_qubits]
binary += key[index_in_qubits]
else:
binary += "0"
print(binary)
array_index = int(binary, 2)
vector[array_index] = val
print(vector)


import functools
import inspect
import warnings
Expand Down Expand Up @@ -187,10 +160,6 @@ def get_counts(self, i: int):
"001": 125,
"010": 125,
}
# qubits =[2,4,1]
# qubits_mm = [0,1,2,4,5]
#
# countsdict_to_array(dict,qubits,qubits_mm)

counts_qubits = [4, 2, 7]
mitiagor_qubits = [7, 4, 2]
Expand Down

0 comments on commit 4878f61

Please sign in to comment.