Source code for qlauncher.routines.orca.algorithms

  1from typing import Literal
  2from collections.abc import Callable
  3import numpy as np
  4
  5from qlauncher.base import Problem, Algorithm, Backend, Result
  6from qlauncher.exceptions import DependencyError
  7from qlauncher.routines.orca.backends import OrcaBackend
  8
  9try:
 10    from ptseries.algorithms.binary_solvers import BinaryBosonicSolver
 11except ImportError as e:
 12    raise DependencyError(e, install_hint='orca', private=True) from e
 13
 14
[docs] 15class BBS(Algorithm): 16 """ 17 Binary Bosonic Solver algorithm class. 18 19 This class represents the Binary Bosonic Solver (BBS) algorithm. BBS is a quantum-inspired algorithm that 20 solves optimization problems by mapping them onto a binary bosonic system. It uses a training process 21 to find the optimal solution. 22 23 ### Attributes: 24 25 - algorithm_format ('qubo', 'fn'), optional): If the algorithm input is a function or a qubo matrix. Defaults to 'qubo'. 26 - 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. 27 - n_samples (int, optional): Number of samples. Defaults to 100. 28 - gradient_mode (str, optional): Gradient mode. Defaults to "parameter-shift". 29 - gradient_delta (float, optional): Gradient Delta. Defaults to np.pi/6. 30 - sampling_factor (int, optional): Number of times quantum samples are passed through the classical flipping layer. Defaults to 1. 31 - learning_rate (float, optional): Learning rate of the algorithm. Defaults to 5e-2. 32 - learning_rate_flip (float, optional): Bit flip learning rate. Defaults to 1e-1. 33 - updates (int, optional): Number of epochs. Defaults to 100. 34 35 """ 36 _algorithm_format = 'qubo' 37 38 def __init__(self, algorithm_format: Literal['qubo', 'fn'] = 'qubo', 39 input_state: list[int] | None = None, 40 n_samples: int = 100, 41 gradient_mode: str = "parameter-shift", 42 gradient_delta: float = np.pi / 6, 43 sampling_factor: int = 1, 44 learning_rate: float = 5e-2, 45 learning_rate_flip: float = 1e-1, 46 updates: int = 100): 47 super().__init__() 48 self._algorithm_format = algorithm_format 49 self.bbs_params = { 50 'n_samples': n_samples, 51 'gradient_mode': gradient_mode, 52 'gradient_delta': gradient_delta, 53 'sampling_factor': sampling_factor, 54 } 55 self.training_params = { 56 'learning_rate': learning_rate, 57 'learning_rate_flip': learning_rate_flip, 58 'updates': updates, 59 } 60 self.input_state = input_state 61
[docs] 62 def run(self, problem: Problem, backend: Backend, formatter: Callable[[Problem], np.ndarray]) -> Result: 63 64 if not isinstance(backend, OrcaBackend): 65 raise ValueError(f'{backend.__class__} is not supported by BBS algorithm, use OrcaBackend instead') 66 objective = formatter(problem) 67 68 # TODO: use offset somehow 69 if not callable(objective): 70 objective, offset = objective 71 72 if self.input_state is None: 73 if not callable(objective): 74 self.input_state = [(i + 1) % 2 for i in range(len(objective))] 75 else: 76 raise ValueError('input_state needs to be provided if objective is a function (callable)') 77 78 tbi = backend.get_tbi() 79 bbs = BinaryBosonicSolver(pb_dim=len(self.input_state), 80 objective=objective, 81 input_state=self.input_state, 82 tbi=tbi, 83 **self.bbs_params) 84 85 bbs.solve(**self.training_params) 86 87 return self.construct_results(bbs)
88
[docs] 89 def get_bitstring(self, result: list[float]) -> str: 90 return ''.join(map(str, map(int, result)))
91
[docs] 92 def construct_results(self, solver: BinaryBosonicSolver) -> Result: 93 # TODO: add support for distribution (probably with different logger) 94 best_bitstring = ''.join( 95 map(str, map(int, solver.config_min_encountered))) 96 best_energy = solver.E_min_encountered 97 most_common_bitstring = None 98 most_common_bitstring_energy = None 99 distribution = None 100 energy = None 101 num_of_samples = solver.n_samples 102 average_energy = None 103 energy_std = None 104 #! Todo: instead of None attach relevant info from 'results' 105 # results fail to pickle correctly btw 106 return Result(best_bitstring, best_energy, most_common_bitstring, 107 most_common_bitstring_energy, distribution, energy, 108 num_of_samples, average_energy, energy_std, None)