ket/c_api/process.rs
1// SPDX-FileCopyrightText: 2020 Evandro Chagas Ribeiro da Rosa <evandro@quantuloop.com>
2// SPDX-FileCopyrightText: 2020 Rafael de Santiago <r.santiago@ufsc.br>
3//
4// SPDX-License-Identifier: Apache-2.0
5
6//! C API for the `Process` struct.
7
8use super::error::wrapper;
9use crate::{
10 execution::{LogicalQubit, Qubit},
11 prelude::*,
12};
13
14/// Creates a new `Process` instance with the given process ID.
15///
16/// # Arguments
17///
18/// * `config` - \[in\] A mutable pointer to a `Configuration` instance.
19/// * `process` - \[out\] A mutable pointer to a `Process` pointer.
20///
21/// # Returns
22///
23/// An integer representing the error code. `0` indicates success.
24///
25/// # Safety
26///
27/// This function is marked as unsafe because it deals with raw pointers.
28#[no_mangle]
29pub unsafe extern "C" fn ket_process_new(
30 config: *mut Configuration,
31 process: &mut *mut Process,
32) -> i32 {
33 let config = unsafe { Box::from_raw(config) };
34 *process = Box::into_raw(Box::new(Process::new(*config)));
35 KetError::Success.error_code()
36}
37
38/// Deletes the `Process` instance.
39///
40/// # Arguments
41///
42/// * `process` - \[in\] A pointer to the `Process` instance to be deleted.
43///
44/// # Returns
45///
46/// An integer representing the error code. `0` indicates success.
47///
48/// # Safety
49///
50/// This function is marked as unsafe because it deals with raw pointers.
51#[no_mangle]
52pub unsafe extern "C" fn ket_process_delete(process: *mut Process) -> i32 {
53 unsafe {
54 let _ = Box::from_raw(process);
55 }
56 KetError::Success.error_code()
57}
58
59/// Allocates a qubit for the `Process` instance.
60///
61/// # Arguments
62///
63/// * `process` - \[in\] A mutable reference to the `Process` instance.
64/// * `qubit` - \[out\] A mutable pointer to a `usize`.
65///
66/// # Returns
67///
68/// An integer representing the error code. `0` indicates success.
69#[no_mangle]
70pub extern "C" fn ket_process_allocate_qubit(process: &mut Process, qubit: &mut usize) -> i32 {
71 match process.alloc() {
72 Ok(result) => {
73 *qubit = result.index();
74 KetError::Success.error_code()
75 }
76 Err(error) => error.error_code(),
77 }
78}
79
80/// Applies a quantum gate to the target `Qubit` in the `Process` instance.
81///
82/// # Arguments
83///
84/// * `process` - \[in\] A mutable reference to the `Process` instance.
85/// * `gate` - \[in\] An integer representing the gate type. See the function body for the mapping of gate values to gate types.
86/// * `pi_fraction_top` - \[in\] The numerator of the fraction part of the angle, used by certain gate types.
87/// * `pi_fraction_bottom` - \[in\] The denominator of the fraction part of the angle, used by certain gate types.
88/// * `scalar` - \[in\] A floating-point parameter value used by certain gate types.
89/// * `target` - \[in\] A reference to the target `Qubit` instance.
90///
91/// # Returns
92///
93/// An integer representing the error code. `0` indicates success.
94#[no_mangle]
95pub extern "C" fn ket_process_apply_gate(
96 process: &mut Process,
97 gate: i32,
98 angle: f64,
99 target: usize,
100) -> i32 {
101 let gate = match gate {
102 1 => QuantumGate::PauliX,
103 2 => QuantumGate::PauliY,
104 3 => QuantumGate::PauliZ,
105 10 => QuantumGate::RotationX(angle),
106 20 => QuantumGate::RotationY(angle),
107 30 => QuantumGate::RotationZ(angle),
108 31 => QuantumGate::Phase(angle),
109 0 => QuantumGate::Hadamard,
110 _ => panic!("Undefined Pauli index. Use 0 for H, 1 for X, 2 for Y, and 3 for Z"),
111 };
112
113 wrapper(process.gate(gate, LogicalQubit::main(target)))
114}
115
116/// Applies a global phase.
117///
118/// # Arguments
119///
120/// * `process` - \[in\] A mutable reference to the `Process` instance.
121/// * `pi_fraction_top` - \[in\] The numerator of the fraction part of the angle.
122/// * `pi_fraction_bottom` - \[in\] The denominator of the fraction part of the angle.
123/// * `scalar` - \[in\] A floating-point parameter value.
124///
125/// # Returns
126///
127/// An integer representing the error code. `0` indicates success.
128#[no_mangle]
129pub extern "C" fn ket_process_apply_global_phase(process: &mut Process, angle: f64) -> i32 {
130 wrapper(process.global_phase(angle))
131}
132
133/// Measures the specified qubits in the `Process` instance.
134///
135/// # Arguments
136///
137/// * `process` - \[in\] A mutable reference to the `Process` instance.
138/// * `qubits` - \[in\] A mutable pointer to an array of mutable references to `Qubit` instances.
139/// * `qubits_size` - \[in\] The size of the `qubits` array.
140/// * `result` - \[out\] A mutable pointer to a `usize` where the measurement result will be stored.
141///
142/// # Returns
143///
144/// An integer representing the error code. `0` indicates success.
145///
146/// # Safety
147///
148/// This function is marked as unsafe due to the use of raw pointers.
149#[no_mangle]
150pub unsafe extern "C" fn ket_process_measure(
151 process: &mut Process,
152 qubits: *const usize,
153 qubits_size: usize,
154 result: &mut usize,
155) -> i32 {
156 let qubits = unsafe { std::slice::from_raw_parts(qubits, qubits_size) };
157 let qubits = qubits
158 .iter()
159 .map(|index| LogicalQubit::main(*index))
160 .collect::<Vec<_>>();
161
162 match process.measure(&qubits) {
163 Ok(result_id) => {
164 *result = result_id;
165 KetError::Success.error_code()
166 }
167 Err(error) => error.error_code(),
168 }
169}
170
171/// Creates a new `PauliHamiltonian` instance.
172///
173/// # Arguments
174///
175/// * `hamiltonian` - \[out\] A mutable pointer to a `PauliHamiltonian` pointer.
176///
177/// # Returns
178///
179/// An integer representing the error code. `0` indicates success.
180#[no_mangle]
181pub extern "C" fn ket_hamiltonian_new(hamiltonian: &mut *mut Hamiltonian<LogicalQubit>) -> i32 {
182 *hamiltonian = Box::into_raw(Box::default());
183
184 KetError::Success.error_code()
185}
186
187/// Adds a term to the `PauliHamiltonian`.
188///
189/// # Arguments
190///
191/// * `hamiltonian` - \[in\] A mutable reference to the `PauliHamiltonian` instance.
192/// * `pauli` - \[in\] A pointer to an array of integers representing the Pauli operators (1 for X, 2 for Y, 3 for Z).
193/// * `pauli_size` - \[in\] The size of the `pauli` array.
194/// * `qubits` - \[in\] A pointer to an array of integers representing the qubit indices for each Pauli operator.
195/// * `qubits_size` - \[in\] The size of the `qubits` array.
196/// * `coefficients` - \[in\] The coefficient for the term.
197///
198/// # Returns
199///
200/// An integer representing the error code. `0` indicates success.
201///
202/// # Safety
203///
204/// This function is marked as unsafe due to the use of raw pointers.
205#[no_mangle]
206pub unsafe extern "C" fn ket_hamiltonian_add(
207 hamiltonian: &mut Hamiltonian<LogicalQubit>,
208 pauli: *const i32,
209 pauli_size: usize,
210 qubits: *const usize,
211 qubits_size: usize,
212 coefficients: f64,
213) -> i32 {
214 assert_eq!(pauli_size, qubits_size);
215
216 let pauli = unsafe { std::slice::from_raw_parts(pauli, pauli_size) };
217 let qubits = unsafe { std::slice::from_raw_parts(qubits, qubits_size) };
218 let qubits = qubits
219 .iter()
220 .map(|index| LogicalQubit::main(*index))
221 .collect::<Vec<_>>();
222
223 let pauli_product: PauliProduct<_> = pauli
224 .iter()
225 .zip(qubits.iter())
226 .map(|(pauli, qubit)| {
227 let pauli = match pauli {
228 1 => Pauli::PauliX,
229 2 => Pauli::PauliY,
230 3 => Pauli::PauliZ,
231 _ => panic!("Undefined Pauli index. Use 1 for X, 2 for Y, and 3 for Z"),
232 };
233
234 PauliTerm {
235 pauli,
236 qubit: *qubit,
237 }
238 })
239 .collect();
240
241 hamiltonian.products.push(pauli_product);
242 hamiltonian.coefficients.push(coefficients);
243
244 KetError::Success.error_code()
245}
246
247/// Calculates the expected value of the `PauliHamiltonian` in the `Process` instance.
248///
249/// # Arguments
250///
251/// * `process` - \[in\] A mutable reference to the `Process` instance.
252/// * `hamiltonian` - \[in\] A mutable pointer to a `PauliHamiltonian`.
253/// * `result` - \[out\] A mutable pointer to a `usize` where the result identifier will be stored.
254///
255/// # Returns
256///
257/// An integer representing the error code. `0` indicates success.
258///
259/// # Safety
260///
261/// This function is marked as unsafe due to the use of raw pointers.
262#[no_mangle]
263pub unsafe extern "C" fn ket_process_exp_value(
264 process: &mut Process,
265 hamiltonian: *mut Hamiltonian<LogicalQubit>,
266 result: &mut usize,
267) -> i32 {
268 let hamiltonian = unsafe { Box::from_raw(hamiltonian) };
269 match process.exp_value(*hamiltonian) {
270 Ok(result_id) => {
271 *result = result_id;
272
273 KetError::Success.error_code()
274 }
275 Err(error) => error.error_code(),
276 }
277}
278
279/// Samples the specified qubits in the `Process` instance.
280///
281/// # Arguments
282///
283/// * `process` - \[in\] A mutable reference to the `Process` instance.
284/// * `qubits` - \[in\] A pointer to an array of integers representing the qubit indices to be sampled.
285/// * `qubits_size` - \[in\] The size of the `qubits` array.
286/// * `shots` - \[in\] The number of measurement shots.
287/// * `result` - \[out\] A mutable pointer to a `usize` where the result identifier will be stored.
288///
289/// # Returns
290///
291/// An integer representing the error code. `0` indicates success.
292///
293/// # Safety
294///
295/// This function is marked as unsafe due to the use of raw pointers.
296#[no_mangle]
297pub unsafe extern "C" fn ket_process_sample(
298 process: &mut Process,
299 qubits: *const usize,
300 qubits_size: usize,
301 shots: usize,
302 result: &mut usize,
303) -> i32 {
304 let qubits = unsafe { std::slice::from_raw_parts(qubits, qubits_size) };
305 let qubits = qubits
306 .iter()
307 .map(|index| LogicalQubit::main(*index))
308 .collect::<Vec<_>>();
309
310 match process.sample(&qubits, shots) {
311 Ok(result_id) => {
312 *result = result_id;
313
314 KetError::Success.error_code()
315 }
316 Err(error) => error.error_code(),
317 }
318}
319
320/// Dumps the state of the specified qubits in the `Process` instance.
321///
322/// # Arguments
323///
324/// * `process` - \[in\] A mutable reference to the `Process` instance.
325/// * `qubits` - \[in\] A pointer to an array of qubit indices to be dumped.
326/// * `qubits_size` - \[in\] The size of the `qubits` array.
327/// * `result` - \[out\] A mutable pointer to a `usize` representing the result index of the dump.
328///
329/// # Returns
330///
331/// An integer representing the error code. `0` indicates success.
332///
333/// # Safety
334///
335/// This function is marked as unsafe due to the use of raw pointers.
336#[no_mangle]
337pub unsafe extern "C" fn ket_process_dump(
338 process: &mut Process,
339 qubits: *const usize,
340 qubits_size: usize,
341 result: &mut usize,
342) -> i32 {
343 let qubits = unsafe { std::slice::from_raw_parts(qubits, qubits_size) };
344 let qubits = qubits
345 .iter()
346 .map(|index| LogicalQubit::main(*index))
347 .collect::<Vec<_>>();
348
349 match process.dump(&qubits) {
350 Ok(result_id) => {
351 *result = result_id;
352
353 KetError::Success.error_code()
354 }
355 Err(error) => error.error_code(),
356 }
357}
358
359/// Pushes control qubits onto the control stack in the `Process` instance.
360///
361/// # Arguments
362///
363/// * `process` - \[in\] A mutable reference to the `Process` instance.
364/// * `qubits` - \[in\] A pointer to an array of qubit indices to be pushed onto the control stack.
365/// * `qubits_size` - \[in\] The size of the `qubits` array.
366///
367/// # Returns
368///
369/// An integer representing the error code. `0` indicates success.
370///
371/// # Safety
372///
373/// This function is marked as unsafe due to the use of raw pointers.
374#[no_mangle]
375pub unsafe extern "C" fn ket_process_ctrl_push(
376 process: &mut Process,
377 qubits: *const usize,
378 qubits_size: usize,
379) -> i32 {
380 let qubits = unsafe { std::slice::from_raw_parts(qubits, qubits_size) };
381 let qubits = qubits
382 .iter()
383 .map(|index| LogicalQubit::main(*index))
384 .collect::<Vec<_>>();
385
386 wrapper(process.ctrl_push(&qubits))
387}
388
389/// Pops control qubits from the control stack in the `Process` instance.
390///
391/// # Arguments
392///
393/// * `process` - \[in\] A mutable reference to the `Process` instance.
394///
395/// # Returns
396///
397/// An integer representing the error code. `0` indicates success.
398#[no_mangle]
399pub extern "C" fn ket_process_ctrl_pop(process: &mut Process) -> i32 {
400 wrapper(process.ctrl_pop())
401}
402
403/// Pushes control stack in the `Process` instance.
404///
405/// # Arguments
406///
407/// * `process` - \[in\] A mutable reference to the `Process` instance.
408///
409/// # Returns
410///
411/// An integer representing the error code. `0` indicates success.
412///
413/// # Safety
414///
415/// This function is marked as unsafe due to the use of raw pointers.
416#[no_mangle]
417pub unsafe extern "C" fn ket_process_ctrl_stack(process: &mut Process) -> i32 {
418 wrapper(process.ctrl_begin())
419}
420
421/// Pops control stack from the `Process` instance.
422///
423/// # Arguments
424///
425/// * `process` - \[in\] A mutable reference to the `Process` instance.
426///
427/// # Returns
428///
429/// An integer representing the error code. `0` indicates success.
430#[no_mangle]
431pub extern "C" fn ket_process_ctrl_unstack(process: &mut Process) -> i32 {
432 wrapper(process.ctrl_end())
433}
434
435/// Begins an adjoint operation in the `Process` instance.
436///
437/// # Arguments
438///
439/// * `process` - \[in\] A mutable reference to the `Process` instance.
440///
441/// # Returns
442///
443/// An integer representing the error code. `0` indicates success.
444#[no_mangle]
445pub extern "C" fn ket_process_adj_begin(process: &mut Process) -> i32 {
446 wrapper(process.adj_begin())
447}
448
449/// Ends an adjoint operation in the `Process` instance.
450///
451/// # Arguments
452///
453/// * `process` - \[in\] A mutable reference to the `Process` instance.
454///
455/// # Returns
456///
457/// An integer representing the error code. `0` indicates success.
458#[no_mangle]
459pub extern "C" fn ket_process_adj_end(process: &mut Process) -> i32 {
460 wrapper(process.adj_end())
461}
462
463/// Prepares the `Process` instance for execution.
464///
465/// # Arguments
466///
467/// * `process` - \[in\] A mutable reference to the `Process` instance.
468///
469/// # Returns
470///
471/// An integer representing the error code. `0` indicates success.
472#[no_mangle]
473pub extern "C" fn ket_process_execute(process: &mut Process) -> i32 {
474 wrapper(process.execute())
475}
476
477#[no_mangle]
478pub extern "C" fn ket_process_transpile(process: &mut Process) -> i32 {
479 process.transpile();
480 wrapper(Ok(()))
481}
482
483/// Gets the JSON representation of the logical instructions in the `Process` instance.
484///
485/// # Arguments
486///
487/// * `process` - \[in\] A mutable reference to the `Process` instance.
488/// * `buffer` - \[in/out\] A mutable pointer to a buffer to store the JSON representation.
489/// * `buffer_size` - \[in\] The size of the provided buffer.
490/// * `write_size` - \[out\] A mutable pointer to the actual size of the written data.
491///
492/// # Returns
493///
494/// An integer representing the error code. `0` indicates success.
495///
496/// # Safety
497///
498/// This function is marked as unsafe due to the use of raw pointers.
499#[no_mangle]
500pub unsafe extern "C" fn ket_process_instructions_json(
501 process: &mut Process,
502 buffer: *mut u8,
503 buffer_size: usize,
504 write_size: &mut usize,
505) -> i32 {
506 let instructions = process.instructions_json();
507 let instructions = instructions.as_bytes();
508 *write_size = instructions.len();
509 if buffer_size >= *write_size {
510 let buffer = unsafe { std::slice::from_raw_parts_mut(buffer, buffer_size) };
511 buffer[..*write_size].copy_from_slice(instructions);
512 }
513
514 KetError::Success.error_code()
515}
516
517/// Gets the JSON representation of the physical instructions in the `Process` instance.
518///
519/// # Arguments
520///
521/// * `process` - \[in\] A mutable reference to the `Process` instance.
522/// * `buffer` - \[in/out\] A mutable pointer to a buffer to store the JSON representation.
523/// * `buffer_size` - \[in\] The size of the provided buffer.
524/// * `write_size` - \[out\] A mutable pointer to the actual size of the written data.
525///
526/// # Returns
527///
528/// An integer representing the error code. `0` indicates success.
529///
530/// # Safety
531///
532/// This function is marked as unsafe due to the use of raw pointers.
533#[no_mangle]
534pub unsafe extern "C" fn ket_process_isa_instructions_json(
535 process: &mut Process,
536 buffer: *mut u8,
537 buffer_size: usize,
538 write_size: &mut usize,
539) -> i32 {
540 let instructions = process.isa_instructions_json();
541 let instructions = instructions.as_bytes();
542 *write_size = instructions.len();
543 if buffer_size >= *write_size {
544 let buffer = unsafe { std::slice::from_raw_parts_mut(buffer, buffer_size) };
545 buffer[..*write_size].copy_from_slice(instructions);
546 }
547
548 KetError::Success.error_code()
549}
550
551/// Gets the JSON representation of the metadata in the `Process` instance.
552///
553/// # Arguments
554///
555/// * `process` - \[in\] A mutable reference to the `Process` instance.
556/// * `buffer` - \[in/out\] A mutable pointer to a buffer to store the JSON representation.
557/// * `buffer_size` - \[in\] The size of the provided buffer.
558/// * `write_size` - \[out\] A mutable pointer to the actual size of the written data.
559///
560/// # Returns
561///
562/// An integer representing the error code. `0` indicates success.
563///
564/// # Safety
565///
566/// This function is marked as unsafe due to the use of raw pointers.
567#[no_mangle]
568pub unsafe extern "C" fn ket_process_metadata_json(
569 process: &mut Process,
570 buffer: *mut u8,
571 buffer_size: usize,
572 write_size: &mut usize,
573) -> i32 {
574 let metadata = process.metadata();
575 let metadata = serde_json::to_string(&metadata).unwrap();
576 let metadata = metadata.as_bytes();
577 *write_size = metadata.len();
578
579 if buffer_size >= *write_size {
580 let buffer = unsafe { std::slice::from_raw_parts_mut(buffer, buffer_size) };
581 buffer[..*write_size].copy_from_slice(metadata);
582 }
583
584 KetError::Success.error_code()
585}