Exemplo n.º 1
0
def optimize(alpha, beta):
    """Define a function that optimizes theta_A0, theta_A1, theta_B0, theta_B1 to maximize the probability of winning the game

    Args:
        - alpha (float): real coefficient of |00>
        - beta (float): real coefficient of |11>

    Returns:
        - (float): Probability of winning
    """
    def cost(params):
        """Define a cost function that only depends on params, given alpha and beta fixed"""
        return -winning_prob(params, alpha, beta)

    # QHACK #

    #Initialize parameters, choose an optimization method and number of steps
    init_params = np.ones(4)
    opt = qml.AdagradOptimizer()
    steps = 2000

    # QHACK #

    # set the initial parameter values
    params = init_params

    for i in range(steps):
        # update the circuit parameters
        # QHACK #

        params = opt.step(cost, params)

        # QHACK #

    return winning_prob(params, alpha, beta)
Exemplo n.º 2
0
def run_vqe(H):
    """Runs the variational quantum eigensolver on the problem Hamiltonian using the
    variational ansatz specified above.

    Fill in the missing parts between the # QHACK # markers below to run the VQE.

    Args:
        H (qml.Hamiltonian): The input Hamiltonian

    Returns:
        The ground state energy of the Hamiltonian.
    """
    # Initialize parameters
    num_qubits = len(H.wires)
    num_param_sets = (2 ** num_qubits) - 1
    params = np.random.uniform(low=-np.pi / 2, high=np.pi / 2, size=(num_param_sets, 3))

    energy = 0

    # QHACK #

    # Create a quantum device, set up a cost funtion and optimizer, and run the VQE.
    # (We recommend ~500 iterations to ensure convergence for this problem,
    # or you can design your own convergence criteria)

    dev = qml.device('default.qubit', wires=num_qubits)
    
    cost_fn = qml.ExpvalCost(variational_ansatz, H, dev)

    opt = qml.AdagradOptimizer(0.2)

    max_iterations = 500
    conv_tol = 1e-06

    for n in range(max_iterations):
        params, prev_energy = opt.step_and_cost(cost_fn, params)
        energy = cost_fn(params)
        conv = np.abs(energy - prev_energy)

        if n % 20 == 0:
            print('Iteration = {:},  Energy = {:.8f} Ha'.format(n, energy))

        if conv <= conv_tol:
            break

    # QHACK #

    # Return the ground state energy
    return energy
Exemplo n.º 3
0
def optimize_ada(init_params):
    ada = qml.AdagradOptimizer(0.4)

    var = init_params
    var_ada = [var]

    for it in range(100):
        var = ada.step(cost, var)

        if (it + 1) % 5 == 0:
            var_ada.append(var)
            print('Objective after step {:5d}: {: .7f} | Angles: {}'.format(
                it + 1, cost(var), var))

    print('Optimized rotation angles: {}, {}'.format(var, cost(var)))
    return var_ada
Exemplo n.º 4
0
def optimize_circuit(params):
    """Minimize the variational circuit and return its minimum value.

    The code you write for this challenge should be completely contained within this function
    between the # QHACK # comment markers. You should create a device and convert the
    variational_circuit function into an executable QNode. Next, you should minimize the variational
    circuit using gradient-based optimization to update the input params. Return the optimized value
    of the QNode as a single floating-point number.

    Args:
        params (np.ndarray): Input parameters to be optimized, of dimension 30

    Returns:
        float: the value of the optimized QNode
    """

    optimal_value = 0.0

    # QHACK #

    # Initialize the device
    dev = qml.device("default.qubit", wires=2)

    # Instantiate the QNode
    circuit = qml.QNode(variational_circuit, dev)

    # Minimize the circuit
    opt = qml.AdagradOptimizer(stepsize=0.4)

    max_iterations = 500
    conv_tol = 1e-6

    for n in range(max_iterations):
        params, prev_optimal_value = opt.step_and_cost(circuit, params)
        optimal_value = circuit(params)
        conv = np.abs(optimal_value - prev_optimal_value)

        # if n % 20 == 0:
        #     print('Iteration = {:},  Energy = {:.8f} Ha'.format(n, optimal_value))

        if conv <= conv_tol:
            break

    # QHACK #

    # Return the value of the minimized QNode
    return optimal_value
Exemplo n.º 5
0
def run_vqe(H):
    """Runs the variational quantum eigensolver on the problem Hamiltonian using the
    variational ansatz specified above.

    Fill in the missing parts between the # QHACK # markers below to run the VQE.

    Args:
        H (qml.Hamiltonian): The input Hamiltonian

    Returns:
        The ground state energy of the Hamiltonian.
    """
    energy = 0

    # QHACK #
    num_qubits = len(H.wires)
    num_params = num_qubits - 1

    # Initialize the quantum device
    dev = qml.device("default.qubit", wires=num_qubits)
    # Randomly choose initial parameters (how many do you need?)
    params = np.random.uniform(low=-np.pi / 2, high=np.pi / 2, size=num_params)
    # Set up a cost function
    cost_fn = qml.ExpvalCost(variational_ansatz, H, dev)
    # Set up an optimizer
    opt = qml.AdagradOptimizer(stepsize=0.4)

    # Run the VQE by iterating over many steps of the optimizer
    max_iterations = 500
    conv_tol = 1e-6

    for n in range(max_iterations):
        params, prev_energy = opt.step_and_cost(cost_fn, params)
        energy = cost_fn(params)
        conv = np.abs(energy - prev_energy)

        # if n % 20 == 0:
        #     print('Iteration = {:},  Energy = {:.8f} Ha'.format(n, energy))

        if conv <= conv_tol:
            break
    # QHACK #

    # Return the ground state energy
    return energy
Exemplo n.º 6
0
def qaoa_maxcut(n_layers=1):
    print("\np={:d}".format(n_layers))

    # initialize the parameters near zero
    init_params = 0.01 * np.random.rand(2, 2)

    # minimize the negative of the objective function
    def objective(params):
        gammas = params[0]
        betas = params[1]
        neg_obj = 0
        for edge in graph:
            # objective for the MaxCut problem
            neg_obj -= 0.5 * (
                1 - circuit(gammas, betas, edge=edge, n_layers=n_layers))
        return neg_obj

    # initialize optimizer: Adagrad works well empirically
    opt = qml.AdagradOptimizer(stepsize=0.5)

    # optimize parameters in objective
    params = init_params
    steps = 30
    for i in range(steps):
        params = opt.step(objective, params)
        if (i + 1) % 5 == 0:
            print("Objective after step {:5d}: {: .7f}".format(
                i + 1, -objective(params)))

    # sample measured bitstrings 100 times
    bit_strings = []
    n_samples = 100
    for i in range(0, n_samples):
        bit_strings.append(
            int(circuit(params[0], params[1], edge=None, n_layers=n_layers)))

    # 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(params[:, :n_layers]))
    print("Most frequently sampled bit string is: {:04b}".format(
        most_freq_bit_string))

    return -objective(params), bit_strings
Exemplo n.º 7
0
    def run_vqe(H, ansatz, params=None, gs_params=None):
        num_qubits = len(H.wires)
        num_param_sets = (2 ** num_qubits) - 1

        if params is None:
            params = np.random.uniform(low=-np.pi / 2, high=np.pi / 2, size=(num_param_sets, 3))

        H_cost_fn = qml.ExpvalCost(ansatz, H, dev)
        cost_fn = H_cost_fn

        if gs_params is not None:
            @qml.qnode(dev)
            def overlap(params, wires):
                variational_ansatz(gs_params, wires)
                qml.inv(qml.template(variational_ansatz)(params, wires))
                # obs = qml.expval(qml.PauliZ(0) @ qml.PauliZ(1) @ qml.PauliZ(2))
                return qml.probs([0, 1, 2])

            cost_fn = lambda p: H_cost_fn(p) + overlap(p, gs_params)[0]

        opt = qml.AdagradOptimizer(stepsize=0.4)

        max_iterations = 500
        conv_tol = 1e-6

        energy = 0

        for n in range(max_iterations):
            params, prev_energy = opt.step_and_cost(cost_fn, params)
            energy = cost_fn(params)
            conv = np.abs(energy - prev_energy)

            if n % 20 == 0:
                print('Iteration = {:},  Energy = {:.8f} Ha'.format(n, energy))

            if conv <= conv_tol:
                break

        return energy, params
Exemplo n.º 8
0
cost_fn = qml.ExpvalCost(ansatz, H, dev, optimize=True)

num_params_per_gate = 15                                 # The number of parameters in each two-qubit gate.
depth               = int(np.floor(np.log2(num_qubits))) # The depth of the TTN.
num_gates           = num_qubits - 1                     # The number of two-qubit gates in the TTN.
if fix_layers:
    num_params = num_params_per_gate * depth
else:
    num_params = num_params_per_gate * num_gates    # The total number of parameters in the TTN.

# Initialize the parameters.
np.random.seed(1)
params = np.pi*(np.random.rand(num_params) - 1.0)

# Perform VQE.
opt = qml.AdagradOptimizer(stepsize=0.2) # The optimizer to use.

# Optimizer parameters.
rtol    = 1e-5
atol    = 1e-9
maxiter = 100

print_results = True

prev_obj = 0.0
for step in range(maxiter):
    params, obj  = opt.step_and_cost(cost_fn, params)
    diff_obj     = np.abs(prev_obj - obj)
    rel_obj      = diff_obj/np.abs(prev_obj + 1e-15)

    prev_obj = obj
Exemplo n.º 9
0
##############################################################################
# We are now ready to perform the optimization. We will initialize the weights
# at random. Then we make use of the `Adagrad <https://pennylane.readthedocs.io/en/stable/introduction/optimizers.html>`_
# optimizer. Adaptive gradient descent methods are advantageous as the optimization
# of quantum sensing protocols is very sensitive to the step size.
def opt_cost(weights, phi=phi, gamma=gamma, J=J, W=W):
    return cost(weights, phi, gamma, J, W)


# Seed for reproducible results
np.random.seed(395)
weights = np.random.uniform(0, 2 * np.pi,
                            NUM_ANSATZ_PARAMETERS + NUM_MEASUREMENT_PARAMETERS)

opt = qml.AdagradOptimizer(stepsize=0.1)

print("Initialization: Cost = {:6.4f}".format(opt_cost(weights)))
for i in range(20):
    weights, cost_ = opt.step_and_cost(opt_cost, weights)

    if (i + 1) % 5 == 0:
        print("Iteration {:>4}: Cost = {:6.4f}".format(i + 1, cost_))

##############################################################################
# Comparison with the standard protocol
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# Now we want to see how our protocol compares to the standard Ramsey interferometry protocol.
# The probe state in this case is a tensor product of three separate :math:`|+\rangle` states
# while the encoded state is measured in the :math:`|+\rangle / |-\rangle` basis.
Exemplo n.º 10
0
    ansatz = ansatz_f
else:
    raise NotImplementedError("Not found initial state!")

# The circuit for computing the expectation value of H.
cost_fn = qml.ExpvalCost(ansatz, H, dev, optimize=True)

print(f"Total # of Parameters={num_params}")

# Perform VQE.
step_size = args.step
if args.opt == "qng":
    opt = qml.QNGOptimizer(stepsize=step_size, diag_approx=True, lam=0.1)
elif args.opt == "adagrad":
    opt = qml.AdagradOptimizer(stepsize=step_size)
elif args.opt == "adam":
    opt = qml.AdamOptimizer(stepsize=step_size)
else:
    raise NotImplementedError("Optimizer not found")
# Initialize the parameters.
np.random.seed(1)
if args.randomize == 1:
    params = np.pi * (np.random.rand(num_params) - 1.0)
elif args.randomize == 2:
    params = np.loadtxt(
        f"params_{args.ansatz}_{args.two_qubit}_{num_qubits}_{h}_{args.opt}_{step_size}_{initState}{1}.txt"
    )
    print(len(params), num_params)
    assert len(params) == num_params
else:
Exemplo n.º 11
0
def qft_U_loss(thetas):
    print(thetas[0].val if type(thetas[0]) is Variable else thetas[0])
    loss = 0
    for i in range(2**n_qubits):
        input_state_vector = I16[i]
        exp_output_eigenvalues = basisvector2eigenvalues(input_state_vector)
        output_eigenvalues = qft_U_iqft(thetas, input_state=input_state_vector)
        # Calculate loss as the sum of the squared diff. btw. eigenvalues of expected output and actual (PauliZ)
        loss += np.sum((np.array(exp_output_eigenvalues) -
                        np.array(output_eigenvalues))**2)
    return loss


# Actual optimazation
opt = qml.AdagradOptimizer()

# Init parameters in the U-gates
rng_seed = 0
np.random.seed(rng_seed)
# thetas = 2*π * np.random.randn(6)
thetas = np.array([π, π, π, π, π, π])

# Test run the loss function
print('Loss test:', qft_U_loss(thetas), qft_U_loss(thetas * 0.2))

# Perform optimazation
cost_history = []
steps = 10
for it in range(steps):
    thetas = opt.step(qft_U_loss, thetas)
Exemplo n.º 12
0
np.random.seed(1)
params0 = np.pi*(np.random.rand(num_params) - 1.0)

# Optimizer parameters.
rtol     = 1e-5
atol     = 1e-9
maxiter  = 50
stepsize = 0.05

print_results = True

# The different optimizers to test.
opt_names = ["QNG", "Grad", "AdaGrad", "Adam"]
opts      = [qml.QNGOptimizer(stepsize=stepsize, diag_approx=True, lam=0.1),
            qml.GradientDescentOptimizer(stepsize=stepsize), 
            qml.AdagradOptimizer(stepsize=stepsize),
            qml.AdamOptimizer(stepsize=stepsize)]

# Perform VQE.
times_opts = []
objs_opts  = []
for (opt, opt_name) in zip(opts, opt_names):
    times = []
    objs  = []

    print(f"OPTIMIZER {opt_name}")
    params   = np.copy(params0)
    prev_obj = 0.0
    for step in range(maxiter):
        start = time.time()
        params, obj  = opt.step_and_cost(cost_fn, params)
Exemplo n.º 13
0
def run_vqe(H):
    """Runs the variational quantum eigensolver on the problem Hamiltonian using the
    variational ansatz specified above.

    Fill in the missing parts between the # QHACK # markers below to run the VQE.

    Args:
        H (qml.Hamiltonian): The input Hamiltonian

    Returns:
        The ground state energy of the Hamiltonian.
    """
    energy = 0

    # QHACK #
    size = (2**(len(H.wires) + 1) - 2, )  #len(H.wires),3)

    dev = qml.device('default.qubit', wires=len(H.wires))
    # Initialize the quantum device
    np.random.seed(0)
    #params = np.random.uniform(low=-np.pi / 2, high=np.pi , size=size)
    params = np.random.normal(0.001, 0.01, size)
    #params = np.random.normal(0.01, np.pi, size)

    # Randomly choose initial parameters (how many do you need?)
    cost_fn = qml.ExpvalCost(variational_ansatz, H, dev, optimize=True)

    # Set up a cost function
    #opt = qml.GradientDescentOptimizer(stepsize=0.01)
    opt = qml.AdagradOptimizer(stepsize=0.2)
    # Set up an optimizer

    #    max_iterations=500
    #previous = 0
    #for i in range(500):
    #index = 0
    while True:
        #previous = energy
        params = opt.step(cost_fn, params)

        if time.time() - start_time > 55:
            break
        #if index % 25 == 0:
        #if round(energy, 7) == round(previous, 7):
        #    break
        #print(energy)
        #print(i)
        #index += 1

    energy = cost_fn(params)
    '''n=0
    while True:
        params = opt.step(cost_fn, params)
        prev = float(energy)
        energy = cost_fn(params)
        #if n%20==0:
        #    print(energy)
        if round(float(energy), 8) == round(prev, 8) or n == 500:
            break
        n+=1'''

    #    conv_tol = 1e-06

    #    print(params)
    #    for n in range(max_iterations):
    #        params, prev_energy = opt.step_and_cost(cost_fn, params)
    #        energy = cost_fn(params)
    #        conv = np.abs(energy - prev_energy)

    #        if n % 20 == 0:
    #            print('Iteration = {:},  Energy = {:.8f} Ha'.format(n, energy))

    #        if conv <= conv_tol:
    #            break
    # Run the VQE by iterating over many steps of the optimizer
    # QHACK #
    return energy
def find_excited_states(H):
    """
    Fill in the missing parts between the # QHACK # markers below. Implement
    a variational method that can find the three lowest energies of the provided
    Hamiltonian.

    Args:
        H (qml.Hamiltonian): The input Hamiltonian

    Returns:
        The lowest three eigenenergies of the Hamiltonian as a comma-separated string,
        sorted from smallest to largest.
    """

    energies = np.zeros(3)

    # QHACK #
    np.random.seed(52)

    def variational_ansatz(params, wires):
        for k in range(len(params)):
            for i in range(len(params[k])):
                qml.Rot(params[k][i][0],
                        params[k][i][1],
                        params[k][i][2],
                        wires=i)

            for i in range(len(params[k]) - 1):
                qml.CNOT(wires=[i, i + 1])
            qml.CNOT(wires=[len(wires) - 1, 0])

    def variational_ansatz1(params, wires):
        qml.PauliX(wires=1)
        for k in range(len(params)):
            for i in range(len(params[k])):
                qml.Rot(params[k][i][0],
                        params[k][i][1],
                        params[k][i][2],
                        wires=i)

            for i in range(len(params[k]) - 1):
                qml.CNOT(wires=[i, i + 1])
            qml.CNOT(wires=[len(wires) - 1, 0])

    def variational_ansatz2(params, wires):
        qml.PauliX(wires=0)
        for k in range(len(params)):
            for i in range(len(params[k])):
                qml.Rot(params[k][i][0],
                        params[k][i][1],
                        params[k][i][2],
                        wires=i)

            for i in range(len(params[k]) - 1):
                qml.CNOT(wires=[i, i + 1])
            qml.CNOT(wires=[len(wires) - 1, 0])

    num_qubits = len(H.wires)

    energy = 0
    opt = qml.AdagradOptimizer(0.2)

    max_iterations = 500
    conv_tol = 1e-04

    dev = qml.device('default.qubit', wires=num_qubits)
    dev1 = qml.device('default.qubit', wires=num_qubits)
    dev2 = qml.device('default.qubit', wires=num_qubits)
    cost_fn = qml.ExpvalCost(variational_ansatz, H, dev)
    cost_fn1 = qml.ExpvalCost(variational_ansatz1, H, dev1)
    cost_fn2 = qml.ExpvalCost(variational_ansatz2, H, dev2)

    def cost(params):
        return 0.55 * cost_fn2(params) + 0.65 * cost_fn1(params) + cost_fn(
            params)

    prev_energy = 100
    params = np.random.uniform(low=-np.pi / 2,
                               high=np.pi / 2,
                               size=(6, num_qubits, 3))
    for n in range(max_iterations):
        params, c = opt.step_and_cost(cost, params)
        energy = cost(params)
        conv = np.abs(energy - prev_energy)
        prev_energy = energy

        #if n % 20 == 0:
        #    print(energy)
        #    print('Iteration = {:},  Energy = {:.8f} Ha'.format(n, cost_fn(params)))
        #   print('Iteration = {:},  Energy = {:.8f} Ha'.format(n, cost_fn1(params)))
        #    print('Iteration = {:},  Energy = {:.8f} Ha'.format(n, cost_fn2(params)))

        if conv <= conv_tol:
            break

    energies[0] = cost_fn(params)
    energies[1] = cost_fn1(params)
    energies[2] = cost_fn2(params)

    # QHACK #

    return ",".join([str(E) for E in energies])
Exemplo n.º 15
0
from cost_functions import m_vqe_cost, ExpvalH
from Ansatz import variational_ansatz
from hamiltonians import hamiltonian_XXZ

# Creating training data
train_deltas = np.random.uniform(low=-1.1, high=1.1, size=5)

# Hyperparameters
eta = 0.75
n_layers = 2  # One encoding and one processing
L = 2 * n_layers

# Training Parameters
epochs = 50
optimizer = qml.AdagradOptimizer()

samples = 100

qubits = [2, 3, 4, 5]

var = []
mean = []

for n_qubits in qubits:
    dev = qml.device("default.qubit", wires=n_qubits)

    v_gradient = []

    for _ in tqdm(range(samples)):
        # Applyies train_deltas for the Meta-VQE cost function
Exemplo n.º 16
0
def find_excited_states(H):
    """
    Fill in the missing parts between the # QHACK # markers below. Implement
    a variational method that can find the three lowest energies of the provided
    Hamiltonian.

    Args:
        H (qml.Hamiltonian): The input Hamiltonian

    Returns:
        The lowest three eigenenergies of the Hamiltonian as a comma-separated string,
        sorted from smallest to largest.
    """

    energies = np.zeros(3)

    # QHACK #
    s_wires = [[0, 1, 2], [1, 2, 3]]
    d_wires = [[[0, 1], [2, 3]]]
    hfstate = [1, 1, 0, 0]

    dev = qml.device("default.qubit", wires=len(H.wires))

    #def new_ansatz(params, wires):
    #    qml.templates.UCCSD(weights=params,wires=H.wires,s_wires=s_wires,d_wires=d_wires,init_state=hfstate)

    def ansatz(params, wires):
        qml.templates.state_preparations.ArbitraryStatePreparation(params,
                                                                   wires=wires)

    cost_fn = qml.ExpvalCost(ansatz, H, dev, optimize=True)

    #opt = qml.GradientDescentOptimizer(stepsize=0.1)
    opt = qml.AdagradOptimizer(stepsize=0.4)
    #    opt = qml.optimize.QNGOptimizer(stepsize=0.1)
    np.random.seed(0)  # for reproducibility
    size = (2**(len(H.wires) + 1) - 2, )  #len(H.wires),3)
    #params = np.random.normal(0, np.pi, len(singles) + len(doubles))
    params = np.random.normal(0.001, 0.01, size=size)
    print(params)

    max_iterations = 140
    #    conv_tol = 1e-06
    #    index=0
    energy = 0

    for n in range(max_iterations):
        params, prev_energy = opt.step_and_cost(cost_fn, params)
        energy = cost_fn(params)
        conv = np.abs(energy - prev_energy)
        if n % 20 == 0:
            print('Iteration = {:},  Energy = {:.8f} Ha'.format(n, energy))

        if float(energy) == float(prev_energy) or n == 100:
            break

        gs = energy

        excited_f_state = (np.linalg.multi_dot(gs, qml.Hamiltonian,
                                               gs)) / np.vdot(gs, gs)

        excited_s_state = (np.linalg.multi_dot(
            excited_f_state, qml.Hamiltonian, excited_f_state)) / np.vdot(
                excited_f_state, excited_f_state)