from collections import OrderedDict
import time

from qiskit import BasicAer
from qiskit.aqua import QuantumInstance, aqua_globals
from qiskit.aqua.algorithms import QAOA
from qiskit.aqua.components.optimizers import COBYLA
from qiskit.optimization.algorithms import MinimumEigenOptimizer, CplexOptimizer
from qiskit.optimization.algorithms.optimization_algorithm import OptimizationResultStatus

from random_lp.lp_random_gen import create_models

DIR = 'TEST_DATA' + "/" + time.strftime("%d_%m_%Y") + "/DENSE/" # 12.03.2021
Q_SEED = 10598 # as used in most issues
aqua_globals.random_seed = Q_SEED
shots = 4096

qps = create_models(DIR)
optimizer = COBYLA() 
cplex = CplexOptimizer()

backend = BasicAer.get_backend('qasm_simulator')
max_qubits = backend.configuration().to_dict()['n_qubits']

quantum_instance = QuantumInstance(backend,
                                   seed_simulator=Q_SEED,
                                   seed_transpiler=Q_SEED,
                                   shots=shots) 
qaoa_mes = QAOA(quantum_instance=quantum_instance, optimizer=optimizer)

results = OrderedDict()
for qp_name, qp in qps.items() :
    print(qp_name)
    print("number of qubits: ", qp.qubo.get_num_vars())
    
    if qp.qubo.get_num_vars() > max_qubits:
        break
        
    qaoa = MinimumEigenOptimizer(qaoa_mes)
    res = qaoa.solve(qp)
    results[qp_name] = res
    if res.status == OptimizationResultStatus.SUCCESS:
        print("success")
        cres  = cplex.solve(qp)
        if res.fval != cres.fval:
            print("\n optimal value QAOA   "+str(res.fval) + "  ,  cplex:"+ str(cres.fval))

# see Class SubstituteVariables in https://qiskit.org/documentation/_modules/qiskit/optimization/problems/quadratic_program.html#QuadraticProgram
# for logger warning constraint A0_leb0 is infeasible due to substitution
# Afterwards a check for feasability of substituted solution is done (line 227 in meo result class) to set OptimizationResultStatus

res_7 = results["test_7"]
print(res_7)

qps["test_7"].is_feasible(res_7.x)

qps["test_8"].is_feasible(results["test_8"].x)

qps["test_8"].to_docplex().prettyprint()

