import numpy as np
import json
from qiskit import Aer
from qiskit_aqua import run_algorithm
from qiskit_aqua.input import EnergyInput
from qiskit_aqua.translators.ising import exactcover
from qiskit_aqua.algorithms import ExactEigensolver

input_file = 'sample.exactcover'
with open(input_file) as f:
    list_of_subsets = json.load(f)
    print(list_of_subsets)
    qubitOp, offset = exactcover.get_exactcover_qubitops(list_of_subsets)
    algo_input = EnergyInput(qubitOp)

def brute_force():
    # brute-force way: try every possible assignment!
    has_sol = False

    def bitfield(n, L):
        result = np.binary_repr(n, L)
        return [int(digit) for digit in result]  # [2:] to chop off the "0b" part

    L = len(list_of_subsets)
    max = 2**L
    for i in range(max):
        cur = bitfield(i, L)
        cur_v = exactcover.check_solution_satisfiability(cur, list_of_subsets)
        if cur_v:
            has_sol = True
            break
    return has_sol, cur

has_sol, cur = brute_force()
if has_sol:
    print("solution is", cur)
else:
    print("no solution is found")

params = {
    'problem': {'name': 'ising'},
    'algorithm': {'name': 'ExactEigensolver'}
}
result = run_algorithm(params, algo_input)
x = exactcover.sample_most_likely(len(list_of_subsets), result['eigvecs'][0])
ising_sol = exactcover.get_solution(x)
np.testing.assert_array_equal(ising_sol, [0, 1, 1, 0])
if exactcover.check_solution_satisfiability(ising_sol, list_of_subsets):
    print("solution is", ising_sol)
else:
    print("no solution is found")

algo = ExactEigensolver(algo_input.qubit_op, k=1, aux_operators=[])
result = algo.run()
x = exactcover.sample_most_likely(len(list_of_subsets), result['eigvecs'][0])
ising_sol = exactcover.get_solution(x)
np.testing.assert_array_equal(ising_sol, [0, 1, 1, 0])

if exactcover.check_solution_satisfiability(ising_sol, list_of_subsets):
    print("solution is", ising_sol)
else:
    print("no solution is found")

algorithm_cfg = {
    'name': 'VQE',
    'operator_mode': 'matrix'
}

optimizer_cfg = {
    'name': 'COBYLA'
}

var_form_cfg = {
    'name': 'RYRZ',
    'depth': 5
}

params = {
    'problem': {'name': 'ising', 'random_seed': 10598},
    'algorithm': algorithm_cfg,
    'optimizer': optimizer_cfg,
    'variational_form': var_form_cfg
}
backend = Aer.get_backend('statevector_simulator')
result = run_algorithm(params, algo_input, backend=backend)
x = exactcover.sample_most_likely(len(list_of_subsets), result['eigvecs'][0])
ising_sol = exactcover.get_solution(x)
if exactcover.check_solution_satisfiability(ising_sol, list_of_subsets):
    print("solution is", ising_sol)
else:
    print("no solution is found")