def _run(self): """ Run the algorithm to compute the minimum eigenvalue. Returns: Dictionary of results """ if not self._quantum_instance.is_statevector and self._operator_mode == 'matrix': logger.warning( 'Qasm simulation does not work on {} mode, changing ' 'the operator_mode to "paulis"'.format(self._operator_mode)) self._operator_mode = 'paulis' self._use_simulator_operator_mode = \ is_aer_statevector_backend(self._quantum_instance.backend) \ and self._operator_mode != 'matrix' self._quantum_instance.circuit_summary = True self._eval_count = 0 self._solve() self._get_ground_state_energy() self._eval_aux_ops() self._ret['eval_count'] = self._eval_count self._ret['eval_time'] = self._eval_time return self._ret
def _config_the_best_mode(self, operator, backend): if not isinstance(operator, (WeightedPauliOperator, MatrixOperator, TPBGroupedWeightedPauliOperator)): logger.debug("Unrecognized operator type, skip auto conversion.") return operator ret_op = operator if not is_statevector_backend( backend): # assume qasm, should use grouped paulis. if isinstance(operator, (WeightedPauliOperator, MatrixOperator)): logger.debug( "When running with Qasm simulator, grouped pauli can " "save number of measurements. " "We convert the operator into grouped ones.") ret_op = op_converter.to_tpb_grouped_weighted_pauli_operator( operator, TPBGroupedWeightedPauliOperator.sorted_grouping) else: if not is_aer_statevector_backend(backend): if not isinstance(operator, MatrixOperator): logger.info( "When running with non-Aer statevector simulator, " "represent operator as a matrix could " "achieve the better performance. We convert " "the operator to matrix.") ret_op = op_converter.to_matrix_operator(operator) else: if not isinstance(operator, WeightedPauliOperator): logger.info("When running with Aer statevector simulator, " "represent operator as weighted paulis could " "achieve the better performance. We convert " "the operator to weighted paulis.") ret_op = op_converter.to_weighted_pauli_operator(operator) return ret_op
def _run(self): """ Run the algorithm to compute the minimum eigenvalue. Returns: dict: Dictionary of results Raises: AquaError: wrong setting of operator and backend. """ if self._auto_conversion: self._operator = \ self._config_the_best_mode(self._operator, self._quantum_instance.backend) for i in range(len(self._aux_operators)): if not self._aux_operators[i].is_empty(): self._aux_operators[i] = \ self._config_the_best_mode(self._aux_operators[i], self._quantum_instance.backend) # sanity check if isinstance( self._operator, MatrixOperator) and not self._quantum_instance.is_statevector: raise AquaError("Non-statevector simulator can not work " "with `MatrixOperator`, either turn ON " "auto_conversion or use the proper " "combination between operator and backend.") self._use_simulator_operator_mode = \ is_aer_statevector_backend(self._quantum_instance.backend) \ and isinstance(self._operator, (WeightedPauliOperator, TPBGroupedWeightedPauliOperator)) self._quantum_instance.circuit_summary = True self._eval_count = 0 self._ret = self.find_minimum(initial_point=self.initial_point, var_form=self.var_form, cost_fn=self._energy_evaluation, optimizer=self.optimizer) if self._ret['num_optimizer_evals'] is not None and \ self._eval_count >= self._ret['num_optimizer_evals']: self._eval_count = self._ret['num_optimizer_evals'] self._eval_time = self._ret['eval_time'] logger.info( 'Optimization complete in %s seconds.\nFound opt_params %s in %s evals', self._eval_time, self._ret['opt_params'], self._eval_count) self._ret['eval_count'] = self._eval_count self._ret['energy'] = self.get_optimal_cost() self._ret['eigvals'] = np.asarray([self.get_optimal_cost()]) self._ret['eigvecs'] = np.asarray([self.get_optimal_vector()]) self._eval_aux_ops() self.cleanup_parameterized_circuits() return self._ret
def _run(self): """ Run the algorithm to compute the minimum eigenvalue. Returns: Dictionary of results """ if not self._quantum_instance.is_statevector and self._operator_mode == 'matrix': logger.warning( 'Qasm simulation does not work on {} mode, changing ' 'the operator_mode to "paulis"'.format(self._operator_mode)) self._operator_mode = 'paulis' self._use_simulator_operator_mode = \ is_aer_statevector_backend(self._quantum_instance.backend) \ and self._operator_mode != 'matrix' self._quantum_instance.circuit_summary = True self._eval_count = 0 self._ret = self.find_minimum(initial_point=self.initial_point, var_form=self.var_form, cost_fn=self._energy_evaluation, optimizer=self.optimizer) if self._ret[ 'num_optimizer_evals'] is not None and self._eval_count >= self._ret[ 'num_optimizer_evals']: self._eval_count = self._ret['num_optimizer_evals'] self._eval_time = self._ret['eval_time'] logger.info( 'Optimization complete in {} seconds.\nFound opt_params {} in {} evals' .format(self._eval_time, self._ret['opt_params'], self._eval_count)) self._ret['eval_count'] = self._eval_count self._ret['energy'] = self.get_optimal_cost() self._ret['eigvals'] = np.asarray([self.get_optimal_cost()]) self._ret['eigvecs'] = np.asarray([self.get_optimal_vector()]) self._eval_aux_ops() return self._ret
def update_backend_schema(self, input_parser): """ Updates backend schema """ if JSONSchema.BACKEND not in self._schema['properties']: return # Updates defaults provider/backend default_provider_name = None default_backend_name = None orig_backend_properties = self._original_schema.get( 'properties', {}).get(JSONSchema.BACKEND, {}).get('properties') if orig_backend_properties is not None: default_provider_name = orig_backend_properties.get( JSONSchema.PROVIDER, {}).get('default') default_backend_name = orig_backend_properties.get( JSONSchema.NAME, {}).get('default') providers = get_local_providers() if default_provider_name is None or default_provider_name not in providers: # use first provider available providers_items = providers.items() provider_tuple = next( iter(providers_items)) if len(providers_items) > 0 else ('', []) default_provider_name = provider_tuple[0] if default_backend_name is None or default_backend_name not in providers.get( default_provider_name, []): # use first backend available in provider default_backend_name = providers.get( default_provider_name)[0] if len( providers.get(default_provider_name, [])) > 0 else '' self._schema['properties'][JSONSchema.BACKEND] = { 'type': 'object', 'properties': { JSONSchema.PROVIDER: { 'type': 'string', 'default': default_provider_name }, JSONSchema.NAME: { 'type': 'string', 'default': default_backend_name }, }, 'required': [JSONSchema.PROVIDER, JSONSchema.NAME], 'additionalProperties': False, } provider_name = input_parser.get_section_property( JSONSchema.BACKEND, JSONSchema.PROVIDER, default_provider_name) backend_names = get_backends_from_provider(provider_name) backend_name = input_parser.get_section_property( JSONSchema.BACKEND, JSONSchema.NAME, default_backend_name) if backend_name not in backend_names: # use first backend available in provider backend_name = backend_names[0] if len(backend_names) > 0 else '' backend = get_backend_from_provider(provider_name, backend_name) config = backend.configuration() # Include shots in schema only if not a statevector backend. # For statevector, shots will be set to 1, in QiskitAqua if not is_statevector_backend(backend): self._schema['properties'][ JSONSchema.BACKEND]['properties']['shots'] = { 'type': 'integer', 'minimum': 1, } default_shots = 1024 # ensure default_shots <= max_shots if config.max_shots: default_shots = min(default_shots, config.max_shots) self._schema['properties'][JSONSchema.BACKEND]['properties'][ 'shots']['maximum'] = config.max_shots self._schema['properties'][JSONSchema.BACKEND]['properties'][ 'shots']['default'] = default_shots self._schema['properties'][ JSONSchema.BACKEND]['properties']['skip_transpiler'] = { 'type': 'boolean', 'default': False, } coupling_map_devices = [] noise_model_devices = [] check_coupling_map = is_simulator_backend(backend) check_noise_model = is_aer_provider( backend) and not is_aer_statevector_backend(backend) try: if (check_coupling_map or check_noise_model) and has_ibmq(): backend_names = get_backends_from_provider('qiskit.IBMQ') for backend_name in backend_names: ibmq_backend = get_backend_from_provider( 'qiskit.IBMQ', backend_name) if is_simulator_backend(ibmq_backend): continue if check_noise_model: noise_model_devices.append('qiskit.IBMQ:' + backend_name) if check_coupling_map and ibmq_backend.configuration( ).coupling_map: coupling_map_devices.append('qiskit.IBMQ:' + backend_name) except Exception as e: logger.debug("Failed to load IBMQ backends. Error {}".format( str(e))) # Includes 'coupling map' and 'coupling_map_from_device' in schema only if a simulator backend. # Actual devices have a coupling map based on the physical configuration of the device. # The user can configure the coupling map so its the same as the coupling map # of a given device in order to better simulate running on the device. # Property 'coupling_map_from_device' is a list of provider:name backends that are # real devices e.g qiskit.IBMQ:ibmqx5. # If property 'coupling_map', an array, is provided, it overrides coupling_map_from_device, # the latter defaults to 'None'. So in total no coupling map is a default, i.e. all to all coupling is possible. if is_simulator_backend(backend): self._schema['properties'][ JSONSchema.BACKEND]['properties']['coupling_map'] = { 'type': ['array', 'null'], 'default': None, } if len(coupling_map_devices) > 0: coupling_map_devices.append(None) self._schema['properties'][JSONSchema.BACKEND]['properties'][ 'coupling_map_from_device'] = { 'type': ['string', 'null'], 'default': None, 'oneOf': [{ 'enum': coupling_map_devices }], } # noise model that can be setup for Aer simulator so as to model noise of an actual device. if len(noise_model_devices) > 0: noise_model_devices.append(None) self._schema['properties'][ JSONSchema.BACKEND]['properties']['noise_model'] = { 'type': ['string', 'null'], 'default': None, 'oneOf': [{ 'enum': noise_model_devices }], } # If a noise model is supplied then the basis gates is set as per the noise model # unless basis gates is not None in which case it overrides noise model and a warning msg is logged. # as it is an advanced use case. self._schema['properties'][ JSONSchema.BACKEND]['properties']['basis_gates'] = { 'type': ['array', 'null'], 'default': None, } # TODO: Not sure if we want to continue with initial_layout in declarative form. # It requires knowledge of circuit registers etc. Perhaps its best to leave this detail to programming API. self._schema['properties'][ JSONSchema.BACKEND]['properties']['initial_layout'] = { 'type': ['object', 'null'], 'default': None, } # The same default and minimum as current RunConfig values self._schema['properties'][ JSONSchema.BACKEND]['properties']['max_credits'] = { 'type': 'integer', 'default': 10, 'minimum': 3, 'maximum': 10, } # Timeout and wait are for remote backends where we have to connect over network if not is_local_backend(backend): self._schema['properties'][ JSONSchema.BACKEND]['properties']['timeout'] = { "type": ["number", "null"], 'default': None, } self._schema['properties'][ JSONSchema.BACKEND]['properties']['wait'] = { 'type': 'number', 'default': 5.0, 'minimum': 0.0, }
def _run(self): """ Run the algorithm to compute the minimum eigenvalue. Returns: dict: Dictionary of results Raises: AquaError: wrong setting of operator and backend. """ self._operator = VQE._config_the_best_mode( self, self._operator, self._quantum_instance.backend) self._use_simulator_operator_mode = \ is_aer_statevector_backend(self._quantum_instance.backend) \ and isinstance(self._operator, (WeightedPauliOperator, TPBGroupedWeightedPauliOperator)) self._quantum_instance.circuit_summary = True cycle_regex = re.compile(r'(.+)( \1)+') # reg-ex explanation: # 1. (.+) will match at least one number and try to match as many as possible # 2. the match of this part is placed into capture group 1 # 3. ( \1)+ will match a space followed by the contents of capture group 1 # -> this results in any number of repeating numbers being detected threshold_satisfied = False alternating_sequence = False prev_op_indices = [] theta = [] max_grad = () iteration = 0 while not threshold_satisfied and not alternating_sequence: iteration += 1 logger.info('--- Iteration #%s ---', str(iteration)) # compute gradients cur_grads = self._compute_gradients(self._excitation_pool, theta, self._delta, self._var_form_base, self._operator, self._optimizer) # pick maximum gradient max_grad_index, max_grad = max(enumerate(cur_grads), key=lambda item: np.abs(item[1][0])) # store maximum gradient's index for cycle detection prev_op_indices.append(max_grad_index) # log gradients gradlog = "\nGradients in iteration #{}".format(str(iteration)) gradlog += "\nID: Excitation Operator: Gradient <(*) maximum>" for i, grad in enumerate(cur_grads): gradlog += '\n{}: {}: {}'.format(str(i), str(grad[1]), str(grad[0])) if grad[1] == max_grad[1]: gradlog += '\t(*)' logger.info(gradlog) if np.abs(max_grad[0]) < self._threshold: logger.info( "Adaptive VQE terminated succesfully with a final maximum gradient: %s", str(np.abs(max_grad[0]))) threshold_satisfied = True break # check indices of picked gradients for cycles if cycle_regex.search(' '.join(map(str, prev_op_indices))) is not None: logger.info("Alternating sequence found. Finishing.") logger.info("Final maximum gradient: %s", str(np.abs(max_grad[0]))) alternating_sequence = True break # add new excitation to self._var_form_base self._var_form_base.push_hopping_operator(max_grad[1]) theta.append(0.0) # run VQE on current Ansatz algorithm = VQE(self._operator, self._var_form_base, self._optimizer, initial_point=theta) self._ret = algorithm.run(self._quantum_instance) theta = self._ret['opt_params'].tolist() # once finished evaluate auxiliary operators if any if self._aux_operators is not None and self._aux_operators: algorithm = VQE(self._operator, self._var_form_base, self._optimizer, initial_point=theta, aux_operators=self._aux_operators) self._ret = algorithm.run(self._quantum_instance) # extend VQE returned information with additional outputs logger.info('The final energy is: %s', str(self._ret['energy'])) self._ret['num_iterations'] = iteration self._ret['final_max_grad'] = max_grad[0] if threshold_satisfied: self._ret['finishing_criterion'] = 'threshold_converged' elif alternating_sequence: self._ret['finishing_criterion'] = 'aborted_due_to_cyclicity' else: raise AquaError( 'The algorithm finished due to an unforeseen reason!') return self._ret