Source code for qlauncher.routines.orca.algorithms

 1from typing import Literal
 2
 3import numpy as np
 4
 5from qlauncher.base import Algorithm, Result
 6from qlauncher.base.models import QUBO
 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[QUBO, OrcaBackend]): 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 26 - algorithm_format ('qubo', 'fn'), optional): If the algorithm input is a function or a qubo matrix. Defaults to 'qubo'. 27 - input_state (list[int] | None, optional): Photonic circuit input state provided to the ORCA computer. If None defaults to [1,0,1,0,1...]. Defaults to None. 28 - n_samples (int, optional): Number of samples. Defaults to 100. 29 - gradient_mode (str, optional): Gradient mode. Defaults to "parameter-shift". 30 - gradient_delta (float, optional): Gradient Delta. Defaults to np.pi/6. 31 - sampling_factor (int, optional): Number of times quantum samples are passed through the classical flipping layer. Defaults to 1. 32 - learning_rate (float, optional): Learning rate of the algorithm. Defaults to 5e-2. 33 - learning_rate_flip (float, optional): Bit flip learning rate. Defaults to 1e-1. 34 - updates (int, optional): Number of epochs. Defaults to 100. 35 36 """ 37 38 def __init__( 39 self, 40 algorithm_format: Literal['qubo', 'fn'] = 'qubo', 41 input_state: list[int] | None = None, 42 n_samples: int = 100, 43 gradient_mode: str = 'parameter-shift', 44 gradient_delta: float = np.pi / 6, 45 sampling_factor: int = 1, 46 learning_rate: float = 5e-2, 47 learning_rate_flip: float = 1e-1, 48 updates: int = 100, 49 ): 50 super().__init__() 51 self._algorithm_format = algorithm_format 52 self.bbs_params = { 53 'n_samples': n_samples, 54 'gradient_mode': gradient_mode, 55 'gradient_delta': gradient_delta, 56 'sampling_factor': sampling_factor, 57 } 58 self.training_params = { 59 'learning_rate': learning_rate, 60 'learning_rate_flip': learning_rate_flip, 61 'updates': updates, 62 } 63 self.input_state = input_state 64
[docs] 65 def run(self, problem: QUBO, backend: OrcaBackend) -> Result: 66 if self.input_state is None: 67 self.input_state = [(i + 1) % 2 for i in range(len(problem.matrix))] 68 69 bbs = BinaryBosonicSolver( 70 pb_dim=len(self.input_state), 71 objective=problem.matrix, 72 input_state=self.input_state, 73 tbi=backend.get_tbi(), 74 **self.bbs_params, 75 ) 76 77 bbs.solve(**self.training_params) 78 79 return self.construct_results(bbs, problem.offset)
80
[docs] 81 def get_bitstring(self, result: list[float]) -> str: 82 return ''.join(map(str, map(int, result)))
83
[docs] 84 def construct_results(self, solver: BinaryBosonicSolver, offset: float) -> Result: 85 # TODO: add support for distribution (probably with different logger) 86 best_bitstring = ''.join(map(str, map(int, solver.config_min_encountered))) 87 best_energy = solver.E_min_encountered + offset 88 num_of_samples = solver.n_samples 89 #! Todo: instead of None attach relevant info from 'results' 90 # results fail to pickle correctly btw 91 return Result(best_bitstring, best_energy, None, None, None, None, num_of_samples, None, None, None) # type: ignore