diff options
| -rw-r--r-- | main.py | 92 |
1 files changed, 25 insertions, 67 deletions
@@ -1,11 +1,12 @@ import pennylane as qml from pennylane import numpy as np +from rich.progress import track n_vertices = 5 n_wires = 2*n_vertices +n_layers = 3 graph = [(0,1),(0,2),(0,3),(0,4),(1,2),(1,3),(2,3),(2,4),(3,4)] -# graph = [(0,2)] cost_hamiltonian = sum(qml.Hamiltonian([1,1,1], [ qml.PauliZ(2*edge[0]) @ qml.PauliZ(2*edge[1]), @@ -18,7 +19,6 @@ def U_B(beta): for wire in range(n_wires): qml.RX(2 * beta, wires=wire) - # unitary operator U_C with parameter gamma def U_C(gamma): for edge in graph: @@ -43,84 +43,42 @@ def U_C(gamma): qml.CNOT(wires=[wire2, wire4]) qml.CNOT(wires=[wire1, wire4]) - -def bitstring_to_int(bit_string_sample): - bit_string = "".join(str(bs) for bs in bit_string_sample) - return int(bit_string, base=2) - -dev = qml.device("default.qubit", wires=n_wires, shots=1) - -@qml.qnode(dev) -def circuit(gammas, betas, sample=False, n_layers=1): - # apply Hadamards to get the n qubit |+> state +def circuit(gammas, betas): for wire in range(n_wires): qml.Hadamard(wires=wire) - # p instances of unitary operators + for i in range(n_layers): U_C(gammas[i]) U_B(betas[i]) - if sample: - # measurement phase - return qml.sample() +dev = qml.device("default.qubit", wires=n_wires) + +@qml.qnode(dev) +def cost_function(params): + circuit(params[0], params[1]) return qml.expval(cost_hamiltonian) -def qaoa_maxcut(n_layers=1): - print("\np={:d}".format(n_layers)) +@qml.qnode(dev) +def probability_circuit(params): + circuit(params[0], params[1]) + return qml.probs() - # initialize the parameters near zero - init_gammas = 0.01 * np.random.rand(n_layers, requires_grad=True) - init_betas = 0.01 * np.random.rand(n_layers, requires_grad=True) +def qaoa_color(): + params = np.random.rand(2, n_layers, requires_grad=True) + print(params) - # initialize optimizer: Adagrad works well empirically opt = qml.QNSPSAOptimizer() - # optimize parameters in objective - gammas = init_gammas - betas = init_betas steps = 200 - for i in range(steps): - params, cost = opt.step_and_cost(circuit, gammas, betas, n_layers=n_layers) - gammas = params[0] - betas = params[1] - if (i + 1) % 5 == 0: - print("Objective after step {:5d}: {: .7f}".format(i + 1, cost)) - - # sample measured bitstrings 100 times - bit_strings = [] - n_samples = 1000 - for i in range(0, n_samples): - bit_strings.append(bitstring_to_int(circuit(gammas, betas, sample=True, n_layers=n_layers))) + for i in track(range(steps)): + params, cost = opt.step_and_cost(cost_function, params) + probs = probability_circuit(params) + print("{: .7f}, {:010b}".format(cost, np.argmax(probs))) - # print optimal parameters and most frequently sampled bitstring - counts = np.bincount(np.array(bit_strings)) - most_freq_bit_string = np.argmax(counts) - print("Optimized (gamma, beta) vectors:\n{} {}".format(gammas, betas)) - print("Most frequently sampled bit string is: {:010b}".format(most_freq_bit_string)) + return params - return circuit(gammas, betas, n_layers=n_layers), bit_strings - -bitstrings1 = qaoa_maxcut(n_layers=2)[1] +@qml.qnode(dev) +def h_exp(): + return qml.expval(cost_hamiltonian) -# import matplotlib.pyplot as plt -# matplotlib.use('module://matplotlib-backend-sixel') -# -# xticks = range(0, 16) -# xtick_labels = list(map(lambda x: format(x, "04b"), xticks)) -# bins = np.arange(0, 17) - 0.5 -# -# fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 4)) -# plt.subplot(1, 2, 1) -# plt.title("n_layers=1") -# plt.xlabel("bitstrings") -# plt.ylabel("freq.") -# plt.xticks(xticks, xtick_labels, rotation="vertical") -# plt.hist(bitstrings1, bins=bins) -# plt.subplot(1, 2, 2) -# plt.title("n_layers=2") -# plt.xlabel("bitstrings") -# plt.ylabel("freq.") -# plt.xticks(xticks, xtick_labels, rotation="vertical") -# plt.hist(bitstrings2, bins=bins) -# plt.tight_layout() -# plt.show() +params = qaoa_color() |