Skip to content

Commit

Permalink
Merge pull request #319 from entropy-lab/QuAM-v2
Browse files Browse the repository at this point in the history
QuAM v2
  • Loading branch information
SatyaBade12 authored Aug 23, 2022
2 parents c416152 + 1fff9fc commit 27e1cfa
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 51 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]

## Changed
QuAM: A new implementation of QuAM (breaking change!)

## [0.15.3] - 2022-07-20

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion entropylab/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from entropylab.pipeline.results_backend.sqlalchemy.db import SqlAlchemyDB
from entropylab.pipeline.script_experiment import Script, script_experiment
from entropylab.pipeline.api.in_process_param_store import InProcessParamStore
from entropylab.quam.core import QuAMManager, QuAM
from entropylab.quam.core import QuAMManager

__all__ = [
"ExperimentReader",
Expand Down
80 changes: 41 additions & 39 deletions entropylab/quam/core.py
Original file line number Diff line number Diff line change
@@ -1,40 +1,46 @@
from abc import abstractmethod
from abc import abstractmethod, ABC
from typing import Callable, Dict
from munch import Munch

from entropylab.pipeline.api.in_process_param_store import InProcessParamStore
from qualang_tools.config import ConfigBuilder
from qualang_tools.config.parameters import ConfigVars
from qm.QuantumMachinesManager import QuantumMachinesManager
from qualang_tools.config import ConfigurationError


class QuAMCore(object):
def __init__(self, path: str):
"""Core QUAM object
class QuAMManager(ABC):
def __init__(self, path: str, host=None, port=None, **kwargs):
"""
QuAMManager
:param host: Host where to find the QM orchestrator. If ``None``,
local settings are used.
:type host: str
:param port: Port where to find the QM orchestrator. If None, local settings are used):
:type port: int
:param path: Path of the entropy DB
:type path: str
"""
self.path = path
self.param_store = InProcessParamStore(path)


class QuAMManager(QuAMCore):
def __init__(self, path: str, **qmm_kwargs):
"""Admin
:param path: Path of the entropy DB
:type path: str
"""
super().__init__(path=path)
self._qmm_kwargs = qmm_kwargs
self._config_builder = ConfigBuilder()
self._config_vars = ConfigVars()
self.config = {}
self.host = host
self.port = port
self.qmm = QuantumMachinesManager(host=host, port=port, **kwargs)

def generate_config(self):
"""Returns the QUA configuration"""
self._config_builder = ConfigBuilder()
self.prepare_config(self._config_builder)
self._set_config_vars()
return self._config_builder.build()
self.config = self._config_builder.build()
return self.config

@property
def config_builder(self):
return self._config_builder

@abstractmethod
def prepare_config(self, cb: ConfigBuilder) -> None:
Expand All @@ -56,48 +62,44 @@ def _set_config_vars(self):
_dict = {}
for k in self.param_store.keys():
if not callable(self._config_vars.parameter(k)._value):
if self.param_store[k] is None:
raise ConfigurationError("Set parameter {}".format(k))
_dict[k] = self.param_store[k]
self._config_vars.set(**_dict)

def open_quam(self):
"""Returns an instance of QuAM
:return: a quam
:rtype: QuAM
"""
self._set_config_vars()
return QuAM(path=self.path, config=self.generate_config(), **self._qmm_kwargs)


class QuAM(QuAMCore):
def __init__(self, path: str, config: dict = None, **qmm_kwargs):
"""User class to facilitate writing and execution of QUA programs
:param path: path to the entropy DB
:type path: str
:param config: a QUA configuration, defaults to an empty dictionary
:type config: Dict, optional
"""
super().__init__(path=path)
self.config = config if config is not None else {}
self.qmm = QuantumMachinesManager(**qmm_kwargs)

@property
def elements(self):
"""Returns a Munch instance of element keys available in the QUA configuration"""
return dict_keys_to_munch(self.config["elements"])
return get_key("elements", self.config)

@property
def pulses(self):
"""Returns a Munch instance of pulses available in the QUA configuration"""
return dict_keys_to_munch(self.config["pulses"])
return get_key("pulses", self.config)

@property
def integration_weights(self):
"""Returns a Munch instance of integration weights available in the QUA configuration"""
return dict_keys_to_munch(self.config["integration_weights"])
return get_key("integration_weights", self.config)

def open_qm(self):
return self.qmm.open_qm(self.generate_config())


def dict_keys_to_munch(d: Dict):
elms = Munch()
for k in d.keys():
elms[k] = k
return elms


def get_key(k: str, d: dict):
if k in d:
return dict_keys_to_munch(d[k])
else:
raise KeyError(
"{} doesn't exist in the QUA configuration, probably the \
config wasn't generated".format(
k
)
)
25 changes: 14 additions & 11 deletions entropylab/quam/tests/test_quam.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from qualang_tools.config import ConfigBuilder

from qm.qua import *
import pytest


class MyManager(QuAMManager):
Expand Down Expand Up @@ -33,23 +34,25 @@ def prepare_config(self, cb: ConfigBuilder):
)


@pytest.mark.skip(reason="requires a gateway server")
def test_quam(db_file_path):
manager = MyManager(path=db_file_path)
manager.param_store["lo"] = 5e5
manager.param_store.save_temp()
quam = MyManager(path=db_file_path)
quam.param_store["lo"] = 5e5
quam.param_store.save_temp()

def voltage_setter(val: float):
print(val)

voltage = manager.parameter("voltage", setter=voltage_setter)
voltage = quam.parameter("voltage", setter=voltage_setter)
voltage(12)
# print(manager.generate_config())

# quam = manager.open_quam()
# print(quam.elements.qb)
print(quam.generate_config())

# with program() as prog:
# play(quam.pulses.cw, quam.elements.qb)
print(quam.elements.qb)

# from qm.simulate import SimulationConfig
# res = quam.qmm.open_qm(quam.config).simulate(prog, simulate=SimulationConfig(duration=1000))
with program() as prog:
play(quam.pulses.cw, quam.elements.qb)

from qm.simulate import SimulationConfig

res = quam.open_qm().simulate(prog, simulate=SimulationConfig(duration=1000))

0 comments on commit 27e1cfa

Please sign in to comment.