Source code for quantum_launcher.launcher.qlauncher

  1""" File with templates """
  2import json
  3import pickle
  4from typing import List, Literal, Optional, Union, Callable
  5from quantum_launcher.base.adapter_structure import get_formatter, ProblemFormatter
  6from quantum_launcher.base import Problem, Algorithm, Backend, Result
  7from quantum_launcher.problems import Raw
  8import logging
  9
 10
[docs] 11class QuantumLauncher: 12 """ 13 Quantum Launcher class. 14 15 Quantum launcher is used to run quantum algorithms on specific problem instances and backends. 16 It provides methods for binding parameters, preparing the problem, running the algorithm, and processing the results. 17 18 Attributes: 19 problem (Problem): The problem instance to be solved. 20 algorithm (Algorithm): The quantum algorithm to be executed. 21 backend (Backend, optional): The backend to be used for execution. Defaults to None. 22 path (str): The path to save the results. Defaults to 'results/'. 23 binding_params (dict or None): The parameters to be bound to the problem and algorithm. Defaults to None. 24 encoding_type (type): The encoding type to be used changing the class of the problem. Defaults to None. 25 26 Example of usage:: 27 28 from templates import QuantumLauncher 29 from problems import MaxCut 30 from qiskit_routines import QAOA, QiskitBackend 31 32 problem = MaxCut(instance_name='default') 33 algorithm = QAOA() 34 backend = QiskitBackend('local_simulator') 35 36 launcher = QuantumLauncher(problem, algorithm, backend) 37 result = launcher.process(save_pickle=True) 38 print(result) 39 40 """ 41 42 def __init__(self, problem: Problem, algorithm: Algorithm, backend: Backend = None, 43 logger: Optional[logging.Logger] = None) -> None: 44 45 if not isinstance(problem, Problem): 46 problem = Raw(problem) 47 48 self.problem: Problem = problem 49 self.algorithm: Algorithm = algorithm 50 self.backend: Backend = backend 51 52 if logger is None: 53 logger: logging.Logger = logging.getLogger('QuantumLauncher') 54 self.logger = logger 55 56 # logging.info(f'Found proper formatter, with formatter structure: {self.formatter.get_pipeline()}') 57 58 self.res: dict = {} 59
[docs] 60 def run(self, **kwargs) -> Result: 61 """ 62 Finds proper formatter, and runs the algorithm on the problem with given backends. 63 64 Returns: 65 dict: The results of the algorithm execution. 66 """ 67 68 formatter: ProblemFormatter = get_formatter(self.problem._problem_id, self.algorithm._algorithm_format) 69 formatter.set_run_params(kwargs) 70 71 self.result = self.algorithm.run(self.problem, self.backend, formatter=formatter) 72 logging.info('Algorithm ended successfully!') 73 return self.result
74
[docs] 75 def save(self, path: str, format: Literal['pickle', 'txt', 'json'] = 'pickle'): 76 logging.info(f'Saving results to file: {path}') 77 if format == 'pickle': 78 with open(path, mode='wb') as f: 79 pickle.dump(self.result, f) 80 elif format == 'json': 81 with open(path, mode='w', encoding='utf-8') as f: 82 json.dump(self.result.__dict__, f, default=fix_json) 83 elif format == 'txt': 84 with open(path, mode='w', encoding='utf-8') as f: 85 f.write(self.result.__str__()) 86 else: 87 raise ValueError( 88 f'format: {format} in not supported try: pickle, txt, csv or json')
89
[docs] 90 def process(self, *, file_path: Optional[str] = None, format: Union[Literal['pickle', 'txt', 'json'], List[Literal['pickle', 'txt', 'json']]] = 'pickle', **kwargs) -> dict: 91 """ 92 Runs the algorithm, processes the data, and saves the results if specified. 93 94 Args: 95 file_path (Optional[str]): Flag indicating whether to save the results to a file. Defaults to None. 96 format (Union[Literal['pickle', 'txt', 'json'], List[Literal['pickle', 'txt', 'json']]]): Format in which file should be saved. Defaults to 'pickle' 97 98 Returns: 99 dict: The processed results. 100 """ 101 results = self.run(**kwargs) 102 energy = results.result['energy'] 103 res = {} 104 res['problem_setup'] = self.problem.setup 105 res['algorithm_setup'] = self.algorithm.setup 106 res['algorithm_setup']['variant'] = self.problem.variant 107 res['backend_setup'] = self.backend.setup 108 res['results'] = results 109 110 self._file_name = self.problem.path + '-' + \ 111 self.backend.path + '-' \ 112 + self.algorithm.path + '-' + str(energy) 113 114 if file_path is not None and isinstance(format, str): 115 self.save(file_path, format) 116 if file_path is not None and isinstance(format, list): 117 for form in format: 118 self.save(file_path, form) 119 return res
120 121
[docs] 122def fix_json(o: object): 123 # if o.__class__.__name__ == 'SamplingVQEResult': 124 # parsed = self.algorithm.parse_samplingVQEResult(o, self._full_path) 125 # return parsed 126 if o.__class__.__name__ == 'complex128': 127 return repr(o) 128 print( 129 f'Name of object {o.__class__} not known, returning None as a json encodable') 130 return None