| # 1 "C:/Users/jessi/Desktop/bobs control repo/sov-kernel-monster/src/bob_circuit.f90"
|
| # 1 "<built-in>"
|
| # 1 "<command-line>"
|
| # 1 "C:/Users/jessi/Desktop/bobs control repo/sov-kernel-monster/src/bob_circuit.f90"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| module bob_circuit
|
| use, intrinsic :: iso_c_binding, only: c_int32_t, c_int64_t, c_double, &
|
| c_ptr, c_f_pointer, c_loc, c_size_t
|
| use, intrinsic :: iso_fortran_env, only: int64, real64, int32
|
| use bob_kinds
|
| use bob_errors
|
| implicit none
|
| private
|
|
|
|
|
|
|
|
|
| integer(i4), parameter, public :: GATE_PAULI_X = 0
|
| integer(i4), parameter, public :: GATE_PAULI_Y = 1
|
| integer(i4), parameter, public :: GATE_PAULI_Z = 2
|
| integer(i4), parameter, public :: GATE_HADAMARD = 3
|
| integer(i4), parameter, public :: GATE_T = 4
|
| integer(i4), parameter, public :: GATE_S = 5
|
| integer(i4), parameter, public :: GATE_CNOT = 100
|
| integer(i4), parameter, public :: GATE_CZ = 101
|
| integer(i4), parameter, public :: GATE_SWAP = 102
|
| integer(i4), parameter, public :: GATE_ROTATION = 200
|
| integer(i4), parameter, public :: GATE_MEASURE = 300
|
|
|
|
|
| integer(i4), parameter, public :: MAX_CIRCUIT_GATES = 65536
|
|
|
| integer(i4), parameter, public :: MAX_QUBITS = 64
|
|
|
|
|
| type, public :: bob_gate_t
|
| integer(i4) :: gate_type = 0
|
| integer(i4) :: target = -1
|
| integer(i4) :: control = -1
|
| real(wp) :: angle = ZERO
|
| integer(i4) :: classical = -1
|
| end type bob_gate_t
|
|
|
|
|
| type, public :: bob_circuit_t
|
| integer(i4) :: num_qubits = 0
|
| integer(i4) :: num_classical = 0
|
| integer(i4) :: num_gates = 0
|
| integer(i4) :: num_measurements= 0
|
| type(bob_gate_t) :: gates(MAX_CIRCUIT_GATES)
|
| logical(lk) :: is_valid = .false.
|
| contains
|
| procedure :: add_gate => circuit_add_gate
|
| procedure :: add_measure => circuit_add_measure
|
| procedure :: depth => circuit_depth
|
| procedure :: validate => circuit_validate
|
| procedure :: reset => circuit_reset
|
| end type bob_circuit_t
|
|
|
| public :: circuit_new
|
| public :: circuit_qft
|
| public :: circuit_grover
|
| public :: circuit_qpe
|
| public :: circuit_shor
|
| public :: circuit_bell_pair
|
| public :: circuit_teleportation
|
| public :: grover_optimal_iterations
|
|
|
|
|
| public :: bob_circuit_new
|
| public :: bob_circuit_qft
|
| public :: bob_circuit_grover
|
| public :: bob_circuit_depth
|
| public :: bob_circuit_free
|
|
|
| contains
|
|
|
|
|
|
|
|
|
| pure function circuit_new(num_qubits, num_classical) result(c)
|
| integer(i4), intent(in) :: num_qubits, num_classical
|
| type(bob_circuit_t) :: c
|
| c%num_qubits = num_qubits
|
| c%num_classical = num_classical
|
| c%num_gates = 0
|
| c%is_valid = .true.
|
| end function circuit_new
|
|
|
| subroutine circuit_reset(this)
|
| class(bob_circuit_t), intent(inout) :: this
|
| this%num_gates = 0
|
| this%num_measurements= 0
|
| this%is_valid = .true.
|
| end subroutine circuit_reset
|
|
|
|
|
|
|
|
|
| subroutine circuit_add_gate(this, gate_type, target, control, angle, status)
|
| class(bob_circuit_t), intent(inout) :: this
|
| integer(i4), intent(in) :: gate_type, target
|
| integer(i4), intent(in), optional :: control
|
| real(wp), intent(in), optional :: angle
|
| integer(i4), intent(out), optional :: status
|
| integer(i4) :: st
|
| st = BOB_SUCCESS
|
| if (.not. this%is_valid) then; st = BOB_ERROR_INVALID_STATE; goto 99; end if
|
| if (this%num_gates >= MAX_CIRCUIT_GATES) then
|
| call bob_set_error(BOB_ERROR_ALLOCATION, "circuit full", "circuit_add_gate")
|
| st = BOB_ERROR_ALLOCATION; goto 99
|
| end if
|
| if (target < 0 .or. target >= this%num_qubits) then
|
| st = BOB_ERROR_INVALID_ARGUMENT; goto 99
|
| end if
|
| this%num_gates = this%num_gates + 1
|
| this%gates(this%num_gates)%gate_type = gate_type
|
| this%gates(this%num_gates)%target = target
|
| this%gates(this%num_gates)%control = -1
|
| this%gates(this%num_gates)%angle = ZERO
|
| this%gates(this%num_gates)%classical = -1
|
| if (present(control)) this%gates(this%num_gates)%control = control
|
| if (present(angle)) this%gates(this%num_gates)%angle = angle
|
| 99 if (present(status)) status = st
|
| end subroutine circuit_add_gate
|
|
|
| subroutine circuit_add_measure(this, qubit, classical_bit, status)
|
| class(bob_circuit_t), intent(inout) :: this
|
| integer(i4), intent(in) :: qubit, classical_bit
|
| integer(i4), intent(out), optional :: status
|
| integer(i4) :: st
|
| st = BOB_SUCCESS
|
| if (qubit < 0 .or. qubit >= this%num_qubits) then
|
| st = BOB_ERROR_INVALID_ARGUMENT; goto 99
|
| end if
|
| this%num_gates = this%num_gates + 1
|
| this%gates(this%num_gates)%gate_type = GATE_MEASURE
|
| this%gates(this%num_gates)%target = qubit
|
| this%gates(this%num_gates)%classical = classical_bit
|
| this%num_measurements = this%num_measurements + 1
|
| 99 if (present(status)) status = st
|
| end subroutine circuit_add_measure
|
|
|
| pure function circuit_depth(this) result(d)
|
| class(bob_circuit_t), intent(in) :: this
|
| integer(i4) :: d
|
| d = this%num_gates
|
| end function circuit_depth
|
|
|
| pure function circuit_validate(this) result(ok)
|
| class(bob_circuit_t), intent(in) :: this
|
| logical :: ok
|
| ok = this%is_valid .and. this%num_gates > 0 .and. this%num_qubits > 0
|
| end function circuit_validate
|
|
|
|
|
|
|
|
|
|
|
|
|
| function circuit_qft(num_qubits, start) result(c)
|
| integer(i4), intent(in) :: num_qubits, start
|
| type(bob_circuit_t) :: c
|
| integer(i4) :: i, j, st
|
| real(wp) :: angle
|
| c = circuit_new(num_qubits, num_qubits)
|
| do i = 0, num_qubits - 1
|
|
|
| call c%add_gate(GATE_HADAMARD, start + i, status=st)
|
|
|
| do j = i + 1, num_qubits - 1
|
| angle = PI / real(ishft(1_i4, j - i), wp)
|
| call c%add_gate(GATE_CNOT, start + j, control=start + i, status=st)
|
| call c%add_gate(GATE_ROTATION, start + i, angle=angle, status=st)
|
| end do
|
| end do
|
|
|
| do i = 0, num_qubits / 2 - 1
|
| call c%add_gate(GATE_SWAP, start + i, &
|
| control=start + num_qubits - 1 - i, status=st)
|
| end do
|
|
|
| do i = 0, num_qubits - 1
|
| call c%add_measure(start + i, i, status=st)
|
| end do
|
| end function circuit_qft
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| pure function grover_optimal_iterations(num_qubits, num_solutions) result(k)
|
| integer(i4), intent(in) :: num_qubits, num_solutions
|
| integer(i4) :: k
|
| real(wp) :: n_states, theta
|
| n_states = real(ishft(1_i4, num_qubits), wp)
|
| theta = asin(sqrt(real(num_solutions, wp) / n_states))
|
| k = max(1, int(PI * QUART / theta, i4))
|
| end function grover_optimal_iterations
|
|
|
| function circuit_grover(num_qubits, num_solutions) result(c)
|
| integer(i4), intent(in) :: num_qubits, num_solutions
|
| type(bob_circuit_t) :: c
|
| integer(i4) :: i, iter, iters, st
|
| c = circuit_new(num_qubits, num_qubits)
|
|
|
| do i = 0, num_qubits - 1
|
| call c%add_gate(GATE_HADAMARD, i, status=st)
|
| end do
|
| iters = grover_optimal_iterations(num_qubits, num_solutions)
|
| do iter = 1, iters
|
|
|
| if (num_qubits >= 2) then
|
| call c%add_gate(GATE_CZ, num_qubits - 1, control=0, status=st)
|
| end if
|
|
|
| do i = 0, num_qubits - 1
|
| call c%add_gate(GATE_HADAMARD, i, status=st)
|
| call c%add_gate(GATE_PAULI_X, i, status=st)
|
| end do
|
| if (num_qubits >= 2) then
|
| call c%add_gate(GATE_CZ, num_qubits - 1, control=0, status=st)
|
| end if
|
| do i = 0, num_qubits - 1
|
| call c%add_gate(GATE_PAULI_X, i, status=st)
|
| call c%add_gate(GATE_HADAMARD, i, status=st)
|
| end do
|
| end do
|
|
|
| do i = 0, num_qubits - 1
|
| call c%add_measure(i, i, status=st)
|
| end do
|
| end function circuit_grover
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| function circuit_qpe(num_counting, target_qubit) result(c)
|
| integer(i4), intent(in) :: num_counting, target_qubit
|
| type(bob_circuit_t) :: c
|
| integer(i4) :: total, i, power, p, st
|
| type(bob_circuit_t) :: qft_c
|
| total = num_counting + 1
|
| c = circuit_new(total, num_counting)
|
|
|
| do i = 0, num_counting - 1
|
| call c%add_gate(GATE_HADAMARD, i, status=st)
|
| end do
|
|
|
| do i = 0, num_counting - 1
|
| power = ishft(1_i4, i)
|
| do p = 1, power
|
| call c%add_gate(GATE_CNOT, target_qubit, control=i, status=st)
|
| end do
|
| end do
|
|
|
| do i = 0, num_counting - 1
|
| call c%add_gate(GATE_HADAMARD, i, status=st)
|
| end do
|
|
|
| do i = 0, num_counting - 1
|
| call c%add_measure(i, i, status=st)
|
| end do
|
| end function circuit_qpe
|
|
|
|
|
|
|
|
|
|
|
|
|
| function circuit_shor(num_qubits) result(c)
|
| integer(i4), intent(in) :: num_qubits
|
| type(bob_circuit_t) :: c
|
| integer(i4) :: counting
|
| counting = max(1, num_qubits / 2)
|
| c = circuit_qpe(counting, counting)
|
| end function circuit_shor
|
|
|
|
|
|
|
|
|
|
|
| function circuit_bell_pair() result(c)
|
| type(bob_circuit_t) :: c
|
| integer(i4) :: st
|
| c = circuit_new(2, 2)
|
| call c%add_gate(GATE_HADAMARD, 0, status=st)
|
| call c%add_gate(GATE_CNOT, 1, control=0, status=st)
|
| call c%add_measure(0, 0, status=st)
|
| call c%add_measure(1, 1, status=st)
|
| end function circuit_bell_pair
|
|
|
|
|
|
|
|
|
|
|
| function circuit_teleportation() result(c)
|
| type(bob_circuit_t) :: c
|
| integer(i4) :: st
|
| c = circuit_new(3, 3)
|
|
|
| call c%add_gate(GATE_HADAMARD, 1, status=st)
|
| call c%add_gate(GATE_CNOT, 2, control=1, status=st)
|
|
|
| call c%add_gate(GATE_CNOT, 1, control=0, status=st)
|
| call c%add_gate(GATE_HADAMARD, 0, status=st)
|
|
|
| call c%add_measure(0, 0, status=st)
|
| call c%add_measure(1, 1, status=st)
|
|
|
| call c%add_gate(GATE_PAULI_X, 2, control=1, status=st)
|
| call c%add_gate(GATE_PAULI_Z, 2, control=0, status=st)
|
| call c%add_measure(2, 2, status=st)
|
| end function circuit_teleportation
|
|
|
|
|
|
|
|
|
|
|
| function bob_circuit_new(num_qubits, num_classical) result(ptr) &
|
| bind(C, name="bob_circuit_new")
|
| integer(c_int32_t), value :: num_qubits, num_classical
|
| type(c_ptr) :: ptr
|
| type(bob_circuit_t), pointer :: c
|
| allocate(c)
|
| c = circuit_new(int(num_qubits,i4), int(num_classical,i4))
|
| ptr = c_loc(c)
|
| end function bob_circuit_new
|
|
|
| function bob_circuit_qft(num_qubits, start) result(ptr) &
|
| bind(C, name="bob_circuit_qft")
|
| integer(c_int32_t), value :: num_qubits, start
|
| type(c_ptr) :: ptr
|
| type(bob_circuit_t), pointer :: c
|
| allocate(c)
|
| c = circuit_qft(int(num_qubits,i4), int(start,i4))
|
| ptr = c_loc(c)
|
| end function bob_circuit_qft
|
|
|
| function bob_circuit_grover(num_qubits, num_solutions) result(ptr) &
|
| bind(C, name="bob_circuit_grover")
|
| integer(c_int32_t), value :: num_qubits, num_solutions
|
| type(c_ptr) :: ptr
|
| type(bob_circuit_t), pointer :: c
|
| allocate(c)
|
| c = circuit_grover(int(num_qubits,i4), int(num_solutions,i4))
|
| ptr = c_loc(c)
|
| end function bob_circuit_grover
|
|
|
| function bob_circuit_depth(circ_ptr) result(d) bind(C, name="bob_circuit_depth")
|
| type(c_ptr), value :: circ_ptr
|
| integer(c_int32_t) :: d
|
| type(bob_circuit_t), pointer :: c
|
| if (.not. c_associated(circ_ptr)) then; d = 0; return; end if
|
| call c_f_pointer(circ_ptr, c)
|
| d = c%depth()
|
| end function bob_circuit_depth
|
|
|
| subroutine bob_circuit_free(circ_ptr) bind(C, name="bob_circuit_free")
|
| type(c_ptr), value :: circ_ptr
|
| type(bob_circuit_t), pointer :: c
|
| if (.not. c_associated(circ_ptr)) return
|
| call c_f_pointer(circ_ptr, c)
|
| deallocate(c)
|
| end subroutine bob_circuit_free
|
|
|
| end module bob_circuit
|
|
|
|
|
|
|