GithubHelp home page GithubHelp logo

entropicalabs / openqaoa Goto Github PK

View Code? Open in Web Editor NEW
114.0 114.0 59.0 288.18 MB

Multi-backend SDK for quantum optimisation

License: MIT License

Python 99.71% Dockerfile 0.01% Makefile 0.10% Shell 0.19%
optimization qaoa quantum-algorithms quantum-computing rqaoa

openqaoa's People

Contributors

adirlou avatar adrianolusso avatar alejomonbar avatar alexisralli avatar christianbmadsen avatar dependabot[bot] avatar emilianog-byte avatar ezerc avatar giacomofrn avatar kidiki avatar kilianpoirier avatar krankgeflugel avatar madhubanimayank avatar maldoalberto avatar mar-ven avatar newtech66 avatar q-lds avatar raulconchello avatar shahidee44 avatar shaohenc avatar terravenil avatar victor-onofre avatar vijeycreative avatar vishal-ph avatar voidburn avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

openqaoa's Issues

Error in documentation rendering

Issue Description

On chrome and microsoft edge, the documentation 04 - Working with the QAOA Variational Parameter Classes has the following rendering error:

image

This is on a windows PC.

Cost vs iterations plot

Description

Now when you call q.results.plot_cost() you get a plot of cost vs number of function evaluations. Like the following:

image

It could be interesting to have another method that plots cost vs number of iterations, so as to see the cost at the end of each iteration of the classical optimizer.

Remove Results obtained from minimize function and capture total number of evaluations

To remove the results returned by Scipy's minimize function.

Note: Some of the evaluations made using the scipy minimize function, for methods that use the jacobian, are not kept tracked off.
To create a way to record the number of evaluations from both the function calls to optimise_this and the those used to compute the jacobian.

The Backend Class returns the appropriate callback function for the jacobian evaluations. We can make modifications to that callback to capture the information we need to return to the user.

To make sure every call to .expectation of the backend class is recorded/kept track off.

For methods like BFGS, it calls the optimise_this method. We need to make sure we are updating the log lists appropriately.

Come up with a cleaner way to process Results from OptimizeVQA

Issue

Currently in the workflow, there needs to be branching if/else statements to handle the different result outputs from the various backends in OptimizeVQA. 'vectorized' producing its results as a probability vector while shot-based backends outputing their results in counts. The results populate different entries in the results_dictionary depending on the backend used.
We should find a more unified way to combine these 2 together. Since in the current version. workflows post-processes the results as well.

Solution

Having the results from the Logger Class go directly into a Results Object that post-processes the results one more time should make the code look cleaner.

Current version cannot be installed due to package incompatibility - both through PyPI and using the local package

Prerequisites

Before raising this issue, I have already checked that I am:

  • running the latest version
  • made sure that this issue has not already been filed

Describe the bug

OpenQAOA cannot be installed currently due to conflicting package requirements. Most likely due to the usage of an older version of the pyquil package.

To Reproduce

Steps to reproduce the behavior:

  • pip install openqaoa

  • clone openqaoa locally and use make dev-install-all

Expected behavior

The package should be installed correctly

Additional context

The current OpenQAOA version makes use of pyquil 3.5.4 to ignore breaking changes occuring with 4.X

Issue with property "q.set_classical_optimizer(optimize=False)"

Describe the bug

I was trying to use OpenQAOA to run only the optimised circuit of my QAOA instance. I have used the simulator to derive the optimal variational parameters, and I wanted to run only the final circuit on the IBMQ cloud.

I used the following command (where qsim_qiskit is my QAOA() object)
qsim_qiskit.set_classical_optimizer(optimize=False)

While it worked on the local qiskit simulator, on the cloud it sent multiple jobs (I am not sure how many iterations it was considering, eventually I killed the jobs).

To Reproduce

Steps to reproduce the behavior:

# initialize model with default configurations
qsim_qiskit = QAOA()

# optionally configure the following properties of the model
# device
qiskit_cloud = create_device(location='ibmq', name='ibmq_qasm_simulator', **qpu_credentials)
qsim_qiskit.set_device(qiskit_cloud)

#qiskit_device = create_device(location='local', name='qiskit.statevector_simulator')
#qsim_qiskit.set_device(qiskit_device)

# circuit properties
qsim_qiskit.set_circuit_properties(p=2, param_type='standard', init_type='custom', mixer_hamiltonian='x',
                                variational_params_dict={
                                    "betas":variational_params.betas.tolist(),
                                    "gammas":variational_params.gammas.tolist()
                                    })


# backend properties (already set by default)
qsim_qiskit.set_backend_properties(prepend_state=None, append_state=None)

#qsim_qiskit.set_classical_optimizer(optimize=False) # **<--- This is the problematic line**

Expected behavior

I want to be able to run only one circuit on the IBMQ cloud

Note that the following command works (but it's not ideal)
#qsim_qiskit.set_classical_optimizer(optimize=False) qsim_qiskit.set_classical_optimizer(method='cobyla', maxiter=0, cost_progress=True, parameter_log=True, optimization_progress=True)

Screenshot 2023-02-19 at 1 45 05 PM

Avoid measurement_outcomes during optimization

I like the openQAOA ecosystem and I am trying to integrate a tensor network based backend (using cuQuantum SDK), which does not calculate the explicit wf as statevec. I can use qiskit circuits as starting point before converting them to perform TN contractions, so I adapted a backend from qiskit_sim. However the optimization fails at the first cycle without measurement_outcomes.

Here is the kernel code from the backend, is there a way to bypass measurement_outcomes?

    def expectation(self,
                    params: QAOAVariationalBaseParams) -> float:

        ckt = self.qaoa_circuit(params)

        ## QISKIT VERSION
        # output_wf = Statevector(ckt)
        # self.measurement_outcomes = output_wf.data
        # cost = np.real(output_wf.expectation_value(self.qiskit_cost_hamil))
         
        ## CUQUANTUM VERSION
        einsum = CircuitToEinsum(ckt, dtype='complex128', backend=cp)
        cost = 0
        for pauli_term_list in self.qiskit_cost_hamil:
            pauli_term = str(pauli_term_list).split(' * ')
            expression, operands = einsum.expectation(pauli_term[1], lightcone=True)
            expec = contract(expression, *operands)
            cost += np.real(expec * float(pauli_term[0]))
        return cost

QAOA and RQAOA objects with "already_optimized" flag

Problem description

A qaoa or a rqaoa object can be optimized more than once without recompiling again.
The following code is now valid:

q = qaoa()
q.compile(problem)
q.optimize()
...
q.optimize()

Solution description

If you run the code above, an error should be raised saying that the qaoa object is already optimized and that it should be compiled before optimizing again.

That could be done by implementing a boolean already_optimized that is False when the user compiles and it's True when they optimize. If the boolean is True then the warning is raised.

Inconsistencies when using random_instance() to generate a random instance of a problem class

Problem

When trying to create a random instance of a number partitioning problem, I get the following error

image

The core issue is that random_instance() is a static method and should be used as such:
image

The inconsistency is made worst by the fact that I can do the following, where the numbers I pass to the constructor are right away changed by the random_instance() method

image

#Solution

I am unsure what's the best way to go about this, but we should review the way that random instances are created across the pre-defined problem settings.

Bugfix for energy calculation in `utilities.py` if Hamiltonian register is not [0, ..., n]

Several energy calculation functions in utilities.py will fail if Hamiltonian object contains terms that are not in the range [0, ..., n], returning an out-of-bounds error. Reason: in these functions, the terms of the Hamiltonian (which may be more than n) is used directly as indices for the bitstring (which has length n). A simple fix is to 're-zero' the terms in the Hamiltonian object so that they range from [0, ...., n].

Affected functions in utilities:
bitstring_energy, energy_expectation, energy_spectrum_hamiltonian

Example solution:

def bitstring_energy(terms:list,
                     weights:list,
                     bitstring:Union[List[int],str]) -> float:
    """
    Computes the energy of a given bitstring with respect to the cost Hamiltonian.
    
    Parameters
    ----------
    terms: list
        Hamiltonian terms
    weights: list
        Coefficients of the hamiltonian terms
    bitstring : Union[list,str]
        A list of integers 0 and 1 of length `n_qubits` representing a configuration
        or a string of bits of length `n_qubits`.

    Returns
    -------
    energy:
        The energy of a given bitstring with respect to the cost Hamiltonian.
    """
    
    # Re-zero terms to prevent out of range error
    rezeroed_terms = rezero_terms(terms)

    energy = 0
    # string_rev = bitstring
    for i, term in enumerate(rezeroed_terms):

        if len(term) == 0:
            energy += np.real(weights[i])
        else:
            variables_product = np.prod([(-1)**int(bitstring[k]) for k in term])
            energy += weights[i]*variables_product
    
    return energy

def rezero_terms(terms):
    
    copied_terms = deepcopy(terms)
    indices = list(set([item for sublist in copied_terms for item in sublist]))
    zero_indices = list(range(len(set([item for sublist in copied_terms for item in sublist]))))
    
    for pairs in copied_terms:
        for i, item in enumerate(pairs):
            pairs[i] = zero_indices[indices.index(item)]
            
    return copied_terms

`random_classical_hamiltonian` has an unexpected behaviour

Function description:
The random classical hamiltonian accepts as input the qubit_register as a List to define a random cost hamiltonian on those qubits. The function's logic randomly either creates an edge between possible pairs of qubits in the qubit_register or omits it.

Unexpected behavior:
For some runs, stochastically, the final hamiltonian ends up having fewer qubits in total than the specified qubit_register. However, if, the mixer_hamiltonian is defined on the original qubit_register it leads to a mismatch in the number of qubits in the QAOA circuit leading to index out of bounds error.

The following is an example of the traceback messages resulting from this error:

---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
File ~/.conda/envs/openqaoa_may22/lib/python3.8/site-packages/qiskit/circuit/quantumcircuit.py:4814, in _bit_argument_conversion(specifier, bit_sequence, bit_set, type_)
   4813 try:
-> 4814     return [bit_sequence[specifier]]
   4815 except IndexError as ex:

IndexError: list index out of range

The above exception was the direct cause of the following exception:

CircuitError                              Traceback (most recent call last)
Input In [1], in <cell line: 24>()
     19 qaoa_circuit_params = QAOACircuitParams(
     20     cost_hamiltonian, mixer_hamiltonian, p)
     21 variational_params_std = QAOAVariationalStandardParams(
     22     qaoa_circuit_params, betas, gammas)
---> 24 backend_qiskit_statevec = get_qaoa_backend(
     25     qaoa_circuit_params, 'qiskit_statevec_simulator')

File ~/openqaoa_github/openqaoa/openqaoa/backends/qaoa_backend.py:144, in get_qaoa_backend(circuit_params, device, prepend_state, append_state, init_hadamard, cvar_alpha, **kwargs)
    142     backend_class = backend_name_to_object_mapper(simulator_name)
    143     backend_kwargs = _backend_arg_mapper(backend_class, **kwargs)
--> 144     backend_obj = backend_class(circuit_params=circuit_params, prepend_state=prepend_state,
    145                                 append_state=append_state, init_hadamard=init_hadamard,
    146                                 cvar_alpha=cvar_alpha, **backend_kwargs)
    147     # except TypeError:
    148     #     raise TypeError(
    149     #         'Please make sure the **kwargs are supported by the chosen backend')
   (...)
    152     #     raise ValueError(
    153     #         f"{e} The backend {simulator_name} returned an error")
    155 elif isinstance(device, AccessObjectBase):

File ~/openqaoa_github/openqaoa/openqaoa/backends/simulators/qaoa_qiskit_sim.py:239, in QAOAQiskitBackendStatevecSimulator.__init__(self, circuit_params, prepend_state, append_state, init_hadamard, cvar_alpha)
    235     assert self.n_qubits >= len(prepend_state.qubits), "Cannot attach a bigger circuit " \
    236                                                         "to the QAOA routine"
    238 # For parametric circuits
--> 239 self.parametric_circuit = self.parametric_qaoa_circuit
    240 self.qiskit_cost_hamil = self.qiskit_cost_hamiltonian
    241 self.qiskit_cost_hamil_sq = self.qiskit_cost_hamil**2

File ~/openqaoa_github/openqaoa/openqaoa/backends/simulators/qaoa_qiskit_sim.py:317, in QAOAQiskitBackendStatevecSimulator.parametric_qaoa_circuit(self)
    315     # Create Circuit
    316     for each_tuple in decomposition:
--> 317         parametric_circuit = each_tuple[0](*each_tuple[1]).apply_gate(parametric_circuit, 'ibm')
    319 if self.append_state:
    320     parametric_circuit = parametric_circuit.compose(self.append_state)

File ~/openqaoa_github/openqaoa/openqaoa/qaoa_parameters/lowlevelgate.py:30, in LowLevelGate.apply_gate(self, circuit, circuit_library)
     27 def apply_gate(self, circuit, circuit_library: str):
     29     if circuit_library == 'ibm':
---> 30         return self._ibm_gate(circuit)
     31     elif circuit_library == 'pyquil':
     32         return self._pyquil_gate(circuit)

File ~/openqaoa_github/openqaoa/openqaoa/qaoa_parameters/lowlevelgate.py:93, in RX._ibm_gate(self, circuit)
     91 def _ibm_gate(self, circuit: qkQuantumCircuit) -> qkQuantumCircuit:
---> 93     circuit.rx(self.rotation_angle_obj.rotation_angle, self.qubit_1)
     94     return circuit

File ~/.conda/envs/openqaoa_may22/lib/python3.8/site-packages/qiskit/circuit/quantumcircuit.py:2988, in QuantumCircuit.rx(self, theta, qubit, label)
   2974 """Apply :class:`~qiskit.circuit.library.RXGate`.
   2975 
   2976 For the full matrix form of this gate, see the underlying gate documentation.
   (...)
   2984     A handle to the instructions created.
   2985 """
   2986 from .library.standard_gates.rx import RXGate
-> 2988 return self.append(RXGate(theta, label=label), [qubit], [])

File ~/.conda/envs/openqaoa_may22/lib/python3.8/site-packages/qiskit/circuit/quantumcircuit.py:1204, in QuantumCircuit.append(self, instruction, qargs, cargs)
   1201     if is_parameter:
   1202         instruction = copy.deepcopy(instruction)
-> 1204 expanded_qargs = [self.qbit_argument_conversion(qarg) for qarg in qargs or []]
   1205 expanded_cargs = [self.cbit_argument_conversion(carg) for carg in cargs or []]
   1207 if self._control_flow_scopes:

File ~/.conda/envs/openqaoa_may22/lib/python3.8/site-packages/qiskit/circuit/quantumcircuit.py:1204, in <listcomp>(.0)
   1201     if is_parameter:
   1202         instruction = copy.deepcopy(instruction)
-> 1204 expanded_qargs = [self.qbit_argument_conversion(qarg) for qarg in qargs or []]
   1205 expanded_cargs = [self.cbit_argument_conversion(carg) for carg in cargs or []]
   1207 if self._control_flow_scopes:

File ~/.conda/envs/openqaoa_may22/lib/python3.8/site-packages/qiskit/circuit/quantumcircuit.py:1102, in QuantumCircuit.qbit_argument_conversion(self, qubit_representation)
   1091 def qbit_argument_conversion(self, qubit_representation: QubitSpecifier) -> List[Qubit]:
   1092     """
   1093     Converts several qubit representations (such as indexes, range, etc.)
   1094     into a list of qubits.
   (...)
   1100         List(Qubit): the resolved instances of the qubits.
   1101     """
-> 1102     return _bit_argument_conversion(
   1103         qubit_representation, self.qubits, self._qubit_indices, Qubit
   1104     )

File ~/.conda/envs/openqaoa_may22/lib/python3.8/site-packages/qiskit/circuit/quantumcircuit.py:4816, in _bit_argument_conversion(specifier, bit_sequence, bit_set, type_)
   4814         return [bit_sequence[specifier]]
   4815     except IndexError as ex:
-> 4816         raise CircuitError(
   4817             f"Index {specifier} out of range for size {len(bit_sequence)}."
   4818         ) from ex
   4819 # Slices can't raise IndexError - they just return an empty list.
   4820 if isinstance(specifier, slice):

CircuitError: 'Index 5 out of range for size 5.'

Resulting from the following qaoa_circuit_params (Notice the different number of qubits in the cost hamiltonian and mixer hamiltonian) :

Circuit Parameters:
	p: 1
	register: [0, 1, 2, 3, 4]

Cost Hamiltonian:
	cost_qubits_singles: [PauliOp(Z,(0,)), PauliOp(Z,(4,)), PauliOp(Z,(4,))]
	cost_single_qubit_coeffs: [0.2553358375172401, 0.7451256815312157, 0.19961958936046076]
	cost_qubits_pairs: [PauliOp(ZZ,(0, 1)), PauliOp(ZZ,(0, 4)), PauliOp(ZZ,(2, 3)), PauliOp(ZZ,(2, 4))]
	cost_pair_qubit_coeffs: [0.41784048382311567, 0.26267010544127745, 0.20272558242632943, 0.5514867726991646]

Mixer Hamiltonian:
	mixer_qubits_singles: [PauliOp(X,(0,)), PauliOp(X,(1,)), PauliOp(X,(2,)), PauliOp(X,(3,)), PauliOp(X,(4,)), PauliOp(X,(5,))]
	mixer_single_qubit_coeffs: [-1, -1, -1, -1, -1, -1]
	mixer_qubits_pairs: []
	mixer_pair_qubit_coeffs: []
qaoa_circuit_params

Prevent double authentication while using `openqaoa-azure`

Prerequisites

Before raising this issue, I have already checked that I am:

  • running the latest version
  • made sure that this issue has not already been filed

Describe the bug

Running a QAOA problem using the OpenQAOA workflow as described in this notebook will require web authentication twice before executing the run. For reference, see the attached screenshot.

This happens because DeviceAzure, which is defined in src/openqaoa-azure/openqaoa_azure/backends/devices.py, has a method called check_connection, that is called twice, once from within the workflow and the other time from within the backend object.

To Reproduce

Steps to reproduce the behavior:

  1. Create the Azure device object
  2. Create a qubo for a problem of choice
  3. Initialize the QAOA workflow as q = QAOA()
  4. Call the compile method and pass the QUBO via q.compile(qubo)

Expected behavior

Upon executing the above steps, the web authenticator should only prompt once for device authentication

Screenshots

image

Improve Unit-tests for QPUs

Issue Description

A recent bug in the decomposition methods of some GateMaps raised concern for the quality of QPU tests. The bug was fixed with PR #91, however, we need to update the QPU test suite.

Add result statistics on measurement outcomes in QAOAResult object

Prerequisites

  • It does not lead to duplication.
  • It has not already been requested.

Is your feature request related to a problem? Please describe.

The QAOAResult object stores information regarding the QAOA optimization routine. This result object can be accessed post optimization through the QAOA workflow object via the following steps:

  1. Define the problem qubo
  2. Initialize QAOA workflow object q = QAOA()
  3. Set QAOA properties via setter methods
  4. Compile the object q.compile(qubo)
  5. Run the optimization q.optimize()
  6. Obtain the results of optimization as qaoa_result = q.result

Add a method under the QAOAResult class that computes some statistical quantities for the measurement outcomes.

Describe the solution you'd like

The QAOA object can store measurement outcomes (i.e. counts) from each circuit evaluation in the QAOAResult object.

  • The method sorts the measurement outcomes (a dictionary) in the descending order of counts.
  • It computes the mean and standard deviation for the optimized set of measurement outcomes.
  • The function also optionally computes these quantities for all intermediate measurement outcomes during optimization if the user specifies.
  • The method should raise an error if the user requires statistics on all intermediate measurement outcomes but hasn't specified saving them during optimization.

Additional context

An approach adding statistical tools to understand QAOA results better

Invalid link for setup of IMBQ account

Prerequisites

Before raising this issue, I have already checked that I am:

  • running the latest version
  • made sure that this issue has not already been filed

Describe the bug

When compiling a QAOA circuit without having the IMBQ credentials set up, the link displayed to solve the issue leads to a 404 error on https://quantum-computing.ibm.com/

To Reproduce

Steps to reproduce the behavior:

  1. Create a QAOA object
  2. Attempt to compile via .compile() function
  3. See error

Expected behavior

The link displayed should lead to a valid page.

Screenshots

Screenshot 2023-05-25 at 13 33 36

Serialization of the results: White spaces in result dictionary keys prevent a good serialization

Description

The QAOA Results object has some dictionaries as attributes. These dictionaries use strings with white spaces as keys, see: https://github.com/entropicalabs/openqaoa/blob/main/openqaoa/optimizers/result.py#L69

That is a problem when trying to serialize the results object to a json. For good serialization, those white spaces should be removed. However, this means that older code that uses these keys will not work anymore.

Design enhancement for derivative functions and QFIM

Currently, the methods to calculate the derivative functions and the quantum Fisher information matrix (QFIM) (located in basebackend.py, the methods derivative_function and qfim respectively) accepts a QAOAVariationalBaseParams object and return a callable which accepts an array of parameters and output either the derivatives or QFIM. This is because the derivative/QFIM argument in scipy.minimize.optimize and our custom gradient optimisers expect a callable that takes in an array and outputs a vector/matrix.

Design wise, it might be more intuitive that these methods directly output the corresponding derivative/QFIM, given the QAOAVariationalBaseParams object, since they already contain angles/parameters.

Some possible solutions to be discussed:

  • Have another function that returns the results directly, instead of a callable.
  • Modify the methods to always return the results directly, but at the optimiser level write a wrapper function that generates this callable that can be fed to the optimiser function.

Expose brute force solver through OpenQAOA workflows

Prerequisites

Before raising this feature request, I made sure:

  • It does not lead to duplication.
  • It has not already been requested.

Is your feature request related to a problem? Please describe.

OpenQAOA has a function called ground_state_hamiltonian that takes as input the Cost Hamiltonian corresponding to the QUBO problem and outputs the degenerate solutions (or ground states of the Hamiltonian) along with the lowest energy (i.e. ground state energy). The function is defined in src/openqaoa-core/openqaoa/utilities.py.

Expose this function as a QAOA workflow class method so users can easily access it.

Describe the solution you'd like

  • Implement the method that calls this function from within the QAOA workflow class
  • Make sure to impose an artificial limit on the size of problem (in terms of the number of qubits) to prevent memory overflow.

Ideal workflow

  1. q = QAOA()
  2. q.compile(qubo)
  3. q.solve_brute_force()

Describe alternatives you've considered

The existing way to obtain the brute force solution of a qubo is described as follows:

  1. construct the problem qubo
  2. `from openqaoa.utilities import ground_state_hamiltonian
  3. Construct the hamiltonian object by calling prob_hamiltonian = qubo.hamiltonian
  4. Obtain the solution solution, energy = ground_state_hamiltonian(prob_hamiltonian)

Transform a docplex optimization problem into openQAOA Hamiltonian


name: Docplex converter.
about: Having an optimization problem in Docplex form transforms it into the OpenQAOA Hamiltonian.
title: 'docplex2hamiltonian'
labels: 'feature request'
assignees: @alejomonbar @MaldoAlberto


Prerequisites

Before raising this feature request, I have made sure:

  • It does not lead to duplication.
  • It has not already been requested.

Is your feature request related to a problem? Please describe.

Implementing optimization problems using openQAOA is restricted to certain problems with a predefined structure ( NumberPartition, TSP, Knapsack, etc). For example, if we want to modify the Knapsack problem with a Heuristic equation, the implemented Knapsack problem would not help me to solve my problem and I must create my own Hamiltonian of this problem. Docplex a python based library used to solve optimization problems can be used to codify the optimization problem and then translate it directly into its OpenQAOA Hamiltonian.

It will be something like:

from docplex.mp.model import Model
from openqaoa.utilities import X_mixer_hamiltonian
from openqaoa.problems.helper_functions import docplex2hamiltonian #The function we want to implement

mdl = Model(name="MyOptimizationProblem") # Docplex model

z = mdl.binary_var_list(10, name="Z") #My binary optimization variables


objective = mdl.sum(z) - 2 * z[0]  + z[3] * z[4]  # Cost function

mdl.minimize(objective) # Adding the objective function to the model 

cost_hamil = docplex2hamiltonian(mdl) # The function we want to implement

mixer_hamil = X_mixer_hamiltonian(num_assets)

circuit_params = QAOACircuitParams(cost_hamil, mixer_hamil, p=1)


variate_params = create_qaoa_variational_params(circuit_params, 'standard', 'ramp')
backend_obj_qiskit = get_qaoa_backend(circuit_params, 'qiskit_shot_simulator', n_shots=10000)
backend_obj_qiskit.expectation_w_uncertainty(variate_params)
backend_obj_qiskit.expectation(variate_params)
optimizer_dict = {'method': 'cobyla', 'maxiter': 10}
variate_params_qiskit = variate_params
optimizer_obj_qiskit = get_optimizer(backend_obj_qiskit, variate_params_qiskit, optimizer_dict)
optimizer_obj_qiskit()
optimizer_obj_qiskit.results_information()

Describe the solution you'd like

Create a class function that translates an optimization problem into its Hamiltonian representation.

Describe alternatives you've considered

we think Numba can be used instead of Docplex. But, we should start first with Docplex.

Additional context

Screen Shot 2022-06-17 at 8 07 02 AM

Screen Shot 2022-06-17 at 8 06 52 AM

Screen Shot 2022-06-17 at 7 30 50 AM

Error: "'openqaoa' is not a package" when trying to run basic testing

Prerequisites

Before raising this issue, I have already checked that I am:

  • [x ] running the latest version
  • [x ] made sure that this issue has not already been filed

Describe the bug

Hello, I am trying to do some basic testing of the openqaoa module. In particular, I am simply going through the initial walkthrough for MinimumVertexCover as described in the docs. I began by successfully cloning the OpenQAOA github file, and then using pip install . to sucessfully install all dependencies. I verified that all dependencies were succesfully installed, including openqaoa.

However, when I run my test file in Python, I get the error:

ModuleNotFoundError: No module named 'openqaoa.utilities'; 'openqaoa' is not a package

and the execution fails.

To Reproduce

Steps to reproduce the behavior:

  1. clone the openqaoa github file
  2. type pip install . or just manually install each required dependency
  3. in the base of the cloned folder, create a file called test.py and paste the following code into it:
import networkx
from openqaoa.problems import MinimumVertexCover

g = networkx.circulant_graph(6, [1])
vc = MinimumVertexCover(g, field=1.0, penalty=10)
qubo_problem = vc.qubo
  1. type python test.py to run the file

Expected behavior

I expect the file to run successfully, not to get the above error.

Additional context

I also tried installing just the openqaoa dependency in a new folder and then running the file there (without cloning the original file), but got the same error.

Knapsack random generation error

When running simple code to generate a random knapsack problem, I encounter the following error. I do not know where this is coming from or if I am doing something wrong.

Code:

q = QAOA()
problem = Knapsack.random_instance(n_items=9, quantum=True).get_pubo_problem()
q.compile(problem)
q.optimize()

Error:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Input In [71], in <cell line: 13>()
     49 q = QAOA()
     50 problem = Knapsack.random_instance(n_items=9, quantum=True).get_pubo_problem()
---> 51 q.compile(problem)
     52 q.optimize()
     53 ks[-1].append(q.results_information["best cost"][0])

File c:\users\owenl\documents\openqaoa-main\openqaoa\workflows\optimizer.py:345, in QAOA.compile(self, problem, verbose)
    324 """
    325 Initialise the trainable parameters for QAOA according to the specified
    326 strategies and by passing the problem statement
   (...)
    339     Set True to have a summary of QAOA to displayed after compilation
    340 """
    341 self.mixer_hamil = get_mixer_hamiltonian(n_qubits=problem.n,
    342                                          qubit_connectivity=self.circuit_properties.mixer_qubit_connectivity,
    343                                          coeffs=self.circuit_properties.mixer_coeffs)
--> 345 self.cost_hamil = Hamiltonian.classical_hamiltonian(
    346     terms=problem.terms, coeffs=problem.weights, constant=problem.constant)
    348 self.circuit_params = QAOACircuitParams(
    349     self.cost_hamil, self.mixer_hamil, p=self.circuit_properties.p)
    350 self.variate_params = create_qaoa_variational_params(qaoa_circuit_params=self.circuit_params, params_type=self.circuit_properties.param_type,
    351                                                      init_type=self.circuit_properties.init_type, variational_params_dict=self.circuit_properties.variational_params_dict,
    352                                                      linear_ramp_time=self.circuit_properties.linear_ramp_time, q=self.circuit_properties.q, seed=self.circuit_properties.seed)

File c:\users\owenl\documents\openqaoa-main\openqaoa\qaoa_parameters\operators.py:610, in Hamiltonian.classical_hamiltonian(cls, terms, coeffs, constant)
    608         pauli_ops.append(PauliOp('Z', term))
    609     else:
--> 610         raise ValueError(
    611             "Hamiltonian only supports Linear and Quadratic terms")
    613 return cls(pauli_ops, coeffs, constant)

ValueError: Hamiltonian only supports Linear and Quadratic terms

The logger is not working correctly for all of the BaseBackendStatevector


name: Bug report
about: Create a report to help us improve
title: The logger is not working correctly for all of the BaseBackendStatevector
labels: bug
assignees: @vishal-ph, @shahidee44

Prerequisites

Before raising this issue, I have already checked that I am:

  • running the latest version
  • made sure that this issue has not already been filed

Describe the bug

Using local statevector/wavefunction simulators results in optimizer.log.probability.best being empty.

The reason is probably a mismatch between the attributes probabilities and counts in the logger

To Reproduce

from openqaoa.qaoa_parameters import PauliOp, Hamiltonian, QAOACircuitParams, create_qaoa_variational_params
from openqaoa.utilities import X_mixer_hamiltonian
from openqaoa.devices import DeviceQiskit, create_device
from openqaoa.backends.qaoa_backend import get_qaoa_backend
from openqaoa.optimizers import get_optimizer
from openqaoa.problems.problem import MinimumVertexCover
import networkx as nx

g = nx.circulant_graph(4, [1])
vc = MinimumVertexCover(g, field =1.0, penalty=10).get_pubo_problem()

mixer_hamil = X_mixer_hamiltonian(n_qubits=3)
circuit_params = QAOACircuitParams(vc.hamiltonian, mixer_hamil, p=2)
variate_params = create_qaoa_variational_params(circuit_params,'standard','ramp')

qiskit_sv_sim = create_device('local','qiskit.statevector_simulator')
backend_qiskit_sv = get_qaoa_backend(circuit_params, qiskit_sv_sim)  

optimizer_dict = {'method': 'cobyla', 'maxiter': 10}
opti_sv = get_optimizer(backend_qiskit_sv, variate_params, optimizer_dict)

opti_sv()

Expected behaviour

The probability attribute should be populated! Note that the optimisation does happen, so the bug is at the logger's level

Screenshots

image

Additional context

Probably a solution is to remove the difference between probability and count, and use the same attribute for both cases!

Circular Import when trying to import from openqaoa.optimizers

Code: from openqaoa.optimizers import *
Error Message:

---------------------------------------------------------------------------
ImportError                               Traceback (most recent call last)
<ipython-input-1-901a46c0d7dd> in <module>
----> 1 from openqaoa.optimizers import *

~/Test/openqaoa/openqaoa/optimizers/__init__.py in <module>
     20 """
     21 
---> 22 from .training_vqa import *
     23 from .qaoa_optimizer import *

~/Test/openqaoa/openqaoa/optimizers/training_vqa.py in <module>
     24 from scipy.optimize import LinearConstraint, NonlinearConstraint, Bounds
     25 
---> 26 from ..basebackend import VQABaseBackend
     27 from ..qaoa_parameters.baseparams import QAOAVariationalBaseParams
     28 from . import optimization_methods as om

~/Test/openqaoa/openqaoa/basebackend.py in <module>
     29 from copy import deepcopy
     30 
---> 31 from .backends.qpus.qpu_auth import AccessObjectBase
     32 from .qaoa_parameters.pauligate import PauliGate, TwoPauliGate
     33 from .qaoa_parameters.baseparams import QAOACircuitParams, QAOAVariationalBaseParams

~/Test/openqaoa/openqaoa/backends/__init__.py in <module>
     30 from .qpus.qpu_auth import *
     31 
---> 32 from .qpus.qaoa_qiskit_qpu import *
     33 from .qpus.qaoa_pyquil_qpu import *
     34 

~/Test/openqaoa/openqaoa/backends/qpus/qaoa_qiskit_qpu.py in <module>
     22 
     23 from .qpu_auth import AccessObjectQiskit
---> 24 from ...basebackend import QAOABaseBackendShotBased, QAOABaseBackendCloud, QAOABaseBackendParametric
     25 from ...qaoa_parameters.baseparams import QAOACircuitParams, QAOAVariationalBaseParams
     26 from ...utilities import flip_counts

ImportError: cannot import name 'QAOABaseBackendShotBased' from partially initialized module 'openqaoa.basebackend' (most likely due to a circular import) (/home/shahidee/Test/openqaoa/openqaoa/basebackend.py)

The issue is partially resolved/the reason why we do not observe the error is when we call the import.
from openqaoa.backends.qpus.qpu_auth import *
The circular import error is fixed.

Azure backend doesn't catch http response errors

Prerequisites

Before raising this issue, I have already checked that I am:

  • running the latest version
  • made sure that this issue has not already been filed

Describe the bug

A clear and concise description of what the bug is.

To Reproduce

Using an azure device (e.g. device = create_device(location='azure', name='rigetti.sim.qvm', resource_id=resource_id, az_location=az_location) ) lead to the following HttpResponseError

image

Since the exception was not caught gracefully by OQ the result of the run was lost.

Expected behaviour

OQ should always exit gracefully any error that happens during the hybrid classical-quantum loop. This is fundamental to avoid loosing QPU data.

Renaming certain files and classes

Prerequisites

Before raising this feature request, I have made sure:

  • It does not lead to duplication.
  • It has not already been requested.

Is your feature request related to a problem? Please describe.

Issues to be resolved:

  1. src/openqaoa-core/optimizers/qaoa_optimizer.py - (Renaming to something like vqa_optimizer.py since the functions in this module are not specific to QAOA.)
  2. src/openqaoa-core/optimizers/training_vqa.py - (training is more meant for ML. optimization_vqa is more accurate. optimization_loop is also proposed as a module name.)
  3. src/openqaoa-core/algorithms/baseworkflow.py - (Find a new name for the Workflow ABC. Workflow is a legacy name.)
  4. The object WorkflowProperties in src/openqaoa-core/algorithms/baseworkflow.py, is labelled as parameters in the asdict method of the workflow objects. A proposal was made to change the entry that contains information from this class from ['data']['input_parameters'] to ['data']['input_properties'].

Describe the solution you'd like

To discuss on what is a better naming scheme for the following files.

Additional context

Issue raised to resolve conversations in ongoing PR #170 that needs to be merged

pip install openqaoa throws some qiskit error

When running in Colab, installing openqaoa with 'pip install openqaoa' and then simply running 'from openqaoa.problems import NumberPartition' throws and error 'ImportError: Missing optional 'qiskit' dependencies. To install run: pip install azure-quantum[qiskit]'

However, after installing the error persists.

Screenshots

Screenshot 2023-12-04 at 23 17 46

Additional context

Current fix is installing openqaoa-core only.

Optimize function crashes silently

The optimize function in training_vqa (see

def optimize(self):
) doesn't return the errors correctly when the minimize() function crashes.

To reproduce the error,

  1. set params to None in
  2. run the following script:
import networkx as nx
from openqaoa.problems.problem import MaximumCut
from openqaoa.workflows.optimizer import QAOA

g = nx.generators.fast_gnp_random_graph(n=6,p=0.6)
maxcut_prob = MaximumCut(g)
maxcut_qubo = maxcut_prob.get_qubo_problem()

q = QAOA()
q.compile(maxcut_qubo) 
q.optimize()

optimize() fails as

capi_return is NULL
Call-back cb_calcfc_in__cobyla__user__routines failed.

But the optimisation doesn't crash, and the result dictionary is still being created (see the finally clause at the end of optimize)

Propose Solution

We need to change the logic of optimize() so to:

  • handle the connection error
  • throwing a proper error if something goes wrong within the optimisation

Integrate ZNE from Mitiq into OpenQAOA

Prerequisites

Before raising this feature request, I have made sure:

  • It does not lead to duplication.
  • It has not already been requested.

Is your feature request related to a problem? Please describe.

Proposal a method into the object QAOA to indicate the parameters necessaries for Mitiq and try to mitigate the error for the problem.

Describe the solution you'd like

Add mitiq on OpenQAOA using ZNE mitigation error and implement in the QAOA class.

Describe alternatives you've considered

A clear and concise description of any alternative solutions or features you've considered.

Additional context

Add any other context or screenshots about the feature request here.

QAOA().compile appears to 'lock-in' values after first run?

Prerequisites

Before raising this issue, I have already checked that I am:

  • [x ] running the latest version
  • [x ] made sure that this issue has not already been filed

Describe the bug

Hello, when performing testing using the QAOA package, I find that the initial run of the program will seem to execute correctly. However, if subsequent runs are executed, the program will re-execute as if no variables had changed.

To Reproduce

In a new folder, install the necessary dependencies, and then execute this code:

import numpy as np
import networkx as nx
from openqaoa.utilities import plot_graph

# Generating a graph of 100 nodes
n = 100  # Number of nodes in graph

G = nx.generators.fast_gnp_random_graph(n, p=0.4, seed=42)
plot_graph(G)
from openqaoa.problems import MaximumCut

maxcut_prob = MaximumCut(G)
maxcut_qubo = maxcut_prob.qubo

print(maxcut_qubo.hamiltonian.expression)
maxcut_qubo.asdict()
print('this is maxcut_qubo', maxcut_qubo.asdict())

plot_graph(G)

from openqaoa import QAOA, create_device  

q = QAOA()
analytical_device = create_device(location='local', name='analytical_simulator')
q.set_device(analytical_device)

q.compile(maxcut_qubo)
q.optimize()

print('this is answer',q.result.most_probable_states)

You will get an error saying 'ValueError: Maximum allowed dimension exceeded'

Then make a slight modification to the code, setting n to 6.

The code will run as if n still equals to 100, and you will get the same error.

Expected behavior

The code should run as id n=6 on the second try.

Additional context

Please note that I tested this on two separate PC laptops, in both virtual and non-virtual environments, and got the same error each time. Also, there is a follow-up question as to why the analytical machine cannot solve the initial max-cut problem at 100 nodes...?

Thank you,

Error Catching for RQAOA Workflow

Prerequisites

Before raising this issue, I have already checked that I am:

  • running the latest version
  • made sure that this issue has not already been filed

Describe the bug

The RQAOA Workflow is missing some form of error catching in the case where a QAOA run is incomplete/crashes midway.

To Reproduce

Link to file
Line 385

Expected behavior

If an error occurred during one of the QAOA runs and the error is caught, but the run is incomplete. The RQAOA should be terminated and whatever information that was obtained should be available in the final workflow object in the result attribute.

[Feature Request] Custom Mixers

The ability to easily use custom mixer's would be nice, currently I see only x and xy supported, but there is a work in exploring more options. The input format could either be a qiskit circuit (depending on internal conversions) or some string based representation, but I think there would be value in this.

Unintended behaviour/error-catching bug when using workflows with IBM backend

Prerequisites

Before raising this issue, I have already checked that I am:

  • running the latest version
  • made sure that this issue has not already been filed

Describe the bug

Using workflows, if the QUBO problem to be compiled contains more qubits than the device chosen, running q.optimise() will just pass, without returning an error message.

To Reproduce

Steps to reproduce the behavior:

  1. Choose an IBM device (eg: ibm_nairobi with 6 qubits)
  2. Create a QUBO problem requiring more qubits than the device (eg : a 7-qubit MaxCut problem)
  3. Run OQ as usual, and finally run q.optimise()
  4. Cell passes, but it should have failed.

Expected behavior

An error message should be thrown to inform the user that the problem and device are incompatible.

Changing the way gates are applied by the `GateApplicator` objects.

I don't think we need 4 different methods (apply_1q_rotation_gate, apply_2q_rotation_gate, apply_1q_fixed_gate, apply_1q_fixed_gate) I think they all do exactly the same.

I believe we could change all of this:

    @staticmethod
    def apply_1q_rotation_gate(
        vectorized_gate: Callable,
        qubit_1: int,
        rotation_object: RotationAngle
    ):
        vectorized_gate(
            qubit_1,
            rotation_object.rotation_angle
        )

    @staticmethod
    def apply_2q_rotation_gate(
        vectorized_gate: Callable,
        qubit_1: int,
        qubit_2: int,
        rotation_object: RotationAngle
    ):
        vectorized_gate(
            qubit_1,
            qubit_2,
            rotation_object.rotation_angle
        )

    @staticmethod
    def apply_1q_fixed_gate(
        vectorized_gate: Callable,
        qubit_1: int
    ):
        vectorized_gate(
            qubit_1
        )

    @staticmethod
    def apply_2q_fixed_gate(
        vectorized_gate: Callable,
        qubit_1: int,
        qubit_2: int
    ):
        vectorized_gate(
            qubit_1,
            qubit_2
        )

    def apply_gate(self, gate: gates_core.Gate, *args):
        selected_vector_gate = self.gate_selector(gate, args[-1])
        # Remove argument from tuple
        args=args[:-1]
        if gate.n_qubits == 1:
            if hasattr(gate, 'rotation_object'):
                # *args must be of the following format -- (qubit_1,rotation_object)
                self.apply_1q_rotation_gate(selected_vector_gate, *args)
            else:
                # *args must be of the following format -- (qubit_1)
                self.apply_1q_fixed_gate(selected_vector_gate, *args)
        elif gate.n_qubits == 2:
            if hasattr(gate, 'rotation_object'):
                # *args must be of the following format -- (qubit_1,qubit_2,rotation_object)
                self.apply_2q_rotation_gate(selected_vector_gate, *args)
            else:
                # *args must be of the following format -- (qubit_1,qubit_2)
                self.apply_2q_fixed_gate(selected_vector_gate, *args)
        else:
            raise ValueError("Error applying the requested gate. Please check in the input")

for something much more compact like:

    def apply_gate(self, gate: gates_core.Gate, *args):

        if not gate.n_qubits in [1, 2]:
            raise ValueError("Error applying the requested gate. Please check in the input")
        
        selected_vector_gate = self.gate_selector(gate, args[-1])

        args_ = args[:-1]
        for i in range(len(args_)):
            if isinstance(args_[i], RotationAngle):
                args_[i] = args_[i].rotation_angle
                
        selected_vector_gate(*args_)

Originally posted by @raulconchello in #193 (comment)

Improve test_problems.py

Issue Description

  • The file is too long and contains tests for all problem classes. We need to break it down as separate files testing each problem class for ease of maintainability.
  • The tests contain some unused code and non consistent coding standards that need to be fixed.

Describe the solution you'd like:

  • Break down the file src/openqaoa-core/tests/test_problems.py into different files containing relevant tests for each problem class defined in OpenQAOA
  • OpenQAOA problem classes are defined in src/openqaoa-core/openqaoa_core/problems/.

Create a new folder in test_problems and create scripts consisting of specific tests corresponding to that problem class.
For e.g. create test_maximumcut.py and put all tests corresponding to maximum_cut.py in this file

NOTE: Please branch out of openqaoa/dev and make the PR to openqaoa/dev

"ImportError: cannot import name 'MaximumCut' from 'openqaoa.problems.problem'"

Prerequisites

Before raising this issue, I have already checked that I am:

  • [ x] running the latest version
  • [ x] made sure that this issue has not already been filed

Describe the bug

Hello!

I am trying to use openqaoa to solve a maximum-cut -type question. Based on the tutorial here: (https://openqaoa.entropicalabs.com/problems/maximum-cut/#maxcut-in-openqaoa), this is the sample code given to solve a small Max Cut question:

import numpy as np
import networkx as nx
#from openqaoa.utilities import plot_graph


# Generating a graph of nodes

G = nx.generators.fast_gnp_random_graph(n=6, p=0.6, seed=42)

from openqaoa.utilities import plot_graph
plot_graph(G)

from openqaoa.problems.problem import MaximumCut

maxcut_prob = MaximumCut(G)
maxcut_qubo = maxcut_prob.qubo

maxcut_qubo.hamiltonian.expression

However, after installing all dependencies and running the code, I get the following error:

image

To Reproduce

Steps to reproduce the behavior:

  1. Create an empty folder
  2. Place the above code into a python file
  3. Install necessary dependencies, especially openqaoa
  4. Run the file

Expected behavior

Metadata/ solution should be produced, not the error above.

Generating random problems potential error

When trying to generate a random problem (e.g. TSP.random_instance(n_cities=[10])) I get the following error. I think it is because the check_kwargs function returns a tuple that is then directly fed into numpy (which doesn't like the tuple). However, I may be using the function wrong, if that is the case just let me know.

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Input In [9], in <cell line: 1>()
----> 1 i = TSP.random_instance(n_cities=[10])

File openqaoa-main\openqaoa\problems\problem.py:237, in TSP.random_instance(**kwargs)
    234 n_cities = check_kwargs(['n_cities'], [None], **kwargs)
    236 box_size = np.sqrt(n_cities)
--> 237 coordinates = box_size * np.random.rand(n_cities, 2)
    238 return TSP(coordinates, n_cities)

File mtrand.pyx:1182, in numpy.random.mtrand.RandomState.rand()

File mtrand.pyx:425, in numpy.random.mtrand.RandomState.random_sample()

File _common.pyx:292, in numpy.random._common.double_fill()

TypeError: 'tuple' object cannot be interpreted as an integer

output of `measurement_outcomes` should be serializable

Prerequisites

Before raising this issue, I have already checked that I am:

  • running the latest version
  • made sure that this issue has not already been filed

Describe the bug

Running a QAOA computation on a QPU and attempting to dump the results fails because some QPUs return their measurement_outcome probabilities as a numpy.float, which is not python serializable. This issue may also happen for statevector simulators, where the measurement_outcomes are wavefunctions which are complex arrays.

To Reproduce

Steps to reproduce the behavior:

  • Run a QAOA computation on a QPU or a statevector simulator
  • Attempt to dump the QAOA results in a JSON file

Expected behavior

OpenQAOA should convert all non-serializable outputs to native python types, so that QPU results including measurement outcomes can be dumped into a JSON

Warning if `0` is passed in `numbers_list` in `NumberPartition` problem

Prerequisites

Before raising this issue, I have already checked that I am:

  • running the latest version
  • made sure that this issue has not already been filed

Describe the bug

Upon creating an instance of the NumberPartition problem with a 0 entry in the list, the problem is created with redundant qubit and terms. These terms then manifest as extra cost gates with angle=0.

To Reproduce

Steps to reproduce the behavior:

from openqaoa.problems import NumberPartition
np = NumberPartition([0,2,3,5,8])
np_qubo = np.qubo()
np_qubo.hamiltonian.expression

Expected behavior

The problem class should catch 0 in the list and raise a warning while removing the zero from the list, and create a problem with the remaining qubits.

Screenshots

If applicable, add screenshots to help explain your problem.

Additional context

Add any other context about the problem here.

Resolve IBMQ deprecation warning for Qiskit

Prerequisites

Before raising this issue, I have already checked that I am:

  • running the latest version
  • made sure that this issue has not already been filed

Describe the bug

image

To Reproduce

The IBMQ import in qiskit is going to be deprecated.

Additional context

Need to change the way the module is imported. Need to check if setup needs to be changed to accomandate possible module that might not be installed with the package.

Implement `as_matrix` method for the `Hamiltonian` class

Prerequisites

Before raising this feature request, I made sure:

  • It does not lead to duplication.
  • It has not already been requested.

Is your feature request related to a problem? Please describe.

The class Hamiltonian in OpenQAOA defined in src/openqaoa-src/openqaoa/qaoa_components/ansatz_constructor/operators.py is responsible for constructing the Cost and Mixer Hamiltonians in QAOA. It fundamentally describes the Hamiltonian object via list of PauliOps defined on a set of qubits and a corresponding list of their coefficients. Implicitly, the definition of the Hamiltonian is then assumed as follows: $$H = \sum_i \alpha_{i} P_i + \sum_{ij} J_{ij} P_{ij},$$ where $\ P_i, P_{ij}$ are one-qubit and two-qubit PauliOps respectively.

Implement a method in this class that returns the matrix representation of the Hamiltonian object. This will be a $2^n x 2^n$ dimensional sum over all Pauli entries as shown above.

Describe the solution you'd like

  • Implement the method
  • Use numpy sparse matrix where relevant
  • Implement checks preventing users from creating matrices beyond 20 qubits to prevent memory overflow
  • Bonus task: If the Hamiltonian can be expressed as a sparse matrix, shift the qubit restriction to a higher number depending on the sparsity of the matrix
class Hamiltonian:
    def as_matrix(self):
        "Implements a numpy array (sparse where relevant) representation
         of the Hamiltonian object."
        #TODO
        return mat

Get counts is broken for the vectorized backend

Currently, get_counts in basebackend.py assumes that the samples should be converted from binary to integers. However, the vectorised backend is already returning the samples in binary.

unique_nums, frequency = np.unique(samples, return_counts=True)
unique_shots = [np.binary_repr(num, self.n_qubits)[
    ::-1] for num in unique_nums]

However, it seems that unique_nums is currently already a list of binary values.

I get a TypeError: 'numpy.str_' object cannot be interpreted as an integer

To reproduce the error run

from openqaoa.qaoa_parameters import create_qaoa_variational_params, QAOACircuitParams, PauliOp, Hamiltonian
from openqaoa.utilities import X_mixer_hamiltonian
from openqaoa.backends.qaoa_backend import get_qaoa_backend

terms = [(1,2),(2,3),(0,3),(4,0),(1,),(3,)]
coeffs = [1,2,3,4,3,5]
cost_hamil = Hamiltonian.classical_hamiltonian(terms,coeffs,0)
mixer_hamil = X_mixer_hamiltonian(n_qubits=5)
qaoa_circuit_params = QAOACircuitParams(cost_hamil,mixer_hamil,p=1)
params1 = create_qaoa_variational_params(qaoa_circuit_params,'fourier','rand',q=1)

backend_obj_vect = get_qaoa_backend(qaoa_circuit_params, 'vectorized')

Note that currently lines 607 and 608 have already been commented out.
See:

# unique_shots = [np.binary_repr(num, self.n_qubits)[

Full traceback :

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Input In [8], in <cell line: 1>()
----> 1 backend_obj_vect.get_counts(params1, n_shots=100)

File ~/openqaoa/openqaoa-temporary/openqaoa/basebackend.py:608, in QAOABaseBackendStatevector.get_counts(self, params, n_shots)
    606 unique_nums, frequency = np.unique(samples, return_counts=True)
    607 print(unique_nums, frequency )
--> 608 unique_shots = [np.binary_repr(num, self.n_qubits)[
    609     ::-1] for num in unique_nums]
    610 counts = dict(zip(unique_nums, frequency))
    612 return counts

File ~/openqaoa/openqaoa-temporary/openqaoa/basebackend.py:608, in <listcomp>(.0)
    606 unique_nums, frequency = np.unique(samples, return_counts=True)
    607 print(unique_nums, frequency )
--> 608 unique_shots = [np.binary_repr(num, self.n_qubits)[
    609     ::-1] for num in unique_nums]
    610 counts = dict(zip(unique_nums, frequency))
    612 return counts

File ~/.conda/envs/openqaoa/lib/python3.8/site-packages/numpy/core/numeric.py:2021, in binary_repr(num, width)
   2014         warnings.warn(
   2015             "Insufficient bit width provided. This behavior "
   2016             "will raise an error in the future.", DeprecationWarning,
   2017             stacklevel=3)
   2019 # Ensure that num is a Python integer to avoid overflow or unwanted
   2020 # casts to floating point.
-> 2021 num = operator.index(num)
   2023 if num == 0:
   2024     return '0' * (width or 1)

TypeError: 'numpy.str_' object cannot be interpreted as an integer

cc @shahidee44 @shaohenc

Improve QPU selection in QPU tests

Prerequisites

Before raising this issue, I have already checked that I am:

  • running the latest version
  • made sure that this issue has not already been filed

Describe the bug

The name of the QPU used for the unittest is hardcoded. To change to automated device name selection.
(https://github.com/entropicalabs/openqaoa/blob/main/tests/test_qpu_qiskit.py#L504)

Expected behavior

In the scenario where ibmq_perth gets decommissioned, the code will not work. Also this code might not work if the device is not accepting jobs. (Although technically the Device Object should already reject this device if it isn't Online, even before the Job is sent.)

type object 'VRP' has no attribute 'from_distance_matrix'

Description

I've been exploring the openqaoa package for solving vehicle routing problems (VRP) and encountered an issue when trying to use the from_distance_matrix method with the VRP class. I have run the code using colab.

Steps to Reproduce

  1. Clone the repository and checkout the dev branch:

    !git clone https://github.com/entropicalabs/openqaoa 
    
    cd openqaoa 
    
    !git checkout dev
    
    !pip install .
    
  2. Run the following Python code:

    from openqaoa.problems import VRP
    distance_matrix = [ [0, 2, 5, 10, 9, 9], [2, 0, 17, 6, 8, 14], [5, 17, 0, 10, 4, 7], [10, 6, 10, 0, 7, 11],  [9, 8, 4, 7, 0, 16], [9, 14, 7, 11, 16, 0]]
    
    vrp = VRP.from_distance_matrix(matrix=distance_matrix, n_vehicles=2)
    

Expected Behavior

I expected to create a VRP instance using the from_distance_matrix method.

Actual Behavior

I encountered the following error:

AttributeError: type object 'VRP' has no attribute 'from_distance_matrix'

Additional Information

I noticed a couple of warnings regarding missing modules (azure and qiskit), but I'm not sure if they are related to this issue.

Any assistance or guidance would be greatly appreciated. Thanks!

Method to get exact solution?

Is there a built in way to get the actual/exact/true solution to a given problem? Obviously it doesn't scale, but I would like to evaluate how well the QAOA is performing.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.