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)