Source code for quantum_launcher.base.base

  1from abc import ABC, abstractmethod
  2from dataclasses import dataclass
  3import pickle
  4from typing import Any, Literal, TypeVar
  5from collections.abc import Callable
  6import logging
  7
  8
  9AVAILABLE_FORMATS = Literal['hamiltonian', 'qubo', 'none', 'fn']
 10
 11
[docs] 12@dataclass 13class Result: 14 best_bitstring: str 15 best_energy: float 16 most_common_bitstring: str 17 most_common_bitstring_energy: float 18 distribution: dict 19 energies: dict 20 num_of_samples: int 21 average_energy: float 22 energy_std: float 23 result: Any 24 25 def __str__(self): 26 return f"Result(bitstring={self.best_bitstring}, energy={self.best_energy})" 27 28 def __repr__(self): 29 return str(self) 30
[docs] 31 def best(self): 32 return self.best_bitstring, self.best_energy
33
[docs] 34 def most_common(self): 35 return self.most_common_bitstring, self.most_common_bitstring_energy
36
[docs] 37 @staticmethod 38 def from_distributions(bitstring_distribution: dict[str, float], energy_distribution: dict[str, float], result: Any = None) -> "Result": 39 """ 40 Constructs the Result object from Dictionary with bitstring to num of occurrences, 41 dictionary mapping bitstring to energy and optional result (rest) 42 """ 43 best_bitstring = min(energy_distribution, key=energy_distribution.get) 44 best_energy = energy_distribution[best_bitstring] 45 most_common_bitstring = max( 46 bitstring_distribution, key=bitstring_distribution.get) 47 most_common_bitstring_energy = energy_distribution[most_common_bitstring] 48 num_of_samples = int(sum(bitstring_distribution.values())) 49 50 mean_value = sum(energy_distribution[bitstring] * occ for bitstring, 51 occ in bitstring_distribution.items()) / num_of_samples 52 std = 0 53 for bitstring, occ in bitstring_distribution.items(): 54 std += occ * ((energy_distribution[bitstring] - mean_value)**2) 55 std = (std/(num_of_samples-1))**0.5 56 return Result(best_bitstring, best_energy, most_common_bitstring, most_common_bitstring_energy, 57 bitstring_distribution, energy_distribution, num_of_samples, mean_value, std, result)
58 59
[docs] 60class Backend: 61 """ 62 Abstract class representing a backend for quantum computing. 63 64 Attributes: 65 name (str): The name of the backend. 66 path (str | None): The path to the backend (optional). 67 parameters (list): A list of parameters for the backend (optional). 68 69 """ 70 71 def __init__(self, name: str, parameters: list | None = None) -> None: 72 self.name: str = name 73 self.path: str | None = None 74 self.parameters = parameters if parameters is not None else [] 75 self.logger: logging.Logger | None = None 76
[docs] 77 def set_logger(self, logger: logging.Logger): 78 self.logger = logger
79 80 def _get_path(self): 81 return f'{self.name}'
82 83 84P = TypeVar('P', bound=type['Problem']) 85 86
[docs] 87class Problem(ABC): 88 """ 89 Abstract class for defining Problems. 90 91 Attributes: 92 variant (str): The variant of the problem. The default variant is "Optimization". 93 path (str | None): The path to the problem. 94 name (str): The name of the problem. 95 instance_name (str): The name of the instance. 96 instance (any): An instance of the problem. 97 98 """ 99 100 _problem_id = None 101 102 def __init__(self, instance: Any, instance_name: str = 'unnamed') -> None: 103 """ 104 Initializes a Problem instance. 105 106 Params: 107 instance (any): An instance of the problem. 108 instance_name (str | None): The name of the instance. 109 110 Returns: 111 None 112 """ 113 self.instance: Any = instance 114 self.instance_name = instance_name 115 self.variant: str = 'Optimization' 116 self.path: str | None = None 117 self.name = self.__class__.__name__.lower() 118
[docs] 119 @classmethod 120 def from_file(cls: P, path: str) -> P: 121 with open(path, 'rb') as f: 122 instance = pickle.load(f) 123 return cls(instance)
124
[docs] 125 @staticmethod 126 def from_preset(instance_name: str, **kwargs): 127 raise NotImplementedError()
128 129 def __init_subclass__(cls) -> None: 130 if Problem not in cls.__bases__: 131 return 132 cls._problem_id = cls 133
[docs] 134 def read_result(self, exp, log_path): 135 """ 136 Reads a result from a file. 137 138 Args: 139 exp: The experiment. 140 log_path: The path to the log file. 141 142 Returns: 143 The result. 144 """ 145 exp += exp 146 with open(log_path, 'rb') as file: 147 res = pickle.load(file) 148 return res
149
[docs] 150 def analyze_result(self, result): 151 """ 152 Analyzes the result. 153 154 Args: 155 result: The result. 156 157 """
158 159
[docs] 160class Algorithm(ABC): 161 """ 162 Abstract class for Algorithms. 163 164 Attributes: 165 name (str): The name of the algorithm, derived from the class name in lowercase. 166 path (str | None): The path to the algorithm, if applicable. 167 parameters (list): A list of parameters for the algorithm. 168 alg_kwargs (dict): Additional keyword arguments for the algorithm. 169 170 Abstract methods: 171 __init__(self, **alg_kwargs): Initializes the Algorithm object. 172 _get_path(self) -> str: Returns the common path for the algorithm. 173 run(self, problem: Problem, backend: Backend): Runs the algorithm on a specific problem using a backend. 174 """ 175 _algorithm_format: AVAILABLE_FORMATS = 'none' 176 177 @abstractmethod 178 def __init__(self, **alg_kwargs) -> None: 179 self.name: str = self.__class__.__name__.lower() 180 self.path: str | None = None 181 self.parameters: list = [] 182 self.alg_kwargs = alg_kwargs 183
[docs] 184 def parse_result_to_json(self, o: object) -> dict: 185 """Parses results so that they can be saved as a JSON file. 186 187 Args: 188 o (object): The result object to be parsed. 189 190 Returns: 191 dict: The parsed result as a dictionary. 192 """ 193 print('Algorithm does not have the parse_result_to_json method implemented') 194 return o.__dict__
195
[docs] 196 @abstractmethod 197 def run(self, problem: Problem, backend: Backend, formatter: Callable | None = None) -> Result: 198 """Runs the algorithm on a specific problem using a backend. 199 200 Args: 201 problem (Problem): The problem to be solved. 202 backend (Backend): The backend to be used for execution. 203 """