# Installing required package: 
# pip install uranium-quantum
#
# Execute script:
# python create_circuit.py

import traceback
from uranium_quantum.circuit_composer.circuit_composer import *

# Create a circuit. Qubits are 0-indexed
no_qubits = 10
quantum_circuit = QuantumCircuit(no_qubits)
    	
try:
    # Add a simple one qubit gate. 
    # - The name of the method used to add a new gate is: 'gate_' + the name of the gate as found in Circuit Editor.
    #   Please checkout circuit editor help in order to see the name assigned to each gate.
    # - Always first argument is a list of controls 
    # - Second argument is always a list of target qubit indexes which may contain one or two qubits depending on the gate.
    # - Subsequent arguments are named gate paramaters, in case the gate accepts any parameters: 
    #   - theta if gate has 'theta' setting
    #   - phi if gate has 'phi' setting
    #   - lambda if gate has 'lambda' setting
    #   - t if gate has root in 't' format for pauli-root gates and swap-root gate
    #   - k if gate has root in 'k' format for pauli-root gates
    targets = [1]
    controls = []
    quantum_circuit.gate_hadamard(controls, targets)

    # Add simple one qubit gate with controls.
    targets = [2]
    controls = [Control(target = 0, state = '1'), Control(target = 1, state = '+i')]
    quantum_circuit.increment_step().gate_hadamard(controls, targets)

    # Add parametric gate. 
    targets = [5]
    theta_radians = 0.1
    phi_radians = 0.2
    lambda_radians = 0.3
    controls = [Control(target = 4, state = '1')];
    quantum_circuit.gate_u3(controls, targets, theta_radians, phi_radians, lambda_radians)

    # Add pauli-root gate, root is in 't' format
    targets = [3]
    controls = [Control(target = 0, state = '1'), Control(target = 1, state = '+i')]
    quantum_circuit.increment_step().gate_pauli_x_root(controls, targets, t=2.0)

    # Add pauli-root gate, root is in 'k' format
    targets = [7]
    controls = [Control(target = 5, state = '1'), Control(target = 6, state = '+i')]
    quantum_circuit.gate_pauli_y_root(controls, targets, k=8.0)

    # Add two qubit gate
    controls = []
    targets = [0, 1]
    quantum_circuit.increment_step().gate_swap(controls, targets)

    # Add controlled two qubit gate
    targets = [5, 6]
    controls = [Control(target = 3, state = '0'), Control(target = 4, state = '-i')]
    quantum_circuit.gate_swap(controls, targets)

    # Add aggregated_gate
    aggregated_gates = []
    aggregated_gates.append({'name': 'rx_theta', 'targets': [2], 'theta': 1.11})
    aggregated_gates.append({'name': 'pauli-x', 'targets': [3]})
    controls = [Control(target = 0, state = '+')]
    quantum_circuit.increment_step().gate_aggregate(controls, aggregated_gates)

except Exception as ex:
    traceback.print_exc()
    print(ex.message)

# Finally save circuit to disk. Circuit in yaml format can be imported in Uranium either directly from
# Circuit Editor using the 'Open' button or from the circuit details page which is reachable via MyProjects link
quantum_circuit.export("circuit.yaml")
