Source code for qlauncher.routines.orca.algorithms

 1from typing import List, Literal
 2from inspect import getfullargspec
 3from collections.abc import Callable
 4import numpy as np
 5
 6from qlauncher.base import Problem, Algorithm, Result
 7from qlauncher.exceptions import DependencyError
 8from qlauncher.routines.orca.backends import OrcaBackend
 9
10try:
11    from ptseries.algorithms.binary_solvers import BinaryBosonicSolver
12except ImportError as e:
13    raise DependencyError(e, install_hint='orca', private=True) from e
14
15
[docs] 16class BBS(Algorithm): 17 """ 18 Binary Bosonic Solver algorithm class. 19 20 This class represents the Binary Bosonic Solver (BBS) algorithm. BBS is a quantum-inspired algorithm that 21 solves optimization problems by mapping them onto a binary bosonic system. It uses a training process 22 to find the optimal solution. 23 24 Attributes: 25 - learning_rate (float): The learning rate for the algorithm. 26 - updates (int): The number of updates to perform during training. 27 - tbi_loops (str): The type of TBI loops to use. 28 - print_frequency (int): The frequency at which to print updates. 29 - logger (Logger): The logger object for logging algorithm information. 30 31 """ 32 _algorithm_format = 'qubo' 33 34 def __init__(self, algorithm_format: Literal['qubo', 'qubo_fn'] = 'qubo', **kwargs) -> None: 35 super().__init__() 36 self._algorithm_format = algorithm_format 37 self.kwargs = kwargs 38 self.input_state = self.kwargs.pop('input_state', None) 39
[docs] 40 def run(self, problem: Problem, backend: OrcaBackend, formatter: Callable[[Problem], np.ndarray]) -> Result: 41 42 objective = formatter(problem) 43 44 # TODO: use offset somehow 45 if not callable(objective): 46 objective, offset = objective 47 if self.input_state is None: 48 self.input_state = [not i % 2 for i in range(len(objective))] 49 50 bbs = backend.get_bbs( 51 len(self.input_state), 52 objective, 53 self.input_state, 54 **{k: v for k, v in self.kwargs.items() if k in getfullargspec(BinaryBosonicSolver.__init__)[0]} 55 56 ) 57 bbs.train(**{k: v for k, v in self.kwargs.items() if k in getfullargspec(BinaryBosonicSolver.train)[0]}) 58 59 return self.construct_results(bbs)
60
[docs] 61 def get_bitstring(self, result: List[float]) -> str: 62 return ''.join(map(str, map(int, result)))
63
[docs] 64 def construct_results(self, solver: BinaryBosonicSolver) -> Result: 65 # TODO: add support for distribution (probably with different logger) 66 best_bitstring = ''.join( 67 map(str, map(int, solver.config_min_encountered))) 68 best_energy = solver.E_min_encountered 69 most_common_bitstring = None 70 most_common_bitstring_energy = None 71 distribution = None 72 energy = None 73 num_of_samples = solver.n_samples 74 average_energy = None 75 energy_std = None 76 #! Todo: instead of None attach relevant info from 'results' 77 # results fail to pickle correctly btw 78 return Result(best_bitstring, best_energy, most_common_bitstring, 79 most_common_bitstring_energy, distribution, energy, 80 num_of_samples, average_energy, energy_std, None)