ket/c_api/
execution.rs

1// SPDX-FileCopyrightText: 2024 Evandro Chagas Ribeiro da Rosa <evandro@quantuloop.com>
2// SPDX-FileCopyrightText: 2024 2024 Otávio Augusto de Santana Jatobá <otavio.jatoba@grad.ufsc.br>
3//
4// SPDX-License-Identifier: Apache-2.0
5
6use itertools::Itertools;
7
8use crate::{
9    execution::*,
10    ir::{
11        instructions::Instruction,
12        qubit::{LogicalQubit, Qubit},
13    },
14    prelude::{Hamiltonian, QuantumGate},
15    process::{DumpData, Sample},
16};
17
18#[repr(C)]
19#[derive(Debug, Clone)]
20pub struct BatchCExecution {
21    submit_execution: fn(*const u8, usize, *const f64, usize),
22    get_results: fn(data: &mut *const u8, len: &mut usize),
23    clear: fn(),
24}
25
26impl BatchExecution for BatchCExecution {
27    fn submit_execution(&mut self, circuit: &[Instruction<usize>], parameters: &[f64]) {
28        let circuit = serde_json::to_vec(circuit).unwrap();
29        (self.submit_execution)(
30            circuit.as_ptr(),
31            circuit.len(),
32            parameters.as_ptr(),
33            parameters.len(),
34        );
35    }
36
37    fn get_results(&mut self) -> ResultData {
38        let mut buffer = std::ptr::null();
39        let mut len: usize = 0;
40        (self.get_results)(&mut buffer, &mut len);
41        let buffer = unsafe { std::slice::from_raw_parts(buffer, len) };
42        serde_json::from_slice(buffer).unwrap()
43    }
44
45    fn clear(&mut self) {
46        (self.clear)();
47    }
48}
49
50#[repr(C)]
51#[derive(Debug, Clone)]
52pub struct LiveCExecution {
53    gate: fn(*const u8, usize, usize, *const usize, usize),
54    measure: fn(*const usize, usize) -> u64,
55    exp_value: fn(*const u8, usize) -> f64,
56    sample: fn(*const usize, usize, usize, &mut *const u8, &mut usize),
57    dump: fn(*const usize, usize, &mut *const u8, &mut usize),
58    save: fn(&mut *const u8, &mut usize),
59    load: fn(*const u8, usize),
60}
61
62impl LiveExecution for LiveCExecution {
63    fn gate(&mut self, gate: QuantumGate, target: LogicalQubit, control: &[LogicalQubit]) {
64        assert!(target.is_main());
65        assert!(!control.iter().any(Qubit::is_aux));
66        let gate = serde_json::to_vec(&gate).unwrap();
67        let control = control.iter().map(Qubit::index).collect_vec();
68        (self.gate)(
69            gate.as_ptr(),
70            gate.len(),
71            target.index(),
72            control.as_ptr(),
73            control.len(),
74        );
75    }
76
77    fn measure(&mut self, qubits: &[LogicalQubit]) -> u64 {
78        assert!(!qubits.iter().any(Qubit::is_aux));
79        let qubits = qubits.iter().map(Qubit::index).collect_vec();
80
81        (self.measure)(qubits.as_ptr(), qubits.len())
82    }
83
84    fn exp_value(&mut self, hamiltonian: &Hamiltonian<LogicalQubit>) -> f64 {
85        let hamiltonian = serde_json::to_vec(&hamiltonian.to_usize_qubit()).unwrap();
86
87        (self.exp_value)(hamiltonian.as_ptr(), hamiltonian.len())
88    }
89
90    fn sample(&mut self, qubits: &[LogicalQubit], shots: usize) -> Sample {
91        assert!(!qubits.iter().any(Qubit::is_aux));
92        let qubits = qubits.iter().map(Qubit::index).collect_vec();
93
94        let mut result = std::ptr::null();
95        let mut size = 0;
96        (self.sample)(qubits.as_ptr(), qubits.len(), shots, &mut result, &mut size);
97
98        serde_json::from_slice(unsafe { std::slice::from_raw_parts(result, size) }).unwrap()
99    }
100
101    fn dump(&mut self, qubits: &[LogicalQubit]) -> DumpData {
102        assert!(!qubits.iter().any(Qubit::is_aux));
103        let qubits = qubits.iter().map(Qubit::index).collect_vec();
104
105        let mut result = std::ptr::null();
106        let mut size = 0;
107        (self.dump)(qubits.as_ptr(), qubits.len(), &mut result, &mut size);
108
109        serde_json::from_slice(unsafe { std::slice::from_raw_parts(result, size) }).unwrap()
110    }
111
112    fn save(&self) -> Vec<u8> {
113        let mut result = std::ptr::null();
114        let mut size = 0;
115        (self.save)(&mut result, &mut size);
116
117        unsafe { std::slice::from_raw_parts(result, size).to_vec() }
118    }
119
120    fn load(&mut self, data: &[u8]) {
121        (self.load)(data.as_ptr(), data.len())
122    }
123}
124
125#[no_mangle]
126/// # Safety
127pub unsafe extern "C" fn ket_make_configuration(
128    execution_target_json: *const u8,
129    execution_target_size: usize,
130    batch_execution: *const BatchCExecution,
131    live_execution: *const LiveCExecution,
132    result: &mut *mut (ExecutionTarget, Option<QuantumExecution>),
133) -> i32 {
134    let execution: Option<QuantumExecution> = if !batch_execution.is_null() {
135        Some(QuantumExecution::Batch(Box::new(unsafe {
136            (*batch_execution).clone()
137        })))
138    } else if !live_execution.is_null() {
139        Some(QuantumExecution::Live(Box::new(unsafe {
140            (*live_execution).clone()
141        })))
142    } else {
143        None
144    };
145
146    let execution_target =
147        unsafe { std::slice::from_raw_parts(execution_target_json, execution_target_size) };
148    let execution_target = serde_json::from_slice(execution_target).unwrap();
149
150    *result = Box::into_raw(Box::new((execution_target, execution)));
151
152    0
153}