Using Qiskit Aqua for stableset problems

This Qiskit Aqua Optimization notebook demonstrates how to use the VQE algorithm to compute the maximum stable set of a given graph.

The problem is defined as follows. Given a graph $G = (V,E)$, we want to compute $S \subseteq V$ such that there do not exist $i, j \in S : (i, j) \in E$, and $|S|$ is maximized. In other words, we are looking for a maximum cardinality set of mutually non-adjacent vertices.

The graph provided as an input is used first to generate an Ising Hamiltonian, which is then passed as an input to VQE. As a reference, this notebook also computes the maximum stable set using the Exact Eigensolver classical algorithm and the solver embedded in the commercial IBM CPLEX product (if it is available in the system and the user has followed the necessary configuration steps in order for Qiskit Aqua to find it). Please refer to the Qiskit Aqua Optimization documentation for installation and configuration details for CPLEX.


In [1]:
from qiskit_aqua import Operator, run_algorithm, get_algorithm_instance
from qiskit_aqua.input import get_input_instance
from qiskit_aqua.translators.ising import stableset
import numpy as np

Here an Operator instance is created for our Hamiltonian. In this case the Paulis are from an Ising Hamiltonian of the maximum stable set problem (expressed in minimization form). We load a small instance of the maximum stable set problem.


In [2]:
w = stableset.parse_gset_format('sample.maxcut')
qubitOp, offset = stableset.get_stableset_qubitops(w)
algo_input = get_input_instance('EnergyInput')
algo_input.qubit_op = qubitOp

We also offer a function to generate a random graph as a input.


In [3]:
if True:
    np.random.seed(8123179)
    w = stableset.random_graph(5, edge_prob=0.5)
    qubitOp, offset = stableset.get_stableset_qubitops(w)
    algo_input.qubit_op = qubitOp
print(w)


[[0. 1. 1. 1. 0.]
 [1. 0. 0. 0. 1.]
 [1. 0. 0. 1. 1.]
 [1. 0. 1. 0. 0.]
 [0. 1. 1. 0. 0.]]

Here we test for the presence of algorithms we want to use in this notebook. If Aqua is installed correctly ExactEigensolver and VQE will always be found. CPLEX.Ising is dependent on IBM CPLEX being installed (see introduction above). CPLEX is not required but if installed then this notebook will demonstrate the CPLEX.Ising algorithm , that uses CPLEX, to compute stable set as well.


In [4]:
to_be_tested_algos = ['ExactEigensolver', 'CPLEX.Ising', 'VQE']
operational_algos = []
for algo in to_be_tested_algos:
    try:
        get_algorithm_instance(algo)
        operational_algos.append(algo)
    except:
        print("{} is unavailable and will be skipped.".format(algo))
print(operational_algos)


['ExactEigensolver', 'CPLEX.Ising', 'VQE']

We can now use the Operator without regard to how it was created. First we need to prepare the configuration params to invoke the algorithm. Here we will use the ExactEigensolver first to return the smallest eigenvalue. Backend is not required since this is computed classically not using quantum computation. We then add in the qubitOp Operator in dictionary format. Now the complete params can be passed to the algorithm and run. The result is a dictionary.


In [5]:
if 'ExactEigensolver' not in operational_algos:
    print("ExactEigensolver is not in operational algorithms.")
else:
    algorithm_cfg = {
        'name': 'ExactEigensolver',
    }

    params = {
        'problem': {'name': 'ising'},
        'algorithm': algorithm_cfg
    }
    result = run_algorithm(params,algo_input)

    x = stableset.sample_most_likely(result['eigvecs'][0])
    print('energy:', result['energy'])
    print('stable set objective:', result['energy'] + offset)
    print('solution:', stableset.get_graph_solution(x))
    print('solution objective and feasibility:', stableset.stableset_value(x, w))


energy: -5.5
stable set objective: -2.0
solution: [0. 1. 1. 0. 0.]
solution objective and feasibility: (2.0, True)

Note: IBM CPLEX is an optional installation addition for Aqua. If installed then the Aqua CPLEX.Ising algorithm will be able to be used. If not, then solving this problem using this particular algorithm will simply be skipped.

We change the configuration parameters to solve it with the CPLEX backend. The CPLEX backend can deal with a particular type of Hamiltonian called Ising Hamiltonian, which consists of only Pauli Z at most second order and can be used for combinatorial optimization problems that can be formulated as quadratic unconstrained binary optimization problems, such as the stable set problem. Note that we may obtain a different solution - but if the objective value is the same as above, the solution will be optimal.


In [6]:
if 'CPLEX.Ising' not in operational_algos:
    print("CPLEX.Ising is not in operational algorithms.")
else:
    algorithm_cfg = {
        'name': 'CPLEX.Ising',
        'display': 0
    }

    params = {
        'problem': {'name': 'ising'},
        'algorithm': algorithm_cfg
    }

    result = run_algorithm(params, algo_input)

    x_dict = result['x_sol']
    print('energy:', result['energy'])
    print('time:', result['eval_time'])
    print('stable set objective:', result['energy'] + offset)
    x = np.array([x_dict[i] for i in sorted(x_dict.keys())])
    print('solution:', stableset.get_graph_solution(x))
    print('solution objective and feasibility:', stableset.stableset_value(x, w))


CPXPARAM_TimeLimit                               600
CPXPARAM_Read_DataCheck                          1
CPXPARAM_Threads                                 1
CPXPARAM_MIP_Tolerances_Integrality              0
CPXPARAM_MIP_Display                             0
energy: -5.5
time: 0.009991101978812367
stable set objective: -2.0
solution: [0 0 0 1 1]
solution objective and feasibility: (2, True)

Now we want VQE and so change it and add its other configuration parameters. VQE also needs and optimizer and variational form. While we can omit them from the dictionary, such that defaults are used, here we specify them explicitly so we can set their parameters as we desire.


In [7]:
if 'VQE' not in operational_algos:
    print("VQE is not in operational algorithms.")
else:
    algorithm_cfg = {
        'name': 'VQE',
        'operator_mode': 'matrix'
    }

    optimizer_cfg = {
        'name': 'L_BFGS_B',
        'maxfun': 2000
    }

    var_form_cfg = {
        'name': 'RYRZ',
        'depth': 3,
        'entanglement': 'linear'
    }

    params = {
        'problem': {'name': 'ising'},
        'algorithm': algorithm_cfg,
        'optimizer': optimizer_cfg,
        'variational_form': var_form_cfg,
        'backend': {'name': 'statevector_simulator'}
    }

    result = run_algorithm(params,algo_input)

    x = stableset.sample_most_likely(result['eigvecs'][0])
    print('energy:', result['energy'])
    print('time:', result['eval_time'])
    print('stable set objective:', result['energy'] + offset)
    print('solution:', stableset.get_graph_solution(x))
    print('solution objective and feasibility:', stableset.stableset_value(x, w))


energy: -5.499999999922404
time: 118.47803401947021
stable set objective: -1.9999999999224043
solution: [0. 0. 0. 0. 0.]
solution objective and feasibility: (0.0, True)

In [ ]: