Single QPU VQE experiment

This notebook goes through the running of a VQE algorithm using interlin-q. For simplicity, we only try out using one QPU.

Step 1: Import libraries.

First we import all the necessary libraries. Interlin-q is build using the python framework QuNetSim which is a python software framework that can be used to simulate quantum networks up to the network layer. We also need PennyLane’s chemistry library for decomposing the Hamiltonian. We would also use PennyLane for the optimiser component

[1]:
# Basic Libraries
import sys
from pennylane import numpy as np
sys.path.append("../../")

# QuNetSim Components
from qunetsim.components import Network
from qunetsim.objects import Logger
from qunetsim.backends.qutip_backend import QuTipBackend

# Interlin-q Components
from interlinq import (ControllerHost, Constants, Clock,
Circuit, Layer, ComputingHost, Operation)

# Extra needed components
from pennylane import GradientDescentOptimizer
from hamiltonian_decomposition import decompose

Logger.DISABLED = False

Step 2: Decompose the Hamiltonian.

[2]:
geometry = 'h2.xyz'
charge = 0
multiplicity = 1
basis_set = 'sto-3g'
name = 'h2'
[3]:
coefficients, observables, qubit_num = decompose(name, geometry, charge, multiplicity, basis_set)
terms = list(zip(coefficients, observables))

terms
[3]:
[(-0.04207897647782276, [('Identity', 0)]),
 (0.17771287465139946, [('PauliZ', 0)]),
 (0.1777128746513994, [('PauliZ', 1)]),
 (-0.24274280513140462, [('PauliZ', 2)]),
 (-0.24274280513140462, [('PauliZ', 3)]),
 (0.17059738328801052, [('PauliZ', 0), ('PauliZ', 1)]),
 (0.04475014401535161,
  [('PauliY', 0), ('PauliX', 1), ('PauliX', 2), ('PauliY', 3)]),
 (-0.04475014401535161,
  [('PauliY', 0), ('PauliY', 1), ('PauliX', 2), ('PauliX', 3)]),
 (-0.04475014401535161,
  [('PauliX', 0), ('PauliX', 1), ('PauliY', 2), ('PauliY', 3)]),
 (0.04475014401535161,
  [('PauliX', 0), ('PauliY', 1), ('PauliY', 2), ('PauliX', 3)]),
 (0.12293305056183798, [('PauliZ', 0), ('PauliZ', 2)]),
 (0.1676831945771896, [('PauliZ', 0), ('PauliZ', 3)]),
 (0.1676831945771896, [('PauliZ', 1), ('PauliZ', 2)]),
 (0.12293305056183798, [('PauliZ', 1), ('PauliZ', 3)]),
 (0.17627640804319591, [('PauliZ', 2), ('PauliZ', 3)])]

Step 3: Prepare Circuit for Given Parameters

The circuit can be prepared using two different ways: either as one circuit, or several circuits run sequentially. The former approach is simpler and generally better for the optimisation function. The latter is better for debugging and for dynamic components of a quantum circuit (i.e. circuits that have a lot of changing operations).

Main Blocks

[4]:
def rotational_gate(params):
    phi, theta, omega = params
    cos = np.cos(theta / 2)
    sin = np.sin(theta / 2)

    res = np.array([[np.exp(-1j * (phi + omega) / 2) * cos, -np.exp(1j * (phi - omega) / 2) * sin],
                     [np.exp(-1j * (phi - omega) / 2) * sin, np.exp(1j * (phi + omega) / 2) * cos]])

    return res.unwrap()
[5]:
def initialisation_operations(q_map):
    ops = []
    host_id = list(q_map.keys())[0]

    op = Operation(
        name=Constants.PREPARE_QUBITS,
        qids=q_map[host_id],
        computing_host_ids=[host_id])
    ops.append(op)

    # Prepare the qubits on the computing host
    op = Operation(
        name=Constants.SINGLE,
        qids=[q_map[host_id][0]],
        gate=Operation.X,
        computing_host_ids=[host_id])
    ops.append(op)

    op = Operation(
        name=Constants.SINGLE,
        qids=[q_map[host_id][1]],
        gate=Operation.X,
        computing_host_ids=[host_id])
    ops.append(op)

    return Layer(ops)
[6]:
def ansatz_operations(q_map, parameters):
    layers = []
    host_id = list(q_map.keys())[0]

    ops = []

    for i in range(len(q_map[host_id])):
        op = Operation(
            name=Constants.SINGLE,
            qids=[q_map[host_id][i]],
            gate=Operation.CUSTOM,
            gate_param=rotational_gate(parameters[i]),
            computing_host_ids=[host_id])

        ops.append(op)

    layers.append(Layer(ops))

    op = Operation(
        name=Constants.TWO_QUBIT,
        qids=[q_map[host_id][2], q_map[host_id][3]],
        gate=Operation.CNOT,
        computing_host_ids=[host_id])

    layers.append(Layer([op]))

    op = Operation(
        name=Constants.TWO_QUBIT,
        qids=[q_map[host_id][2], q_map[host_id][0]],
        gate=Operation.CNOT,
        computing_host_ids=[host_id])

    layers.append(Layer([op]))

    op = Operation(
        name=Constants.TWO_QUBIT,
        qids=[q_map[host_id][3], q_map[host_id][1]],
        gate=Operation.CNOT,
        computing_host_ids=[host_id])

    layers.append(Layer([op]))

    return layers
[7]:
def measurement_operations(q_map):
    ops = []
    # Measuring only the first qubit
    op = Operation(
        name=Constants.MEASURE,
        qids=['q_0_0'],
        cids=['q_0_0'],
        computing_host_ids=[host_id])
    ops.append(op)
    layers.append(Layer(ops))

    # Measuring all qubits
    q_ids = q_map[host_id].copy()
    ops = []
    for q_id in q_ids:
        op = Operation(
            name=Constants.MEASURE,
            qids=[q_id],
            cids=[q_id],
            computing_host_ids=[computing_host_ids[0]])
        ops.append(op)

    return Layer(ops)

Single-step approach

[8]:
def initialise_and_create_ansatz(q_map, parameters):
    layers = []
    host_id = list(q_map.keys())[0]

    # Initialise the qubits on the computing host
    layers.append(initialisation_operations(q_map))

    # Apply the ansatz
    layers = layers + ansatz_operations(q_map, parameters)

    circuit = Circuit(q_map, layers)
    return circuit
[9]:
def controller_host_protocol(host, q_map, params):
    """
    Protocol for the controller host
    """

    monolithic_circuit = initialise_and_create_ansatz(q_map, params)

    host.generate_and_send_schedules(monolithic_circuit)
[10]:
def computing_host_protocol(host):
    host.receive_schedule()

Split-steps approach

[11]:
def prepare_qubits(q_map):
    circuit = Circuit(q_map, [initialisation_operations(q_map)])
    return circuit
[12]:
def apply_ansatz(q_map, parameters):
    circuit = Circuit(q_map, ansatz_operations(q_map, parameters))
    return circuit
[13]:
def controller_host_protocol_preparation(host, q_map, params):
    """
    Protocol for the controller host
    """
    host.generate_and_send_schedules(prepare_qubits(q_map))
[14]:
def controller_host_protocol_ansatz(host, q_map, params):
    """
    Protocol for the controller host
    """
    host.generate_and_send_schedules(apply_ansatz(q_map, params))
[15]:
# Used for the last one
def computing_host_protocol(host):
    host.receive_schedule()

Step 4: Run the circuit and get the Expectation Value

[16]:
def init_network():
    network = Network.get_instance()
    network.delay = 0
    network.start()

    clock = Clock()

    qutip = QuTipBackend()

    controller_host = ControllerHost(
        host_id="host_1",
        clock=clock,
        backend=qutip
    )

    computing_hosts, q_map = controller_host.create_distributed_network(
        num_computing_hosts=1,
        num_qubits_per_host=4)
    controller_host.start()

    network.add_hosts([
        computing_hosts[0],
        controller_host])

    return clock, controller_host, computing_hosts, q_map
[17]:
params = np.random.rand(4, 3)

Running for the single-step approach

[18]:
clock, controller_host, computing_hosts, q_map = init_network()

t1 = controller_host.run_protocol(
    controller_host_protocol,
    (q_map, params))
t2 = computing_hosts[0].run_protocol(computing_host_protocol)

t1.join()
t2.join()
INFO:qu_net_sim:Host QPU_0 started processing
INFO:qu_net_sim:Host host_1 started processing
INFO:qu_net_sim:host_1 sends BROADCAST message
INFO:qu_net_sim:sending ACK:1 from QPU_0 to host_1
INFO:qu_net_sim:QPU_0 received {"QPU_0": [{"name": "PREPARE_QUBITS", "qids": ["q_0_0", "q_0_1", "q_0_2", "q_0_3"], "cids": null, "gate": null, "gate_param": null, "computing_host_ids": ["QPU_0"], "pre_allocated_qubits": false, "layer_end": 0}, {"name": "SINGLE", "qids": ["q_0_0"], "cids": null, "gate": "X", "gate_param": null, "computing_host_ids": ["QPU_0"], "pre_allocated_qubits": false, "layer_end": 0}, {"name": "SINGLE", "qids": ["q_0_1"], "cids": null, "gate": "X", "gate_param": null, "computing_host_ids": ["QPU_0"], "pre_allocated_qubits": false, "layer_end": 0}, {"name": "SINGLE", "qids": ["q_0_0"], "cids": null, "gate": "custom_gate", "gate_param": [[[0.935132620818695, -0.34995168750809186], [-0.0549545845743462, 0.006386824348507643]], [[0.0549545845743462, 0.006386824348507643], [0.935132620818695, 0.34995168750809186]]], "computing_host_ids": ["QPU_0"], "pre_allocated_qubits": false, "layer_end": 1}, {"name": "SINGLE", "qids": ["q_0_1"], "cids": null, "gate": "custom_gate", "gate_param": [[[0.879507800560643, -0.16263760408224082], [-0.4471232796357334, 0.00978832463470065]], [[0.4471232796357334, 0.00978832463470065], [0.879507800560643, 0.16263760408224082]]], "computing_host_ids": ["QPU_0"], "pre_allocated_qubits": false, "layer_end": 1}, {"name": "SINGLE", "qids": ["q_0_2"], "cids": null, "gate": "custom_gate", "gate_param": [[[0.8415306556123834, -0.3629895117941569], [-0.40006883103057383, 0.0031145513098929673]], [[0.40006883103057383, 0.0031145513098929673], [0.8415306556123834, 0.3629895117941569]]], "computing_host_ids": ["QPU_0"], "pre_allocated_qubits": false, "layer_end": 1}, {"name": "SINGLE", "qids": ["q_0_3"], "cids": null, "gate": "custom_gate", "gate_param": [[[0.9274354442890774, -0.16893973773183632], [-0.3326177226041721, -0.026235706604433237]], [[0.3326177226041721, -0.026235706604433237], [0.9274354442890774, 0.16893973773183632]]], "computing_host_ids": ["QPU_0"], "pre_allocated_qubits": false, "layer_end": 1}, {"name": "TWO_QUBIT", "qids": ["q_0_2", "q_0_3"], "cids": null, "gate": "cnot", "gate_param": null, "computing_host_ids": ["QPU_0"], "pre_allocated_qubits": false, "layer_end": 2}, {"name": "TWO_QUBIT", "qids": ["q_0_2", "q_0_0"], "cids": null, "gate": "cnot", "gate_param": null, "computing_host_ids": ["QPU_0"], "pre_allocated_qubits": false, "layer_end": 3}, {"name": "TWO_QUBIT", "qids": ["q_0_3", "q_0_1"], "cids": null, "gate": "cnot", "gate_param": null, "computing_host_ids": ["QPU_0"], "pre_allocated_qubits": false, "layer_end": 4}]} with sequence number 0
INFO:qu_net_sim:QPU_0 sends CLASSICAL to host_1 with sequence 0
INFO:qu_net_sim:host_1 received ACK from QPU_0 with sequence number 0
INFO:qu_net_sim:QPU_0 awaits classical ACK from host_1 with sequence 0
INFO:qu_net_sim:sending ACK:1 from host_1 to QPU_0
INFO:qu_net_sim:host_1 received ACK with sequence number 0
INFO:qu_net_sim:QPU_0 received ACK from host_1 with sequence number 0
[19]:
# This should be 7 after the first invocation.
# For any further invocations, it would increase by 6: 13,19, 25, etc. So is that expected behaviour?
clock.ticks
[19]:
6

Running for the multi-step approach

[20]:
clock, controller_host, computing_hosts, q_map = init_network()

t1 = controller_host.run_protocol(
    controller_host_protocol_preparation,
    (q_map, params))
t2 = computing_hosts[0].run_protocol(computing_host_protocol)

t1.join()
t2.join()
INFO:qu_net_sim:Host QPU_0 started processing
INFO:qu_net_sim:Host host_1 started processing
INFO:qu_net_sim:host_1 sends BROADCAST message
INFO:qu_net_sim:sending ACK:1 from QPU_0 to host_1
INFO:qu_net_sim:QPU_0 received {"QPU_0": [{"name": "PREPARE_QUBITS", "qids": ["q_0_0", "q_0_1", "q_0_2", "q_0_3"], "cids": null, "gate": null, "gate_param": null, "computing_host_ids": ["QPU_0"], "pre_allocated_qubits": false, "layer_end": 0}, {"name": "SINGLE", "qids": ["q_0_0"], "cids": null, "gate": "X", "gate_param": null, "computing_host_ids": ["QPU_0"], "pre_allocated_qubits": false, "layer_end": 0}, {"name": "SINGLE", "qids": ["q_0_1"], "cids": null, "gate": "X", "gate_param": null, "computing_host_ids": ["QPU_0"], "pre_allocated_qubits": false, "layer_end": 0}]} with sequence number 0
INFO:qu_net_sim:QPU_0 sends CLASSICAL to host_1 with sequence 0
INFO:qu_net_sim:host_1 received ACK from QPU_0 with sequence number 0
INFO:qu_net_sim:QPU_0 awaits classical ACK from host_1 with sequence 0
INFO:qu_net_sim:sending ACK:1 from host_1 to QPU_0
INFO:qu_net_sim:host_1 received ACK with sequence number 0
INFO:qu_net_sim:QPU_0 received ACK from host_1 with sequence number 0
[21]:
clock.ticks
[21]:
2
[22]:
t1 = controller_host.run_protocol(
    controller_host_protocol_ansatz,
    (q_map, params))
t2 = computing_hosts[0].run_protocol(computing_host_protocol)

t1.join()
t2.join()
INFO:qu_net_sim:host_1 sends BROADCAST message
INFO:qu_net_sim:sending ACK:2 from QPU_0 to host_1
INFO:qu_net_sim:QPU_0 received {"QPU_0": [{"name": "SINGLE", "qids": ["q_0_0"], "cids": null, "gate": "custom_gate", "gate_param": [[[0.935132620818695, -0.34995168750809186], [-0.0549545845743462, 0.006386824348507643]], [[0.0549545845743462, 0.006386824348507643], [0.935132620818695, 0.34995168750809186]]], "computing_host_ids": ["QPU_0"], "pre_allocated_qubits": false, "layer_end": 2}, {"name": "SINGLE", "qids": ["q_0_1"], "cids": null, "gate": "custom_gate", "gate_param": [[[0.879507800560643, -0.16263760408224082], [-0.4471232796357334, 0.00978832463470065]], [[0.4471232796357334, 0.00978832463470065], [0.879507800560643, 0.16263760408224082]]], "computing_host_ids": ["QPU_0"], "pre_allocated_qubits": false, "layer_end": 2}, {"name": "SINGLE", "qids": ["q_0_2"], "cids": null, "gate": "custom_gate", "gate_param": [[[0.8415306556123834, -0.3629895117941569], [-0.40006883103057383, 0.0031145513098929673]], [[0.40006883103057383, 0.0031145513098929673], [0.8415306556123834, 0.3629895117941569]]], "computing_host_ids": ["QPU_0"], "pre_allocated_qubits": false, "layer_end": 2}, {"name": "SINGLE", "qids": ["q_0_3"], "cids": null, "gate": "custom_gate", "gate_param": [[[0.9274354442890774, -0.16893973773183632], [-0.3326177226041721, -0.026235706604433237]], [[0.3326177226041721, -0.026235706604433237], [0.9274354442890774, 0.16893973773183632]]], "computing_host_ids": ["QPU_0"], "pre_allocated_qubits": false, "layer_end": 2}, {"name": "TWO_QUBIT", "qids": ["q_0_2", "q_0_3"], "cids": null, "gate": "cnot", "gate_param": null, "computing_host_ids": ["QPU_0"], "pre_allocated_qubits": false, "layer_end": 3}, {"name": "TWO_QUBIT", "qids": ["q_0_2", "q_0_0"], "cids": null, "gate": "cnot", "gate_param": null, "computing_host_ids": ["QPU_0"], "pre_allocated_qubits": false, "layer_end": 4}, {"name": "TWO_QUBIT", "qids": ["q_0_3", "q_0_1"], "cids": null, "gate": "cnot", "gate_param": null, "computing_host_ids": ["QPU_0"], "pre_allocated_qubits": false, "layer_end": 5}]} with sequence number 1
INFO:qu_net_sim:QPU_0 sends CLASSICAL to host_1 with sequence 1
INFO:qu_net_sim:QPU_0 awaits classical ACK from host_1 with sequence 1
INFO:qu_net_sim:host_1 received ACK from QPU_0 with sequence number 1
INFO:qu_net_sim:sending ACK:2 from host_1 to QPU_0
INFO:qu_net_sim:host_1 received ACK with sequence number 1
INFO:qu_net_sim:QPU_0 received ACK from host_1 with sequence number 1
[23]:
clock.ticks
[23]:
7

Using qutip to get the expectation value

[24]:
from qutip import identity, sigmax, sigmay, sigmaz
from qutip import expect

def string_to_qutip_pauli(string):
    if string == 'Identity':
        return identity(2)
    if string == 'PauliX':
        return sigmax()
    if string == 'PauliY':
        return sigmay()
    if string == 'PauliZ':
        return sigmaz()

def expectation_value(terms, matrices):
    total = 0

    for term in terms:
        coefficient, observables = term

        needed_matrices = []
        needed_paulis = []

        for obs in observables:
            pauli, index = obs

            needed_matrices.append(matrices[index])
            needed_paulis.append(string_to_qutip_pauli(pauli))

        expectation = expect(needed_paulis, needed_matrices)

        total += coefficient * expectation[0][0]

    return total
[25]:
density_matrices = []

for qubit_id in computing_hosts[0].qubit_ids:
    qubit = computing_hosts[0].get_qubit_by_id(qubit_id)
    density_matrices.append(computing_hosts[0].backend.density_operator(qubit))

density_matrices
[25]:
[Quantum object: dims = [[2], [2]], shape = (2, 2), type = oper, isherm = True
 Qobj data =
 [[ 0.16214572+0.j         -0.04915474+0.01713544j]
  [-0.04915474-0.01713544j  0.83785428+0.j        ]],
 Quantum object: dims = [[2], [2]], shape = (2, 2), type = oper, isherm = True
 Qobj data =
 [[ 0.34145788+0.j         -0.39165646+0.04298185j]
  [-0.39165646-0.04298185j  0.65854212+0.j        ]],
 Quantum object: dims = [[2], [2]], shape = (2, 2), type = oper, isherm = True
 Qobj data =
 [[ 0.83993523+0.j         -0.020644  +0.00909593j]
  [-0.020644  -0.00909593j  0.16006477+0.j        ]],
 Quantum object: dims = [[2], [2]], shape = (2, 2), type = oper, isherm = True
 Qobj data =
 [[ 0.7642501 +0.j         -0.24510936+0.01696731j]
  [-0.24510936-0.01696731j  0.2357499 +0.j        ]]]
[26]:
expectation_value(terms, density_matrices)
[26]:
-0.7957850305933003

Optimise

[27]:
from qutip import identity, sigmax, sigmay, sigmaz
from qutip import expect

def string_to_qutip_pauli(string):
    if string == 'Identity':
        return identity(2)
    if string == 'PauliX':
        return sigmax()
    if string == 'PauliY':
        return sigmay()
    if string == 'PauliZ':
        return sigmaz()

def expectation_value(terms, matrices):
    total = 0

    for term in terms:
        coefficient, observables = term

        needed_matrices = []
        needed_paulis = []

        for obs in observables:
            pauli, index = obs

            needed_matrices.append(matrices[index])
            needed_paulis.append(string_to_qutip_pauli(pauli))

        expectation = expect(needed_paulis, needed_matrices)

        total += coefficient * expectation[0][0]

    return total
[28]:
def cost_fn(params):
    network = Network.get_instance()
    network.delay = 0
    network.start()

    clock = Clock()

    qutip = QuTipBackend()

    controller_host = ControllerHost(
        host_id="host_1",
        clock=clock,
        backend=qutip
    )

    computing_hosts, q_map = controller_host.create_distributed_network(
        num_computing_hosts=1,
        num_qubits_per_host=4)
    controller_host.start()

    network.add_hosts([
        computing_hosts[0],
        controller_host])

    t1 = controller_host.run_protocol(
    controller_host_protocol,
    (q_map, params))
    t2 = computing_hosts[0].run_protocol(computing_host_protocol)

    t1.join()
    t2.join()

    density_matrices = []

    for qubit_id in computing_hosts[0].qubit_ids:
        qubit = computing_hosts[0].get_qubit_by_id(qubit_id)
        density_matrices.append(computing_hosts[0].backend.density_operator(qubit))


    network.remove_host(computing_hosts[0])
    network.remove_host(controller_host)

    return expectation_value(terms, density_matrices)
[29]:
opt = opt = GradientDescentOptimizer(stepsize=0.4)
params = np.random.normal(0, np.pi, (4, 3))

params
[29]:
tensor([[ 1.11797316, -3.86530105,  1.84447336],
        [-2.49246701,  4.95869687, -2.97578573],
        [-0.56524129,  1.42750818,  1.3953073 ],
        [-1.11492183, -1.9811752 ,  0.79328341]], requires_grad=True)
[30]:
cost_fn(params)
INFO:qu_net_sim:Host QPU_0 started processing
INFO:qu_net_sim:Host host_1 started processing
INFO:qu_net_sim:host_1 sends BROADCAST message
INFO:qu_net_sim:sending ACK:1 from QPU_0 to host_1
INFO:qu_net_sim:QPU_0 received {"QPU_0": [{"name": "PREPARE_QUBITS", "qids": ["q_0_0", "q_0_1", "q_0_2", "q_0_3"], "cids": null, "gate": null, "gate_param": null, "computing_host_ids": ["QPU_0"], "pre_allocated_qubits": false, "layer_end": 0}, {"name": "SINGLE", "qids": ["q_0_0"], "cids": null, "gate": "X", "gate_param": null, "computing_host_ids": ["QPU_0"], "pre_allocated_qubits": false, "layer_end": 0}, {"name": "SINGLE", "qids": ["q_0_1"], "cids": null, "gate": "X", "gate_param": null, "computing_host_ids": ["QPU_0"], "pre_allocated_qubits": false, "layer_end": 0}, {"name": "SINGLE", "qids": ["q_0_0"], "cids": null, "gate": "custom_gate", "gate_param": [[[-0.03166728279602556, 0.3525897498727833], [0.8742146405529816, -0.3323047001289419]], [[-0.8742146405529816, -0.3323047001289419], [-0.03166728279602556, -0.3525897498727833]]], "computing_host_ids": ["QPU_0"], "pre_allocated_qubits": false, "layer_end": 1}, {"name": "SINGLE", "qids": ["q_0_1"], "cids": null, "gate": "custom_gate", "gate_param": [[[0.7240487217891628, -0.3125154764682361], [-0.5970209248675964, -0.14715142103816284]], [[0.5970209248675964, -0.14715142103816284], [0.7240487217891628, 0.3125154764682361]]], "computing_host_ids": ["QPU_0"], "pre_allocated_qubits": false, "layer_end": 1}, {"name": "SINGLE", "qids": ["q_0_2"], "cids": null, "gate": "custom_gate", "gate_param": [[[0.6917350553796867, -0.3047979267544777], [-0.36452021651009525, 0.5438068119842441]], [[0.36452021651009525, 0.5438068119842441], [0.6917350553796867, 0.3047979267544777]]], "computing_host_ids": ["QPU_0"], "pre_allocated_qubits": false, "layer_end": 1}, {"name": "SINGLE", "qids": ["q_0_3"], "cids": null, "gate": "custom_gate", "gate_param": [[[0.5411248043502964, 0.08778132718020476], [0.4836945380987444, -0.6822887794246493]], [[-0.4836945380987444, -0.6822887794246493], [0.5411248043502964, -0.08778132718020476]]], "computing_host_ids": ["QPU_0"], "pre_allocated_qubits": false, "layer_end": 1}, {"name": "TWO_QUBIT", "qids": ["q_0_2", "q_0_3"], "cids": null, "gate": "cnot", "gate_param": null, "computing_host_ids": ["QPU_0"], "pre_allocated_qubits": false, "layer_end": 2}, {"name": "TWO_QUBIT", "qids": ["q_0_2", "q_0_0"], "cids": null, "gate": "cnot", "gate_param": null, "computing_host_ids": ["QPU_0"], "pre_allocated_qubits": false, "layer_end": 3}, {"name": "TWO_QUBIT", "qids": ["q_0_3", "q_0_1"], "cids": null, "gate": "cnot", "gate_param": null, "computing_host_ids": ["QPU_0"], "pre_allocated_qubits": false, "layer_end": 4}]} with sequence number 0
INFO:qu_net_sim:QPU_0 sends CLASSICAL to host_1 with sequence 0
INFO:qu_net_sim:host_1 received ACK from QPU_0 with sequence number 0
INFO:qu_net_sim:QPU_0 awaits classical ACK from host_1 with sequence 0
INFO:qu_net_sim:sending ACK:1 from host_1 to QPU_0
INFO:qu_net_sim:host_1 received ACK with sequence number 0
INFO:qu_net_sim:QPU_0 received ACK from host_1 with sequence number 0
[30]:
0.03713374738267447
[31]:
Logger.DISABLED = True
[32]:
def rotational_gate(params):
    phi, theta, omega = params
    cos = np.cos(theta / 2)
    sin = np.sin(theta / 2)

    res = np.array([[np.exp(-1j * (phi + omega) / 2) * cos, -np.exp(1j * (phi - omega) / 2) * sin],
                     [np.exp(-1j * (phi - omega) / 2) * sin, np.exp(1j * (phi + omega) / 2) * cos]])

    if isinstance(res, np.tensor):
        return res.unwrap()
    else:
        return res._value
[33]:
%debug
max_iterations = 200
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
ERROR:root:No traceback has been produced, nothing to debug.
/home/shiro-raven/.local/lib/python3.8/site-packages/autograd/tracer.py:14: UserWarning: Output seems independent of input.
  warnings.warn("Output seems independent of input.")
Iteration = 0,  Energy = 0.03713375 Ha
[ ]: