aboutsummaryrefslogtreecommitdiff
path: root/libpsi-core/src/core/runtime.rs
diff options
context:
space:
mode:
Diffstat (limited to 'libpsi-core/src/core/runtime.rs')
-rw-r--r--libpsi-core/src/core/runtime.rs160
1 files changed, 145 insertions, 15 deletions
diff --git a/libpsi-core/src/core/runtime.rs b/libpsi-core/src/core/runtime.rs
index 7b73c47..0a78f0f 100644
--- a/libpsi-core/src/core/runtime.rs
+++ b/libpsi-core/src/core/runtime.rs
@@ -1,5 +1,10 @@
use super::{GateOp, QuantumGate, QuantumRegister, QuantumState};
-use crate::gates::*;
+use crate::gates::{
+ cp_matrix, crx_matrix, cry_matrix, crz_matrix, p_matrix, rx_matrix, ry_matrix,
+ rz_matrix, u1_matrix, u2_matrix, u3_matrix, CNOT, CZ, FREDKIN, HADAMARD,
+ PAULI_X, PAULI_Y, PAULI_Z, SDG_GATE, SWAP, SXDG_GATE, SX_GATE, S_GATE, TDG_GATE,
+ TOFFOLI, T_GATE,
+};
use crate::maths::vector::Vector;
use crate::{complex, Complex, Matrix};
use rayon::prelude::*;
@@ -48,17 +53,118 @@ impl Runtime {
for op in operations {
match op {
+ // Clifford gates
GateOp::H(t) => register.apply_gate(&HADAMARD, &[*t]),
GateOp::X(t) => register.apply_gate(&PAULI_X, &[*t]),
GateOp::Y(t) => register.apply_gate(&PAULI_Y, &[*t]),
GateOp::Z(t) => register.apply_gate(&PAULI_Z, &[*t]),
GateOp::S(t) => register.apply_gate(&S_GATE, &[*t]),
- GateOp::T(t) => register.apply_gate(&T_GATE, &[*t]),
GateOp::CNOT(c, t) => register.apply_gate(&CNOT, &[*c, *t]),
GateOp::CZ(c, t) => register.apply_gate(&CZ, &[*c, *t]),
GateOp::SWAP(a, b) => register.apply_gate(&SWAP, &[*a, *b]),
GateOp::CCNOT(c1, c2, t) => register.apply_gate(&TOFFOLI, &[*c1, *c2, *t]),
GateOp::CSWAP(c, t1, t2) => register.apply_gate(&FREDKIN, &[*c, *t1, *t2]),
+
+ // Non-Clifford fixed gates
+ GateOp::T(t) => register.apply_gate(&T_GATE, &[*t]),
+ GateOp::Sdg(t) => register.apply_gate(&SDG_GATE, &[*t]),
+ GateOp::Tdg(t) => register.apply_gate(&TDG_GATE, &[*t]),
+ GateOp::Sx(t) => register.apply_gate(&SX_GATE, &[*t]),
+ GateOp::Sxdg(t) => register.apply_gate(&SXDG_GATE, &[*t]),
+
+ // Parametric single-qubit gates (non-Clifford for most angles)
+ GateOp::Rx(t, theta) => {
+ let gate = QuantumGate {
+ name: "Rx",
+ matrix: rx_matrix(*theta),
+ num_qubits: 1,
+ };
+ register.apply_gate(&gate, &[*t]);
+ }
+ GateOp::Ry(t, theta) => {
+ let gate = QuantumGate {
+ name: "Ry",
+ matrix: ry_matrix(*theta),
+ num_qubits: 1,
+ };
+ register.apply_gate(&gate, &[*t]);
+ }
+ GateOp::Rz(t, theta) => {
+ let gate = QuantumGate {
+ name: "Rz",
+ matrix: rz_matrix(*theta),
+ num_qubits: 1,
+ };
+ register.apply_gate(&gate, &[*t]);
+ }
+ GateOp::P(t, theta) => {
+ let gate = QuantumGate {
+ name: "P",
+ matrix: p_matrix(*theta),
+ num_qubits: 1,
+ };
+ register.apply_gate(&gate, &[*t]);
+ }
+ GateOp::U1(t, lambda) => {
+ let gate = QuantumGate {
+ name: "U1",
+ matrix: u1_matrix(*lambda),
+ num_qubits: 1,
+ };
+ register.apply_gate(&gate, &[*t]);
+ }
+ GateOp::U2(t, phi, lambda) => {
+ let gate = QuantumGate {
+ name: "U2",
+ matrix: u2_matrix(*phi, *lambda),
+ num_qubits: 1,
+ };
+ register.apply_gate(&gate, &[*t]);
+ }
+ GateOp::U3(t, theta, phi, lambda) => {
+ let gate = QuantumGate {
+ name: "U3",
+ matrix: u3_matrix(*theta, *phi, *lambda),
+ num_qubits: 1,
+ };
+ register.apply_gate(&gate, &[*t]);
+ }
+
+ // Controlled parametric gates
+ GateOp::CRx(c, t, theta) => {
+ let gate = QuantumGate {
+ name: "CRx",
+ matrix: crx_matrix(*theta),
+ num_qubits: 2,
+ };
+ register.apply_gate(&gate, &[*c, *t]);
+ }
+ GateOp::CRy(c, t, theta) => {
+ let gate = QuantumGate {
+ name: "CRy",
+ matrix: cry_matrix(*theta),
+ num_qubits: 2,
+ };
+ register.apply_gate(&gate, &[*c, *t]);
+ }
+ GateOp::CRz(c, t, theta) => {
+ let gate = QuantumGate {
+ name: "CRz",
+ matrix: crz_matrix(*theta),
+ num_qubits: 2,
+ };
+ register.apply_gate(&gate, &[*c, *t]);
+ }
+ GateOp::CP(c, t, theta) => {
+ let gate = QuantumGate {
+ name: "CP",
+ matrix: cp_matrix(*theta),
+ num_qubits: 2,
+ };
+ register.apply_gate(&gate, &[*c, *t]);
+ }
+
+ // Measurement and custom gates
GateOp::Measure(_, _) => {}
GateOp::Custom(gate, targets) => {
let quantum_gate = gate.to_quantum_gate();
@@ -83,18 +189,42 @@ impl Runtime {
state[0] = complex!(1.0, 0.0);
for op in operations {
- let (gate, targets): (&QuantumGate, Vec<usize>) = match op {
- GateOp::H(t) => (&HADAMARD, vec![*t]),
- GateOp::X(t) => (&PAULI_X, vec![*t]),
- GateOp::Y(t) => (&PAULI_Y, vec![*t]),
- GateOp::Z(t) => (&PAULI_Z, vec![*t]),
- GateOp::S(t) => (&S_GATE, vec![*t]),
- GateOp::T(t) => (&T_GATE, vec![*t]),
- GateOp::CNOT(c, t) => (&CNOT, vec![*c, *t]),
- GateOp::CZ(c, t) => (&CZ, vec![*c, *t]),
- GateOp::SWAP(a, b) => (&SWAP, vec![*a, *b]),
- GateOp::CCNOT(c1, c2, t) => (&TOFFOLI, vec![*c1, *c2, *t]),
- GateOp::CSWAP(c, t1, t2) => (&FREDKIN, vec![*c, *t1, *t2]),
+ let (gate_matrix, targets): (Matrix<Complex<f64>>, Vec<usize>) = match op {
+ // Clifford gates
+ GateOp::H(t) => (HADAMARD.matrix.clone(), vec![*t]),
+ GateOp::X(t) => (PAULI_X.matrix.clone(), vec![*t]),
+ GateOp::Y(t) => (PAULI_Y.matrix.clone(), vec![*t]),
+ GateOp::Z(t) => (PAULI_Z.matrix.clone(), vec![*t]),
+ GateOp::S(t) => (S_GATE.matrix.clone(), vec![*t]),
+ GateOp::CNOT(c, t) => (CNOT.matrix.clone(), vec![*c, *t]),
+ GateOp::CZ(c, t) => (CZ.matrix.clone(), vec![*c, *t]),
+ GateOp::SWAP(a, b) => (SWAP.matrix.clone(), vec![*a, *b]),
+ GateOp::CCNOT(c1, c2, t) => (TOFFOLI.matrix.clone(), vec![*c1, *c2, *t]),
+ GateOp::CSWAP(c, t1, t2) => (FREDKIN.matrix.clone(), vec![*c, *t1, *t2]),
+
+ // Non-Clifford fixed gates
+ GateOp::T(t) => (T_GATE.matrix.clone(), vec![*t]),
+ GateOp::Sdg(t) => (SDG_GATE.matrix.clone(), vec![*t]),
+ GateOp::Tdg(t) => (TDG_GATE.matrix.clone(), vec![*t]),
+ GateOp::Sx(t) => (SX_GATE.matrix.clone(), vec![*t]),
+ GateOp::Sxdg(t) => (SXDG_GATE.matrix.clone(), vec![*t]),
+
+ // Parametric single-qubit gates
+ GateOp::Rx(t, theta) => (rx_matrix(*theta), vec![*t]),
+ GateOp::Ry(t, theta) => (ry_matrix(*theta), vec![*t]),
+ GateOp::Rz(t, theta) => (rz_matrix(*theta), vec![*t]),
+ GateOp::P(t, theta) => (p_matrix(*theta), vec![*t]),
+ GateOp::U1(t, lambda) => (u1_matrix(*lambda), vec![*t]),
+ GateOp::U2(t, phi, lambda) => (u2_matrix(*phi, *lambda), vec![*t]),
+ GateOp::U3(t, theta, phi, lambda) => (u3_matrix(*theta, *phi, *lambda), vec![*t]),
+
+ // Controlled parametric gates
+ GateOp::CRx(c, t, theta) => (crx_matrix(*theta), vec![*c, *t]),
+ GateOp::CRy(c, t, theta) => (cry_matrix(*theta), vec![*c, *t]),
+ GateOp::CRz(c, t, theta) => (crz_matrix(*theta), vec![*c, *t]),
+ GateOp::CP(c, t, theta) => (cp_matrix(*theta), vec![*c, *t]),
+
+ // Measurement (skip) and custom gates
GateOp::Measure(_, _) => continue,
GateOp::Custom(custom_gate, tgts) => {
let quantum_gate = custom_gate.to_quantum_gate();
@@ -103,7 +233,7 @@ impl Runtime {
}
};
- state = apply_gate_parallel(&state, &gate.matrix, &targets, num_qubits);
+ state = apply_gate_parallel(&state, &gate_matrix, &targets, num_qubits);
}
QuantumState::new(state)