def set_backend(self, backend: Union[Backend, BaseBackend], **kwargs) -> None: """ Sets backend with configuration. Raises: ValueError: statevector or param_qobj are True when not supported by backend. """ self.quantum_instance = QuantumInstance(backend) self.quantum_instance.set_config(**kwargs)
def __init__(self, **kwargs): self.qubo = kwargs.get("qubo", None) if self.qubo is not None: self.operator, self.offset = self.qubo.to_ising() self.no_cars = kwargs.get("no_cars", 0) self.no_routes = kwargs.get("no_routes", 0) self.symmetrise = kwargs.get("symmetrise", False) self.customise = kwargs.get("customise", False) opt_str = kwargs.get('opt_str', "LN_BOBYQA") print("Optimizer: {}".format(opt_str)) self.optimizer = NLOPT_Optimizer(opt_str) self.optimizer.set_options(maxeval=200) self.original_qubo = deepcopy(self.qubo) #Benchmarking, using classical result for ground state energy, and then random energy measurement. self.classical_result = kwargs.get("classical_result", None) self.solve_classically() self.random_instance = QuantumInstance( backend=Aer.get_backend("aer_simulator_matrix_product_state"), shots=1000) #1000 randomly measured self.get_random_energy() #Simulation methods simulator = kwargs.get("simulator", None) noise_model = kwargs.get("noise_model", None) if simulator == None: simulator = "aer_simulator_density_matrix" print("Using " + simulator) self.quantum_instance = QuantumInstance( backend=Aer.get_backend(simulator), shots=8192, noise_model=noise_model, basis_gates=["cx", "x", "sx", "rz", "id"]) #Symmetrise if self.symmetrise: self.symmetrise_qubo() #Customise QAOA if self.customise: self.construct_initial_state(symmetrise=self.symmetrise) self.construct_mixer() else: self.initial_state = None self.mixer = None #Results placeholder self.prob_s = [] self.eval_s = [] self.approx_s = []
def quantum_instance( self, quantum_instance: Union[QuantumInstance, BaseBackend, Backend]) -> None: """ Sets quantum instance. """ if isinstance(quantum_instance, (BaseBackend, Backend)): quantum_instance = QuantumInstance(quantum_instance) self._quantum_instance = quantum_instance
def quantum_instance(self, quantum_instance: Union[QuantumInstance, Backend, BaseBackend]) -> None: """ Sets the QuantumInstance. Raises: ValueError: statevector or param_qobj are True when not supported by backend. """ if isinstance(quantum_instance, (Backend, BaseBackend)): quantum_instance = QuantumInstance(quantum_instance) self._quantum_instance = quantum_instance self._check_quantum_instance_and_modes_consistent()
def __init__( self, backend: Union[Backend, BaseBackend, QuantumInstance], statevector: Optional[bool] = None, param_qobj: bool = False, attach_results: bool = False, caching: str = "last", ) -> None: """ Args: backend: The quantum backend or QuantumInstance to use to sample the circuits. statevector: If backend is a statevector backend, whether to replace the CircuitStateFns with DictStateFns (from the counts) or VectorStateFns (from the statevector). ``None`` will set this argument automatically based on the backend. attach_results: Whether to attach the data from the backend ``Results`` object for a given ``CircuitStateFn``` to an ``execution_results`` field added the converted ``DictStateFn`` or ``VectorStateFn``. param_qobj: Whether to use Aer's parameterized Qobj capability to avoid re-assembling the circuits. caching: The caching strategy. Can be `'last'` (default) to store the last operator that was converted, set to `'all'` to cache all processed operators. Raises: ValueError: Set statevector or param_qobj True when not supported by backend. """ self._quantum_instance = ( backend if isinstance(backend, QuantumInstance) else QuantumInstance(backend=backend) ) self._statevector = ( statevector if statevector is not None else self.quantum_instance.is_statevector ) # Set to False until https://github.com/Qiskit/qiskit-aer/issues/1249 is closed. param_qobj = False self._param_qobj = param_qobj self._attach_results = attach_results self._check_quantum_instance_and_modes_consistent() # Object state variables self._caching = caching self._cached_ops: Dict[int, OperatorCache] = {} self._last_op: Optional[OperatorBase] = None self._reduced_op_cache = None self._circuit_ops_cache: Dict[int, CircuitStateFn] = {} self._transpiled_circ_cache: Optional[List[Any]] = None self._transpiled_circ_templates: Optional[List[Any]] = None self._transpile_before_bind = True
def __init__(self, backend: Union[Backend, BaseBackend, QuantumInstance], statevector: Optional[bool] = None, param_qobj: bool = False, attach_results: bool = False) -> None: """ Args: backend: The quantum backend or QuantumInstance to use to sample the circuits. statevector: If backend is a statevector backend, whether to replace the CircuitStateFns with DictStateFns (from the counts) or VectorStateFns (from the statevector). ``None`` will set this argument automatically based on the backend. attach_results: Whether to attach the data from the backend ``Results`` object for a given ``CircuitStateFn``` to an ``execution_results`` field added the converted ``DictStateFn`` or ``VectorStateFn``. param_qobj: Whether to use Aer's parameterized Qobj capability to avoid re-assembling the circuits. Raises: ValueError: Set statevector or param_qobj True when not supported by backend. """ self._quantum_instance = backend if isinstance(backend, QuantumInstance) else\ QuantumInstance(backend=backend) self._statevector = statevector if statevector is not None \ else self.quantum_instance.is_statevector self._param_qobj = param_qobj self._attach_results = attach_results self._check_quantum_instance_and_modes_consistent() # Object state variables self._last_op = None self._reduced_op_cache = None self._circuit_ops_cache = {} # type: Dict[int, CircuitStateFn] self._transpiled_circ_cache = None # type: Optional[List[Any]] self._transpiled_circ_templates = None # type: Optional[List[Any]] self._transpile_before_bind = True self._binding_mappings = None
def __init__(self, qubo, no_cars, no_routes, **kwargs): opt_str = kwargs.get('opt_str', "LN_SBPLX") self.symmetrise = kwargs.get('symmetrise', False) var_list = qubo.variables self.optimizer = NLOPT_Optimizer(opt_str) self.optimizer.set_options(max_eval=1000) self.original_qubo = qubo self.qubo = qubo self.solve_classically() op, offset = qubo.to_ising() self.operator = op self.offset = offset if self.symmetrise: self.symmetrise_qubo() self.quantum_instance = QuantumInstance( backend=Aer.get_backend("aer_simulator_matrix_product_state"), shots=4096) self.replacements = {var.name: None for var in var_list} self.no_cars = no_cars self.no_routes = no_routes self.car_blocks = np.empty(shape=(no_cars, ), dtype=object) for car_no in range(no_cars): self.car_blocks[car_no] = [ "X_{}_{}".format(car_no, route_no) for route_no in range(no_routes) ] self.qaoa_result = None self.benchmark_energy = None self.var_values = {} self.construct_initial_state() self.construct_mixer() self.get_random_energy() self.get_benchmark_energy() self.prob_s = [] self.approx_s = [] self.optimal_point = None
def __init__(self, qubo, no_cars, no_routes): var_list = qubo.variables opt_str = "LN_SBPLX" print("Optimizer: {}".format(opt_str)) self.optimizer = NLOPT_Optimizer(opt_str) self.original_qubo = qubo self.qubo = qubo op, offset = qubo.to_ising() self.operator = op self.offset = offset self.quantum_instance = QuantumInstance(backend = Aer.get_backend("aer_simulator_matrix_product_state"), shots = 1024) self.replacements = {var.name:None for var in var_list} self.no_cars = no_cars self.no_routes = no_routes self.car_blocks = np.empty(shape = (no_cars,), dtype=object) for car_no in range(no_cars): self.car_blocks[car_no] = ["X_{}_{}".format(car_no, route_no) for route_no in range(no_routes)] self.qaoa_result = None self.benchmark_energy = None self.var_values = {} self.construct_initial_state() self.construct_mixer() self.get_random_energy() self.get_benchmark_energy()
def main(args=None): """[summary] Args: raw_args ([type], optional): [description]. Defaults to None. """ start = time() if args == None: args = parse() qubo_no = args["no_samples"] print_to_file("-" * 50) print_to_file("QUBO_{}".format(qubo_no)) #Load generated qubo_no with open( 'qubos_{}_car_{}_routes/qubo_{}.pkl'.format( args["no_cars"], args["no_routes"], qubo_no), 'rb') as f: qubo, max_coeff, operator, offset, routes = pkl.load(f) qubo = QuadraticProgram() qubo.from_ising(operator) x_s, opt_value, classical_result = find_all_ground_states(qubo) print_to_file(classical_result) #Set optimizer method method = args["method"] optimizer = NLOPT_Optimizer(method=method, result_message=False) # optimizer = COBYLA() backend = Aer.get_backend("statevector_simulator") quantum_instance = QuantumInstance(backend=backend) approx_ratios = [] prob_s_s = [] p_max = args["p_max"] no_routes, no_cars = (args["no_routes"], args["no_cars"]) custom = True if custom: initial_state = construct_initial_state(no_routes=no_routes, no_cars=no_cars) mixer = n_qbit_mixer(initial_state) else: initial_state, mixer = (None, None) fourier_parametrise = args["fourier"] print_to_file("-" * 50) print_to_file( "Now solving with TQA_QAOA... Fourier Parametrisation: {}".format( fourier_parametrise)) # maxeval = 125 for p in range(1, p_max + 1): construct_circ = False deltas = np.arange(0.45, 0.91, 0.05) point = np.append([(i + 1) / p for i in range(p)], [1 - (i + 1) / p for i in range(p)]) points = [delta * point for delta in deltas] print_to_file("-" * 50) print_to_file(" " + "p={}".format(p)) if fourier_parametrise: points = [ convert_to_fourier_point(point, len(point)) for point in points ] # maxeval *= 2 #Double max_allowed evals for optimizer # optimizer.set_options(maxeval = maxeval) optimizer.set_options(maxeval=1000 * p) qaoa_results, optimal_circ = CustomQAOA( operator, quantum_instance, optimizer, reps=p, initial_state=initial_state, mixer=mixer, construct_circ=construct_circ, fourier_parametrise=fourier_parametrise, list_points=points, qubo=qubo) exp_val = qaoa_results.eigenvalue * max_coeff state_solutions = { item[0][::-1]: item[1:] for item in qaoa_results.eigenstate } for item in sorted(state_solutions.items(), key=lambda x: x[1][1], reverse=True)[0:5]: print_to_file(item) prob_s = 0 for string in x_s: prob_s += state_solutions[string][ 1] if string in state_solutions else 0 prob_s /= len(x_s) #normalise optimal_point = qaoa_results.optimal_point if fourier_parametrise: optimal_point = convert_from_fourier_point(optimal_point, len(optimal_point)) approx_ratio = 1 - np.abs((opt_value - exp_val) / opt_value) nfev = qaoa_results.cost_function_evals print_to_file( " " + "Optimal_point: {}, Nfev: {}".format(optimal_point, nfev)) print_to_file(" " + "Exp_val: {}, Prob_s: {}, approx_ratio: {}".format( exp_val, prob_s, approx_ratio)) approx_ratios.append(approx_ratio) prob_s_s.append(prob_s) print_to_file("-" * 50) print_to_file("QAOA terminated") print_to_file("-" * 50) print_to_file("Approximation ratios per layer: {}".format(approx_ratios)) print_to_file("Prob_success per layer: {}".format(prob_s_s)) save_results = np.append(approx_ratios, prob_s_s) if fourier_parametrise: with open( 'results_{}cars{}routes/TQA_F_{}.csv'.format( args["no_cars"], args["no_routes"], args["no_samples"]), 'w') as f: np.savetxt(f, save_results, delimiter=',') print_to_file( "Results saved in results_{}cars{}routes/TQA_F_{}.csv".format( args["no_cars"], args["no_routes"], args["no_samples"])) else: with open( 'results_{}cars{}routes/TQA_NF_{}.csv'.format( args["no_cars"], args["no_routes"], args["no_samples"]), 'w') as f: np.savetxt(f, save_results, delimiter=',') print_to_file( "Results saved in results_{}cars{}routes/TQA_NF_{}.csv".format( args["no_cars"], args["no_routes"], args["no_samples"])) finish = time() print_to_file("Time Taken: {}".format(finish - start))
def main(args=None): """[summary] Args: raw_args ([type], optional): [description]. Defaults to None. """ start = time() if args == None: args = parse() prob_s_s = [] qubo_no = args["no_samples"] print("__" * 50, "\nQUBO NO: {}\n".format(qubo_no), "__" * 50) #Load generated qubo_no with open( 'qubos_{}_car_{}_routes/qubo_{}.pkl'.format( args["no_cars"], args["no_routes"], qubo_no), 'rb') as f: qubo, max_coeff, operator, offset, routes = pkl.load(f) print(operator) x_s = find_all_ground_states(qubo) # Visualise if args["visual"]: graph = import_map('melbourne.pkl') visualise_solution(graph, routes) # Solve QAOA from QUBO with valid solution no_couplings = count_coupling_terms(operator) print("Number of couplings: {}".format(no_couplings)) print("Solving with QAOA...") no_shots = 10000 backend = Aer.get_backend('statevector_simulator') quantum_instance = QuantumInstance(backend, shots=no_shots) optimizer_method = "LN_SBPLX" optimizer = NLOPT_Optimizer(method=optimizer_method) print("_" * 50, "\n" + optimizer.__class__.__name__) print("_" * 50) quantum_instance = QuantumInstance(backend) prob_s_s = [] initial_state = construct_initial_state(args["no_routes"], args["no_cars"]) mixer = n_qbit_mixer(initial_state) next_fourier_point, next_fourier_point_B = [0, 0], [ 0, 0 ] #Not used for p=1 then gets updated for p>1. for p in range(1, args["p_max"] + 1): print("p = {}".format(p)) if p == 1: points = [[0.75,0]] \ # + [[ np.pi*(2*np.random.rand() - 1) for _ in range(2) ] for _ in range(args["no_restarts"])] draw_circuit = True else: penalty = 0.6 points = generate_points(next_fourier_point, no_perturb=10, penalty=0.6) print(points) \ # + generate_points(next_fourier_point_B, 10, penalty) draw_circuit = False #empty lists to save following results to choose best result results = [] exp_vals = [] for r in range(len(points)): point = points[r] if np.amax(np.abs(point)) < np.pi / 2: qaoa_results, optimal_circ = CustomQAOA( operator, quantum_instance, optimizer, reps=p, initial_fourier_point=points[r], initial_state=initial_state, mixer=mixer, construct_circ=draw_circuit) if r == 0: next_fourier_point = np.array(qaoa_results.optimal_point) next_fourier_point = QAOAEx.convert_from_fourier_point( next_fourier_point, 2 * p + 2) next_fourier_point = QAOAEx.convert_to_fourier_point( next_fourier_point, 2 * p + 2) exp_val = qaoa_results.eigenvalue * max_coeff + offset exp_vals.append(exp_val) prob_s = 0 for string in x_s: prob_s += qaoa_results.eigenstate[ string] if string in qaoa_results.eigenstate else 0 results.append((qaoa_results, optimal_circ, prob_s)) print("Point_no: {}, Exp_val: {}, Prob_s: {}".format( r, exp_val, prob_s)) else: print( "Point_no: {}, was skipped because it is outside of bounds" .format(r)) minim_index = np.argmin(exp_vals) optimal_qaoa_result, optimal_circ, optimal_prob_s = results[ minim_index] # if draw_circuit: # print(optimal_circ.draw()) minim_exp_val = exp_vals[minim_index] print("Minimum: {}, prob_s: {}".format(minim_exp_val, optimal_prob_s)) prob_s_s.append(optimal_prob_s) next_fourier_point_B = np.array(optimal_qaoa_result.optimal_point) print("Optimal_point: {}".format(next_fourier_point_B)) next_fourier_point_B = QAOAEx.convert_from_fourier_point( next_fourier_point_B, 2 * p + 2) next_fourier_point_B = QAOAEx.convert_to_fourier_point( next_fourier_point_B, 2 * p + 2) print(prob_s_s) with open( 'results/{}cars{}routes_qubo{}.csv'.format(args["no_cars"], args["no_routes"], args["no_samples"]), 'w') as f: np.savetxt(f, prob_s_s, delimiter=',') finish = time() print("Time Taken: {}".format(finish - start))
class CircuitSampler(ConverterBase): """ The CircuitSampler traverses an Operator and converts any CircuitStateFns into approximations of the state function by a DictStateFn or VectorStateFn using a quantum backend. Note that in order to approximate the value of the CircuitStateFn, it must 1) send state function through a depolarizing channel, which will destroy all phase information and 2) replace the sampled frequencies with **square roots** of the frequency, rather than the raw probability of sampling (which would be the equivalent of sampling the **square** of the state function, per the Born rule. The CircuitSampler aggressively caches transpiled circuits to handle re-parameterization of the same circuit efficiently. If you are converting multiple different Operators, you are better off using a different CircuitSampler for each Operator to avoid cache thrashing. """ def __init__(self, backend: Union[Backend, BaseBackend, QuantumInstance], statevector: Optional[bool] = None, param_qobj: bool = False, attach_results: bool = False) -> None: """ Args: backend: The quantum backend or QuantumInstance to use to sample the circuits. statevector: If backend is a statevector backend, whether to replace the CircuitStateFns with DictStateFns (from the counts) or VectorStateFns (from the statevector). ``None`` will set this argument automatically based on the backend. attach_results: Whether to attach the data from the backend ``Results`` object for a given ``CircuitStateFn``` to an ``execution_results`` field added the converted ``DictStateFn`` or ``VectorStateFn``. param_qobj: Whether to use Aer's parameterized Qobj capability to avoid re-assembling the circuits. Raises: ValueError: Set statevector or param_qobj True when not supported by backend. """ self._quantum_instance = backend if isinstance(backend, QuantumInstance) else\ QuantumInstance(backend=backend) self._statevector = statevector if statevector is not None \ else self.quantum_instance.is_statevector self._param_qobj = param_qobj self._attach_results = attach_results self._check_quantum_instance_and_modes_consistent() # Object state variables self._last_op = None self._reduced_op_cache = None self._circuit_ops_cache = {} # type: Dict[int, CircuitStateFn] self._transpiled_circ_cache = None # type: Optional[List[Any]] self._transpiled_circ_templates = None # type: Optional[List[Any]] self._transpile_before_bind = True self._binding_mappings = None def _check_quantum_instance_and_modes_consistent(self) -> None: """ Checks whether the statevector and param_qobj settings are compatible with the backend Raises: ValueError: statevector or param_qobj are True when not supported by backend. """ if self._statevector and not is_statevector_backend( self.quantum_instance.backend): raise ValueError( 'Statevector mode for circuit sampling requires statevector ' 'backend, not {}.'.format(self.quantum_instance.backend)) if self._param_qobj and not is_aer_provider( self.quantum_instance.backend): raise ValueError('Parameterized Qobj mode requires Aer ' 'backend, not {}.'.format( self.quantum_instance.backend)) @property def backend(self) -> Union[Backend, BaseBackend]: """ Returns the backend. Returns: The backend used by the CircuitSampler """ return self.quantum_instance.backend @backend.setter def backend(self, backend: Union[Backend, BaseBackend]): """ Sets backend without additional configuration. """ self.set_backend(backend) def set_backend(self, backend: Union[Backend, BaseBackend], **kwargs) -> None: """ Sets backend with configuration. Raises: ValueError: statevector or param_qobj are True when not supported by backend. """ self.quantum_instance = QuantumInstance(backend) self.quantum_instance.set_config(**kwargs) @property def quantum_instance(self) -> QuantumInstance: """ Returns the quantum instance. Returns: The QuantumInstance used by the CircuitSampler """ return self._quantum_instance @quantum_instance.setter def quantum_instance( self, quantum_instance: Union[QuantumInstance, Backend, BaseBackend]) -> None: """ Sets the QuantumInstance. Raises: ValueError: statevector or param_qobj are True when not supported by backend. """ if isinstance(quantum_instance, (Backend, BaseBackend)): quantum_instance = QuantumInstance(quantum_instance) self._quantum_instance = quantum_instance self._check_quantum_instance_and_modes_consistent() # pylint: disable=arguments-differ def convert( self, operator: OperatorBase, params: Optional[Dict[Parameter, Union[float, List[float], List[List[float]]]]] = None ) -> OperatorBase: r""" Converts the Operator to one in which the CircuitStateFns are replaced by DictStateFns or VectorStateFns. Extracts the CircuitStateFns out of the Operator, caches them, calls ``sample_circuits`` below to get their converted replacements, and replaces the CircuitStateFns in operator with the replacement StateFns. Args: operator: The Operator to convert params: A dictionary mapping parameters to either single binding values or lists of binding values. Returns: The converted Operator with CircuitStateFns replaced by DictStateFns or VectorStateFns. Raises: OpflowError: if extracted circuits are empty. """ if self._last_op is None or id(operator) != id(self._last_op): # Clear caches self._last_op = operator self._reduced_op_cache = None self._circuit_ops_cache = None self._transpiled_circ_cache = None self._transpile_before_bind = True if not self._reduced_op_cache: operator_dicts_replaced = operator.to_circuit_op() self._reduced_op_cache = operator_dicts_replaced.reduce() if not self._circuit_ops_cache: self._circuit_ops_cache = {} self._extract_circuitstatefns(self._reduced_op_cache) if not self._circuit_ops_cache: raise OpflowError( 'Circuits are empty. ' 'Check that the operator is an instance of CircuitStateFn or its ListOp.' ) if params is not None and len(params.keys()) > 0: p_0 = list(params.values())[0] # type: ignore if isinstance(p_0, (list, np.ndarray)): num_parameterizations = len(cast(List, p_0)) param_bindings = [ { param: value_list[i] # type: ignore for (param, value_list) in params.items() } for i in range(num_parameterizations) ] else: num_parameterizations = 1 param_bindings = [params] # type: ignore else: param_bindings = None num_parameterizations = 1 # Don't pass circuits if we have in the cache, the sampling function knows to use the cache circs = list(self._circuit_ops_cache.values() ) if not self._transpiled_circ_cache else None p_b = cast(List[Dict[Parameter, float]], param_bindings) sampled_statefn_dicts = self.sample_circuits(circuit_sfns=circs, param_bindings=p_b) def replace_circuits_with_dicts(operator, param_index=0): if isinstance(operator, CircuitStateFn): return sampled_statefn_dicts[id(operator)][param_index] elif isinstance(operator, ListOp): return operator.traverse( partial(replace_circuits_with_dicts, param_index=param_index)) else: return operator if params: return ListOp([ replace_circuits_with_dicts(self._reduced_op_cache, param_index=i) for i in range(num_parameterizations) ]) else: return replace_circuits_with_dicts(self._reduced_op_cache, param_index=0) def _extract_circuitstatefns(self, operator: OperatorBase) -> None: r""" Recursively extract the ``CircuitStateFns`` contained in operator into the ``_circuit_ops_cache`` field. """ if isinstance(operator, CircuitStateFn): self._circuit_ops_cache[id(operator)] = operator elif isinstance(operator, ListOp): for op in operator.oplist: self._extract_circuitstatefns(op) def sample_circuits( self, circuit_sfns: Optional[List[CircuitStateFn]] = None, param_bindings: Optional[List[Dict[Parameter, float]]] = None ) -> Dict[int, Union[StateFn, List[StateFn]]]: r""" Samples the CircuitStateFns and returns a dict associating their ``id()`` values to their replacement DictStateFn or VectorStateFn. If param_bindings is provided, the CircuitStateFns are broken into their parameterizations, and a list of StateFns is returned in the dict for each circuit ``id()``. Note that param_bindings is provided here in a different format than in ``convert``, and lists of parameters within the dict is not supported, and only binding dicts which are valid to be passed into Terra can be included in this list. Args: circuit_sfns: The list of CircuitStateFns to sample. param_bindings: The parameterizations to bind to each CircuitStateFn. Returns: The dictionary mapping ids of the CircuitStateFns to their replacement StateFns. Raises: OpflowError: if extracted circuits are empty. """ if not circuit_sfns and not self._transpiled_circ_cache: raise OpflowError('CircuitStateFn is empty and there is no cache.') if circuit_sfns: self._transpiled_circ_templates = None if self._statevector: circuits = [ op_c.to_circuit(meas=False) for op_c in circuit_sfns ] else: circuits = [ op_c.to_circuit(meas=True) for op_c in circuit_sfns ] try: self._transpiled_circ_cache = self.quantum_instance.transpile( circuits) except QiskitError: logger.debug( r'CircuitSampler failed to transpile circuits with unbound ' r'parameters. Attempting to transpile only when circuits are bound ' r'now, but this can hurt performance due to repeated transpilation.' ) self._transpile_before_bind = False self._transpiled_circ_cache = circuits else: circuit_sfns = list(self._circuit_ops_cache.values()) if param_bindings is not None: if self._param_qobj: start_time = time() ready_circs = self._prepare_parameterized_run_config( param_bindings) end_time = time() logger.debug('Parameter conversion %.5f (ms)', (end_time - start_time) * 1000) else: start_time = time() ready_circs = [ circ.assign_parameters(_filter_params(circ, binding)) for circ in self._transpiled_circ_cache for binding in param_bindings ] end_time = time() logger.debug('Parameter binding %.5f (ms)', (end_time - start_time) * 1000) else: ready_circs = self._transpiled_circ_cache results = self.quantum_instance.execute( ready_circs, had_transpiled=self._transpile_before_bind) if param_bindings is not None and self._param_qobj: self._clean_parameterized_run_config() # Wipe parameterizations, if any # self.quantum_instance._run_config.parameterizations = None sampled_statefn_dicts = {} for i, op_c in enumerate(circuit_sfns): # Taking square root because we're replacing a statevector # representation of probabilities. reps = len(param_bindings) if param_bindings is not None else 1 c_statefns = [] for j in range(reps): circ_index = (i * reps) + j circ_results = results.data(circ_index) if 'expval_measurement' in circ_results.get( 'snapshots', {}).get('expectation_value', {}): snapshot_data = results.data(circ_index)['snapshots'] avg = snapshot_data['expectation_value'][ 'expval_measurement'][0]['value'] if isinstance(avg, (list, tuple)): # Aer versions before 0.4 use a list snapshot format # which must be converted to a complex value. avg = avg[0] + 1j * avg[1] # Will be replaced with just avg when eval is called later num_qubits = circuit_sfns[0].num_qubits result_sfn = DictStateFn( '0' * num_qubits, is_measurement=op_c.is_measurement) * avg elif self._statevector: result_sfn = StateFn(op_c.coeff * results.get_statevector(circ_index), is_measurement=op_c.is_measurement) else: shots = self.quantum_instance._run_config.shots result_sfn = StateFn( { b: (v / shots)**0.5 * op_c.coeff for (b, v) in results.get_counts(circ_index).items() }, is_measurement=op_c.is_measurement) if self._attach_results: result_sfn.execution_results = circ_results c_statefns.append(result_sfn) sampled_statefn_dicts[id(op_c)] = c_statefns return sampled_statefn_dicts def _build_aer_params(self, circuit: QuantumCircuit, building_param_tables: Dict[Tuple[int, int], List[float]], input_params: Dict[Parameter, float]) -> None: def resolve_param(inst_param): if not isinstance(inst_param, ParameterExpression): return None param_mappings = {} for param in inst_param._parameter_symbols.keys(): if param not in input_params: raise ValueError('unexpected parameter: {0}'.format(param)) param_mappings[param] = input_params[param] return float(inst_param.bind(param_mappings)) gate_index = 0 for inst, _, _ in circuit.data: param_index = 0 for inst_param in inst.params: val = resolve_param(inst_param) if val is not None: param_key = (gate_index, param_index) if param_key in building_param_tables: building_param_tables[param_key].append(val) else: building_param_tables[param_key] = [val] param_index += 1 gate_index += 1 def _prepare_parameterized_run_config( self, param_bindings: List[Dict[Parameter, float]]) -> List[Any]: self.quantum_instance._run_config.parameterizations = [] if self._transpiled_circ_templates is None \ or len(self._transpiled_circ_templates) != len(self._transpiled_circ_cache): # temporally resolve parameters of self._transpiled_circ_cache # They will be overridden in Aer from the next iterations self._transpiled_circ_templates = [ circ.assign_parameters(_filter_params(circ, param_bindings[0])) for circ in self._transpiled_circ_cache ] for circ in self._transpiled_circ_cache: building_param_tables = { } # type: Dict[Tuple[int, int], List[float]] for param_binding in param_bindings: self._build_aer_params(circ, building_param_tables, param_binding) param_tables = [] for gate_and_param_indices in building_param_tables: gate_index = gate_and_param_indices[0] param_index = gate_and_param_indices[1] param_tables.append([[gate_index, param_index], building_param_tables[(gate_index, param_index)]]) self.quantum_instance._run_config.parameterizations.append( param_tables) return self._transpiled_circ_templates def _clean_parameterized_run_config(self) -> None: self.quantum_instance._run_config.parameterizations = []
def main(args = None): """[summary] Args: raw_args ([type], optional): [description]. Defaults to None. """ start = time() if args == None: args = parse() qubo_no = args["no_samples"] print_to_file("-"*50) print_to_file("QUBO_{}".format(qubo_no)) #Load generated qubo_no with open('qubos_{}_car_{}_routes/qubo_{}.pkl'.format(args["no_cars"], args["no_routes"], qubo_no), 'rb') as f: qubo, max_coeff, operator, offset, routes = pkl.load(f) qubo = QuadraticProgram() qubo.from_ising(operator) x_s, opt_value, classical_result = find_all_ground_states(qubo) print_to_file(classical_result) #Set optimizer method method = args["method"] optimizer = NLOPT_Optimizer(method = method, result_message=False) backend = Aer.get_backend("statevector_simulator") quantum_instance = QuantumInstance(backend = backend) approx_ratios = [] prob_s_s = [] p_max = args["p_max"] no_routes, no_cars = (args["no_routes"], args["no_cars"]) custom = True if custom: initial_state = construct_initial_state(no_routes = no_routes, no_cars = no_cars) mixer = n_qbit_mixer(initial_state) else: initial_state, mixer = (None, None) fourier_parametrise = args["fourier"] print_to_file("-"*50) print_to_file("Now solving with QAOA... Fourier Parametrisation: {}".format(fourier_parametrise)) for p in range(1, p_max+1): if p == 1: points = [[0,0]] + [ np.random.uniform(low = -np.pi/2+0.01, high = np.pi/2-0.01, size = 2*p) for _ in range(2**p)] next_point = [] else: penalty = 0.6 points = [next_point_l] + generate_points(next_point, no_perturb=min(2**p-1,10), penalty=penalty) construct_circ = False #empty lists to save following results to choose best result results = [] exp_vals = [] print_to_file("-"*50) print_to_file(" "+"p={}".format(p)) optimizer.set_options(maxeval = 1000*p) for r, point in enumerate(points): qaoa_results, optimal_circ = CustomQAOA(operator, quantum_instance, optimizer, reps = p, initial_fourier_point= point, initial_state = initial_state, mixer = mixer, construct_circ= construct_circ, fourier_parametrise = fourier_parametrise, qubo = qubo ) if r == 0: if fourier_parametrise: next_point_l = np.zeros(shape = 2*p + 2) next_point_l[0:p] = qaoa_results.optimal_point[0:p] next_point_l[p+1:2*p+1] = qaoa_results.optimal_point[p:2*p] else: next_point_l = interp_point(qaoa_results.optimal_point) exp_val = qaoa_results.eigenvalue * max_coeff exp_vals.append(exp_val) state_solutions = { item[0][::-1]: item[1:] for item in qaoa_results.eigenstate } for item in sorted(state_solutions.items(), key = lambda x: x[1][1], reverse = True)[0:5]: print_to_file( item ) prob_s = 0 for string in x_s: prob_s += state_solutions[string][1] if string in state_solutions else 0 prob_s /= len(x_s) #normalise results.append((qaoa_results, optimal_circ, prob_s)) print_to_file(" "+"Point_{}, Exp_val: {}, Prob_s: {}".format(r, exp_val, prob_s)) minim_index = np.argmin(exp_vals) optimal_qaoa_result, optimal_circ, optimal_prob_s = results[minim_index] if fourier_parametrise: next_point = convert_from_fourier_point( optimal_qaoa_result.optimal_point, 2*p ) next_point = convert_to_fourier_point( interp_point(next_point), 2*p + 2 ) # next_point = np.zeros(shape = 2*p + 2) # next_point[0:p] = optimal_qaoa_result.optimal_point[0:p] # next_point[p+1:2*p+1] = optimal_qaoa_result.optimal_point[p:2*p] else: next_point = interp_point(optimal_qaoa_result.optimal_point) if construct_circ: print_to_file(optimal_circ.draw(fold=150)) minim_exp_val = exp_vals[minim_index] approx_ratio = 1.0 - np.abs( (opt_value - minim_exp_val ) / opt_value ) print_to_file(" "+"Minimum: {}, prob_s: {}, approx_ratio {}".format(minim_exp_val, optimal_prob_s, approx_ratio)) approx_ratios.append(approx_ratio) prob_s_s.append(optimal_prob_s) print_to_file("-"*50) print_to_file("QAOA terminated") print_to_file("-"*50) print_to_file("Approximation ratios per layer: {}".format(approx_ratios)) print_to_file("Prob_success per layer: {}".format(prob_s_s)) save_results = np.append(approx_ratios, prob_s_s) if fourier_parametrise: with open('results_{}cars{}routes/RI_F_{}.csv'.format(args["no_cars"], args["no_routes"], args["no_samples"]), 'w') as f: np.savetxt(f, save_results, delimiter=',') print_to_file("Results saved in results_{}cars{}routes/RI_F_{}.csv".format(args["no_cars"], args["no_routes"], args["no_samples"])) else: with open('results_{}cars{}routes/RI_NF_{}.csv'.format(args["no_cars"], args["no_routes"], args["no_samples"]), 'w') as f: np.savetxt(f, save_results, delimiter=',') print_to_file("Results saved in results_{}cars{}routes/RI_NF_{}.csv".format(args["no_cars"], args["no_routes"], args["no_samples"])) finish = time() print_to_file("Time Taken: {}".format(finish - start))
def __init__(self, qubo, no_cars, no_routes, **kwargs): opt_str = kwargs.get('opt_str', "LN_COBYLA") self.symmetrise = kwargs.get('symmetrise', False) self.customise = kwargs.get('customise', True) self.classical_result = kwargs.get("classical_result", None) simulator = kwargs.get("simulator", "aer_simulator_matrix_product_state") noise_model = kwargs.get("noise_model", None) if simulator == None: simulator = "aer_simulator_matrix_product_state" #Initializing other algorithm required objects var_list = qubo.variables if noise_model == None: self.quantum_instance = QuantumInstance( backend = Aer.get_backend(simulator), shots = 4096) elif noise_model: self.quantum_instance = QuantumInstance( backend = Aer.get_backend(simulator), shots = 4096, noise_model = noise_model, basis_gates = ["cx", "x", "sx", "rz", "id"] ) self.random_instance = QuantumInstance(backend = Aer.get_backend("aer_simulator_matrix_product_state"), shots = 1000) #print backend name print("Quantum Instance: {}\n".format(self.quantum_instance.backend_name)) #print backend name self.optimizer = NLOPT_Optimizer(opt_str) self.optimizer.set_options(max_eval = 1000) self.original_qubo = qubo self.qubo = qubo self.operator, self.offset = qubo.to_ising() #If no classical result, this will compute the appropriate self.classical_result, else this will simply re-organise already available result self.solve_classically() #Setup for variable replacements self.replacements = {var.name:None for var in var_list} self.no_cars = no_cars self.no_routes = no_routes self.car_blocks = np.empty(shape = (no_cars,), dtype=object) for car_no in range(no_cars): self.car_blocks[car_no] = ["X_{}_{}".format(car_no, route_no) for route_no in range(no_routes)] #Initialize variable placeholders in self.qaoa_result = None self.initial_state = None self.mixer = None self.benchmark_energy = None self.var_values = {} self.prob_s = [] self.approx_s = [] self.optimal_point = None #Random energy self.get_random_energy() #Symmetrise QUBO if required (after getting random energy WITHOUT ancilla) if self.symmetrise: self.symmetrise_qubo() #Custom initial state and mixer if required if self.customise: if self.symmetrise: self.construct_initial_state(ancilla = True) else: self.construct_initial_state() self.construct_mixer()
def main(args=None): start = time() if args == None: args = parse() prob_s_s = [] qubo_no = args["no_samples"] print("__"*50, "\nQUBO NO: {}\n".format(qubo_no), "__"*50) #Load generated qubo_no with open('qubos_{}_car_{}_routes/qubo_{}.pkl'.format(args["no_cars"], args["no_routes"], qubo_no), 'rb') as f: qubo, max_coeff, operator, offset, routes = pkl.load(f) # print(operator) classical_result = solve_classically(qubo) print(classical_result) x_arr = classical_result.x optimal_value = qubo.objective.evaluate(x_arr) # print(optimal_value) x_str = arr_to_str(x_arr) sort_values = get_costs(qubo) # print("_"*50) # up_to = 27 # print("{} lowest states:".format(up_to)) # avg = 0 # for i in range(up_to): # print(sort_values[i]) # avg += sort_values[i][1] # print("_"*50) # print("Avg: {}".format(avg/up_to)) #Remake QUBO to introduce only ZiZj terms op, offset = qubo.to_ising() new_operator = [] for i, op_1 in enumerate(op): coeff, op_1 = op_1.to_pauli_op().coeff, op_1.to_pauli_op().primitive op_1_str = op_1.to_label() Z_counts = op_1_str.count('Z') if Z_counts == 1: op_1_str = 'Z' + op_1_str else: op_1_str = 'I' + op_1_str pauli = PauliOp( primitive = Pauli(op_1_str), coeff = coeff ) new_operator.append(pauli) qubo_2 = QuadraticProgram() operator = sum(new_operator) qubo_2.from_ising(operator, offset, linear=True) print("Solving with QAOA...") no_shots = 10000 backend = Aer.get_backend('statevector_simulator') quantum_instance = QuantumInstance(backend, shots = no_shots) optimizer_method = "LN_SBPLX" optimizer = NLOPT_Optimizer(method = optimizer_method) print("_"*50,"\n"+optimizer.__class__.__name__) print("_"*50) p = 1 delta_points = [] deltas = np.arange(0.75, 0.76, 0.05) print("delta_t's: ", deltas) original_point = np.append([], [[(i+1)/p, 1-(i+1)/p] for i in range(p)]) for delta in deltas: delta_points.append(delta*original_point) # point = [ 0.60081404, 0.11785113, 0.02330747, 1.10006101, 0.46256391, # -0.96823671] draw_circuit = True initial_state = construct_initial_state_2(args["no_routes"], args["no_cars"]) mixer = n_qbit_mixer(initial_state) quantum_instance = QuantumInstance(backend) results = [] exp_vals = [] for point in delta_points: point = QAOAEx.convert_to_fourier_point(point, 2*p) qaoa_results, _ = Fourier_QAOA(operator, quantum_instance, optimizer, reps = p, initial_fourier_point=point, initial_state = initial_state, mixer = mixer, construct_circ=draw_circuit, fourier_parametrise = True ) # print(optimal_circ.draw()) results.append(qaoa_results) exp_val = qaoa_results.eigenvalue + offset print("ExpVal {}".format(exp_val)) exp_vals.append(exp_val) minim_index = np.argmin(exp_vals) qaoa_results = results[minim_index] sort_states = sorted(qaoa_results.eigenstate.items(), key=lambda x: x[1], reverse=True) correlations = get_correlations(sort_states) # print(correlations) i,j = find_strongest_correlation(correlations) if correlations[i,j] > 0: condition = "Z_{i} = Z_{j}".format(i=i,j=j) else: condition = "Z_{i} = - Z_{j}".format(i=i,j=j) print("Max: <Z_{i}Z_{j}>={maxim}, condition: ".format(i=i, j=j, maxim = correlations[i,j])+condition) ground_energy = sort_values[0][1] x_s = [x_str] for i in range(0,10): if sort_values[i][0] == x_str or np.round(sort_values[i][1], 4) != np.round(ground_energy, 4): continue else: print("Other ground state(s) found: '{}'".format(sort_values[i][0])) x_s.append(sort_values[i][0]) x_s_2 = [] print("All the possible solutions were originally: ") print("[Z0 Z1 Z2 Z3 Z4 Z5 Z6 Z7 Z8 Z9]") for string in x_s: x = '0' + string x_arr = np.array(str_to_arr(x)) # print("f({x})={obj}".format(x=x, obj = qubo_2.objective.evaluate(x_arr))) x_s_2.append(x_arr) formatted_arr = ["{} ".format(item) for item in x_arr] formatted_arr = ' '.join(formatted_arr) print("[{}]".format(formatted_arr)) finish = time() print("Time taken {time}s".format(time=finish-start))
def main(): #Must load after importing/defining Ox_Route and QAOA_Traffic classes with open("traffic.pkl", 'rb') as f: traffic = pkl.load(f) routing_dict = { var: traffic.routing_dict()[var].routing() for var in traffic.routing_dict() } edges_dict = get_edges_dict(routing_dict) new_dict = deepcopy(edges_dict) #Remove edges with <50m overlaps. for edge, value in edges_dict.items(): weight = 0 edge_data = traffic.obtain_map().get_edge_data(*edge, default=[None])[0] if edge_data: weight += edge_data["length"] if weight < 50: # print(edge, value, weight) new_dict.pop(edge, None) variable_renaming = { "Car_{}_Route_{}".format(str(i).zfill(2), j): "X_{}_{}".format(str(i).zfill(2), j) for i, j in product(range(21), range(3)) } new_edges_dict = {} for edge, variables in new_dict.items(): new_edges_dict[edge] = [variable_renaming[var] for var in variables] del edges_dict del new_dict global qubo unconstrained_qubo, linear, quadratic = build_qubo_unconstrained_from_edges_dict( traffic.obtain_map(), new_edges_dict, variables=variable_renaming.values()) qubo = add_qubo_constraints(unconstrained_qubo, no_cars=21, no_routes=3) qubo, max_coeff = convert_qubo(qubo, linear, quadratic, penalty_multiplier=1.5) min_results = {} min_total_obj = 0 max_results = {} max_total_obj = 0 for car in range(21): zeros = [0] * 3 assignments = [[0] * i + [1] + [0] * (2 - i) for i in range(3)] assignments_obj = {} for assignment in assignments: x = zeros * (car) + assignment + zeros * (20 - car) var_dict = { "X_{}_{}".format(str(int((k - k % 3) / 3)).zfill(2), k % 3): x[k] for k in range(len(x)) } obj = unconstrained_qubo.objective.evaluate(var_dict) assignments_obj[tuple(assignment)] = obj min_assignment = min(assignments_obj.items(), key=lambda x: x[1]) max_assignment = max(assignments_obj.items(), key=lambda x: x[1]) min_total_obj += min_assignment[1] max_total_obj += max_assignment[1] min_car_dict_assignment = { "X_{}_{}".format(str(car).zfill(2), k): min_assignment[0][k] for k in range(3) } max_car_dict_assignment = { "X_{}_{}".format(str(car).zfill(2), k): max_assignment[0][k] for k in range(3) } for var, value in min_car_dict_assignment.items(): min_results[var] = value for var, value in max_car_dict_assignment.items(): max_results[var] = value greedy = qubo.objective.evaluate(min_results) max_greedy = qubo.objective.evaluate(max_results) print("Zeros:", qubo.objective.evaluate([0 for _ in range(63)])) print("MIN GREEDY:", greedy) print("Total distance traversed(min):", min_total_obj) print(min_results) print("MAX GREEDY:", max_greedy) print("Total distance traversed(max):", max_total_obj) print(max_results) optimizer = NELDER_MEAD() optimizer.set_options(maxiter=1) backend = Aer.get_backend("aer_simulator_matrix_product_state") quantum_instance = QuantumInstance(backend, shots=1) op, offset = qubo.to_ising() op *= 1 / max_coeff print(op) # initial_state = construct_initial_state(no_routes = 3, no_cars = 21) # mixer = n_qbit_mixer(initial_state) #p=1 start = time() result, qc = QiskitQAOA(operator=op, quantum_instance=quantum_instance, optimizer=optimizer, reps=1, construct_circ=True, initial_state=None, mixer=None, initial_point=[0, 0]) print(qc.draw()) print(qc.depth()) end = time() print(result.eigenstate) print(max_coeff * (result.eigenvalue) + offset) print("p=1, Time taken: {}s".format(end - start)) print(result.cost_function_evals)