Source code for simulaqron.settings.simulaqron_config

#
# Copyright (c) 2017, Stephanie Wehner and Axel Dahlberg
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
#    must display the following acknowledgement:
#    This product includes software developed by Stephanie Wehner, QuTech.
# 4. Neither the name of the QuTech organization nor the
#    names of its contributors may be used to endorse or promote products
#    derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ''AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES
# LOSS OF USE, DATA, OR PROFITS OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#########################
# SETTINGS FOR SIMULAQRON
#########################
import json
import logging
from dataclasses import dataclass, fields
from enum import Enum
from os import PathLike
from pathlib import Path
from typing_extensions import Self

from dataclasses_serialization.json import JSONSerializer
from dataclasses_serialization.json import JSONSerializerMixin

# Some helpers paths that point to the usual locations where the
# configurations can reside:
DEFAULT_SIMULAQRON_SETTINGS_FILENAME = "simulaqron_settings.json"
LOCAL_SIMULAQRON_SETTINGS = (Path.cwd() / DEFAULT_SIMULAQRON_SETTINGS_FILENAME).resolve()
HOME_SIMULAQRON_SETTINGS = (Path.home() / ".simulaqron" / DEFAULT_SIMULAQRON_SETTINGS_FILENAME).resolve()


[docs]class SimBackend(JSONSerializerMixin, Enum): """ Enum used to list the supported SimulaQron backends. """ STABILIZER = "stabilizer" PROJECTQ = "projectq" QUTIP = "qutip" def __str__(self): return self.value def __repr__(self): return str(self)
[docs]@dataclass class SimulaqronConfig(JSONSerializerMixin): """ Holds the general SimulaQron config. """ # Default config max_qubits: int = 20 max_registers: int = 1000 conn_retry_time: float = 0.5 conn_max_retries: int = 10 recv_timeout: int = 100 recv_retry_time: float = 0.1 recv_max_retries: int = 10 log_level: int = logging.WARNING sim_backend: SimBackend = SimBackend.QUTIP noisy_qubits: bool = False max_app_waiting_time: float = -1.0 # In seconds, negative means unlimited waiting t1: float = 1.0 @classmethod def _create_home_settings_folder(cls): home_setting_folder = (Path.home() / ".simulaqron").resolve() home_setting_folder.mkdir(parents=True, exist_ok=True)
[docs] def read_from_file(self, file_path: Path | str): """ Reads the SimulaQron configuration from the given file path. :param file_path: A `pathlib.Path` or `str` representing the file path to read the configurations from. :type file_path: Path | str """ if isinstance(file_path, str): file_path = Path(file_path).resolve() new_config = self._deserialize_from_file(file_path) cls_fields = fields(self.__class__) for field in cls_fields: new_val = getattr(new_config, field.name) setattr(self, field.name, new_val)
@classmethod def _deserialize_from_file(cls, file_path: Path) -> Self: with file_path.resolve().open("rt") as file: config_content = json.load(file) return JSONSerializer.deserialize(cls, config_content)
[docs] @classmethod def read_from_known_sources(cls) -> Self: """ Reads the SimulaQron configuration from usual locations. This method will try to load the configuration files *in the following order* from (1) the current folder (`./simulaqron_settings.json`) and, (2) simulaqron settings in the user's home folder (`~/.simulaqron/simulaqron_settings.json`). If none of these files exists, this method will create a SimulaQron configuration in user's home folder (`~/.simulaqron/simulaqron_settings.json`) containing the default SimulaQron configuration. To check the default configuration, check the documentation of `default_settings`. See Also: :py:meth:`default_settings` """ cwd_settings_file = LOCAL_SIMULAQRON_SETTINGS.resolve() home_settings_file = HOME_SIMULAQRON_SETTINGS.resolve() files_to_load = [cwd_settings_file, home_settings_file] for file in files_to_load: try: if file.exists() and file.is_file(): return cls._deserialize_from_file(file) except json.JSONDecodeError: # Nothing to do; try next one pass # Ultimate case; we create a new config file in the ohme and load it new_default_config = cls() new_default_config.write_to_file(home_settings_file) return new_default_config
[docs] def default_settings(self): """ Resets the current SimulaQron configuration object to its default configuration set. The default configuration is: * max_qubits = 20 * max_registers = 1000 * conn_retry_time = 0.5 * conn_max_retries = 10 * recv_timeout = 100 * recv_retry_time = 0.1 * recv_max_retries = 10 * log_level = logging.WARNING * sim_backend = SimBackend.QUTIP * noisy_qubits = False * max_app_waiting_time = -1.0 # In seconds, negative means unlimited waiting * t1: float = 1.0 """ default_config = SimulaqronConfig() cls_fields = fields(self.__class__) for field in cls_fields: new_val = getattr(default_config, field.name) setattr(self, field.name, new_val)
[docs] def write_to_file(self, path: PathLike): """ Writes the current in-memory configuration (`simulaqron_config`) to the given file path. :param path:A `PathLike` object (even a string) representing the path to write the configuration to. :type path: PathLike """ file_path = Path(str(path)).resolve() # Create all the parent folder if they not exists if not file_path.parent.exists(): file_path.parent.mkdir(parents=True) # Poke the file, so it exists before opening file_path.touch(exist_ok=True) with file_path.open("wt") as file: serialized = JSONSerializer.serialize(self) json.dump(serialized, file, indent=4)
[docs]def get_default_simulaqron_config_file(): """ Get the simulaqron config file path to use. :return: Path to the simulaqron config file. :rtype: Path """ # Implements using the local directory setting as a priority if LOCAL_SIMULAQRON_SETTINGS.exists(): return LOCAL_SIMULAQRON_SETTINGS if HOME_SIMULAQRON_SETTINGS.exists(): return HOME_SIMULAQRON_SETTINGS from . import simulaqron_settings # Create default in HOME (matches load_from_known_sources behavior) # XXX I have mixed feelings we should do this, but I leave it for now simulaqron_settings.default_settings() HOME_SIMULAQRON_SETTINGS.parent.mkdir(parents=True, exist_ok=True) simulaqron_settings.write_to_file(HOME_SIMULAQRON_SETTINGS) return HOME_SIMULAQRON_SETTINGS