import time
from typing import Tuple
import dimod
from dwave.system import DWaveSampler, EmbeddingComposite, DWaveCliqueSampler
from qiskit_optimization import QuadraticProgram
from qiskit_optimization.algorithms import CplexOptimizer
from qiskit_optimization.converters import LinearEqualityToPenalty
from utilities.helpers import create_quadratic_programs_from_paths
DIR = 'TEST_DATA' + "/" + '27_04_2021'

# select linear programs to solve
qps = create_quadratic_programs_from_paths(DIR + "/DENSE/")
qp_dense = qps['test_70']

qps = create_quadratic_programs_from_paths(DIR + "/SPARSE/")
qp_sparse = qps['test_100']

# init solvers
cplex = CplexOptimizer()
dwave_dense = DWaveCliqueSampler()
dwave_sparse = EmbeddingComposite(DWaveSampler())
# solve classically
for qp in (qp_dense, qp_sparse):
    print(cplex.solve(qp))

def qp_to_bqm(qp: QuadraticProgram) -> dimod.BQM:
    conv = LinearEqualityToPenalty()
    qubo = conv.convert(qp)
    bqm = dimod.as_bqm(qubo.objective.linear.to_array(), qubo.objective.quadratic.to_array(), dimod.BINARY)
    return bqm

solver_parameters = {'num_reads': 1024, 'annealing_time': 3}

def solve_bqm(sampler: dimod.Sampler, bqm: dimod.BQM):
    sampleset = sampler.sample(bqm, **solver_parameters)
    return sampleset

qubo_dense = qp_to_bqm(qp_dense)
sampleset_dense = solve_bqm(dwave_dense, qubo_dense)
# 44d0d592-9107-4661-a6df-3e65836c1bda
sampleset_dense.to_pandas_dataframe()

def eval_bqm_sampleset(qp: QuadraticProgram, sampleset) -> Tuple[bool, int, float]:
    x = sampleset.record.sample[0]
    feasible = qp.is_feasible(x)
    num_occur = sampleset.record.num_occurrences[0]
    energy = sampleset.record.energy[0]
    return feasible, num_occur, energy

res = eval_bqm_sampleset(qp_dense, sampleset_dense)
res

