1use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
6
7use super::types::{
8 BQPComplexity, BellInequality, BlochVector, CSSCode, ChoiMatrix, Complex, Concurrence,
9 CvQuantumInfo, CvStateType, DensityMatrix, EntanglementMeasure, GateType, HolographicCode,
10 KrausChannel, MixedState, PPTCriterion, PureState, QMAComplexity, QccProtocol, QkdProtocol,
11 QuantumChannel, QuantumCircuit, QuantumDiscord, QuantumErrorMitigation, ResourceTheory,
12 StabilizerCode, StateDiscrimination, SurfaceCode, SyndromeDecoder,
13};
14
15pub fn app(f: Expr, a: Expr) -> Expr {
16 Expr::App(Box::new(f), Box::new(a))
17}
18pub fn app2(f: Expr, a: Expr, b: Expr) -> Expr {
19 app(app(f, a), b)
20}
21pub fn app3(f: Expr, a: Expr, b: Expr, c: Expr) -> Expr {
22 app(app2(f, a, b), c)
23}
24pub fn cst(s: &str) -> Expr {
25 Expr::Const(Name::str(s), vec![])
26}
27pub fn prop() -> Expr {
28 Expr::Sort(Level::zero())
29}
30pub fn type0() -> Expr {
31 Expr::Sort(Level::succ(Level::zero()))
32}
33pub fn pi(bi: BinderInfo, name: &str, dom: Expr, body: Expr) -> Expr {
34 Expr::Pi(bi, Name::str(name), Box::new(dom), Box::new(body))
35}
36pub fn arrow(a: Expr, b: Expr) -> Expr {
37 pi(BinderInfo::Default, "_", a, b)
38}
39pub fn bvar(n: u32) -> Expr {
40 Expr::BVar(n)
41}
42pub fn nat_ty() -> Expr {
43 cst("Nat")
44}
45pub fn real_ty() -> Expr {
46 cst("Real")
47}
48pub fn bool_ty() -> Expr {
49 cst("Bool")
50}
51pub fn list_ty(elem: Expr) -> Expr {
52 app(cst("List"), elem)
53}
54pub fn density_matrix_ty() -> Expr {
57 arrow(nat_ty(), type0())
58}
59pub fn pure_state_ty() -> Expr {
62 arrow(nat_ty(), type0())
63}
64pub fn mixed_state_ty() -> Expr {
67 arrow(nat_ty(), type0())
68}
69pub fn bloch_vector_ty() -> Expr {
72 type0()
73}
74pub fn von_neumann_entropy_ty() -> Expr {
77 arrow(app(cst("DensityMatrix"), nat_ty()), real_ty())
78}
79pub fn purity_ty() -> Expr {
82 arrow(app(cst("DensityMatrix"), nat_ty()), real_ty())
83}
84pub fn entropy_zero_iff_pure_ty() -> Expr {
86 prop()
87}
88pub fn purity_one_iff_pure_ty() -> Expr {
90 prop()
91}
92pub fn quantum_channel_ty() -> Expr {
95 arrow(nat_ty(), arrow(nat_ty(), type0()))
96}
97pub fn kraus_representation_ty() -> Expr {
100 arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), type0())))
101}
102pub fn choi_matrix_ty() -> Expr {
105 arrow(nat_ty(), arrow(nat_ty(), type0()))
106}
107pub fn depolarizing_channel_ty() -> Expr {
110 arrow(
111 nat_ty(),
112 arrow(real_ty(), app2(cst("QuantumChannel"), nat_ty(), nat_ty())),
113 )
114}
115pub fn diamond_norm_ty() -> Expr {
118 arrow(app2(cst("QuantumChannel"), nat_ty(), nat_ty()), real_ty())
119}
120pub fn choi_kraus_isomorphism_ty() -> Expr {
122 prop()
123}
124pub fn stinespring_dilation_ty() -> Expr {
126 prop()
127}
128pub fn entanglement_measure_ty() -> Expr {
131 arrow(nat_ty(), arrow(nat_ty(), type0()))
132}
133pub fn concurrence_ty() -> Expr {
136 arrow(app(cst("DensityMatrix"), cst("Nat.four")), real_ty())
137}
138pub fn partial_transpose_ty() -> Expr {
141 arrow(
142 nat_ty(),
143 arrow(
144 nat_ty(),
145 arrow(
146 app(
147 cst("DensityMatrix"),
148 app2(cst("Nat.mul"), nat_ty(), nat_ty()),
149 ),
150 app(
151 cst("DensityMatrix"),
152 app2(cst("Nat.mul"), nat_ty(), nat_ty()),
153 ),
154 ),
155 ),
156 )
157}
158pub fn ppt_criterion_ty() -> Expr {
161 arrow(app(cst("DensityMatrix"), nat_ty()), prop())
162}
163pub fn entanglement_of_formation_ty() -> Expr {
166 arrow(app(cst("DensityMatrix"), cst("Nat.four")), real_ty())
167}
168pub fn ppt_necessary_ty() -> Expr {
170 prop()
171}
172pub fn ppt_sufficient_low_dim_ty() -> Expr {
174 prop()
175}
176pub fn stabilizer_code_ty() -> Expr {
179 arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), type0())))
180}
181pub fn css_code_ty() -> Expr {
184 arrow(nat_ty(), arrow(nat_ty(), type0()))
185}
186pub fn surface_code_ty() -> Expr {
189 arrow(nat_ty(), type0())
190}
191pub fn syndrome_decoder_ty() -> Expr {
194 arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), type0())))
195}
196pub fn stabilizer_distance_ty() -> Expr {
199 arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), nat_ty())))
200}
201pub fn quantum_singleton_bound_ty() -> Expr {
203 prop()
204}
205pub fn knill_laflamme_ty() -> Expr {
208 prop()
209}
210pub fn bqp_complexity_ty() -> Expr {
214 type0()
215}
216pub fn qma_complexity_ty() -> Expr {
219 type0()
220}
221pub fn quantum_circuit_complexity_ty() -> Expr {
224 arrow(nat_ty(), type0())
225}
226pub fn t_gate_count_ty() -> Expr {
229 arrow(nat_ty(), arrow(nat_ty(), nat_ty()))
230}
231pub fn clifford_plus_t_ty() -> Expr {
234 type0()
235}
236pub fn bqp_in_pspace_ty() -> Expr {
238 prop()
239}
240pub fn p_in_bqp_ty() -> Expr {
242 prop()
243}
244pub fn solovay_kitaev_ty() -> Expr {
247 prop()
248}
249pub fn build_quantum_information_env(env: &mut Environment) -> Result<(), String> {
251 let axioms: &[(&str, Expr)] = &[
252 ("DensityMatrix", density_matrix_ty()),
253 ("PureState", pure_state_ty()),
254 ("MixedState", mixed_state_ty()),
255 ("BlochVector", bloch_vector_ty()),
256 ("VonNeumannEntropy", von_neumann_entropy_ty()),
257 ("Purity", purity_ty()),
258 ("EntropyZeroIffPure", entropy_zero_iff_pure_ty()),
259 ("PurityOneIffPure", purity_one_iff_pure_ty()),
260 ("Nat.four", nat_ty()),
261 ("Nat.mul", arrow(nat_ty(), arrow(nat_ty(), nat_ty()))),
262 ("QuantumChannel", quantum_channel_ty()),
263 ("KrausRepresentation", kraus_representation_ty()),
264 ("ChoiMatrix", choi_matrix_ty()),
265 ("DepolarizingChannel", depolarizing_channel_ty()),
266 ("DiamondNorm", diamond_norm_ty()),
267 ("ChoiKrausIsomorphism", choi_kraus_isomorphism_ty()),
268 ("StinespringDilation", stinespring_dilation_ty()),
269 ("EntanglementMeasure", entanglement_measure_ty()),
270 ("Concurrence", concurrence_ty()),
271 ("PartialTranspose", partial_transpose_ty()),
272 ("PPTCriterion", ppt_criterion_ty()),
273 ("EntanglementOfFormation", entanglement_of_formation_ty()),
274 ("PPTNecessary", ppt_necessary_ty()),
275 ("PPTSufficientLowDim", ppt_sufficient_low_dim_ty()),
276 ("StabilizerCode", stabilizer_code_ty()),
277 ("CSSCode", css_code_ty()),
278 ("SurfaceCode", surface_code_ty()),
279 ("SyndromeDecoder", syndrome_decoder_ty()),
280 ("StabilizerDistance", stabilizer_distance_ty()),
281 ("QuantumSingletonBound", quantum_singleton_bound_ty()),
282 ("KnillLaflamme", knill_laflamme_ty()),
283 ("BQPComplexity", bqp_complexity_ty()),
284 ("QMAComplexity", qma_complexity_ty()),
285 ("QuantumCircuitComplexity", quantum_circuit_complexity_ty()),
286 ("TGateCount", t_gate_count_ty()),
287 ("CliffordPlusT", clifford_plus_t_ty()),
288 ("BQPInPSPACE", bqp_in_pspace_ty()),
289 ("PInBQP", p_in_bqp_ty()),
290 ("SolovayKitaev", solovay_kitaev_ty()),
291 ];
292 for (name, ty) in axioms {
293 env.add(Declaration::Axiom {
294 name: Name::str(*name),
295 univ_params: vec![],
296 ty: ty.clone(),
297 })
298 .map_err(|e| format!("Failed to add '{}': {:?}", name, e))?;
299 }
300 Ok(())
301}
302#[cfg(test)]
303mod tests {
304 use super::*;
305 #[test]
306 fn test_density_matrix_pure() {
307 let psi = PureState::zero_state();
308 let rho = DensityMatrix::from_pure_state(&psi);
309 assert!(rho.is_pure());
310 assert!((rho.purity() - 1.0).abs() < 1e-9);
311 }
312 #[test]
313 fn test_density_matrix_mixed() {
314 let rho = DensityMatrix::maximally_mixed(2);
315 assert!(!rho.is_pure());
316 assert!((rho.purity() - 0.5).abs() < 1e-9);
317 }
318 #[test]
319 fn test_von_neumann_entropy() {
320 let psi = PureState::zero_state();
321 let rho_pure = DensityMatrix::from_pure_state(&psi);
322 assert!(rho_pure.von_neumann_entropy() < 1e-9);
323 let rho_mix = DensityMatrix::maximally_mixed(2);
324 assert!((rho_mix.von_neumann_entropy() - 1.0).abs() < 1e-9);
325 }
326 #[test]
327 fn test_bloch_vector() {
328 let psi = PureState::zero_state();
329 let rho = DensityMatrix::from_pure_state(&psi);
330 let bv = BlochVector::from_density_matrix(&rho);
331 assert!((bv.z - 1.0).abs() < 1e-9);
332 assert!(bv.x.abs() < 1e-9);
333 assert!(bv.y.abs() < 1e-9);
334 assert!(bv.is_valid());
335 let rho_mix = DensityMatrix::maximally_mixed(2);
336 let bv_mix = BlochVector::from_density_matrix(&rho_mix);
337 assert!(bv_mix.x.abs() < 1e-9);
338 assert!(bv_mix.y.abs() < 1e-9);
339 assert!(bv_mix.z.abs() < 1e-9);
340 }
341 #[test]
342 fn test_depolarizing_channel() {
343 let ch = KrausChannel::depolarizing(2, 0.0);
344 let psi = PureState::zero_state();
345 let rho = DensityMatrix::from_pure_state(&psi);
346 let out = ch.apply(&rho);
347 assert!((out.get(0, 0).re - 1.0).abs() < 1e-9);
348 assert!(out.get(1, 1).re.abs() < 1e-9);
349 }
350 #[test]
351 fn test_channel_unitary() {
352 let eye: Vec<Complex> = vec![
353 Complex::one(),
354 Complex::zero(),
355 Complex::zero(),
356 Complex::one(),
357 ];
358 let ch = KrausChannel::new(2, 2, vec![eye]);
359 assert!(ch.is_unitary());
360 let dep = KrausChannel::depolarizing(2, 0.1);
361 assert!(!dep.is_unitary());
362 }
363 #[test]
364 fn test_partial_transpose_separable() {
365 let psi = PureState::basis(2, 0);
366 let rho_a = DensityMatrix::from_pure_state(&psi);
367 let rho_b = DensityMatrix::maximally_mixed(2);
368 let mut data = vec![Complex::zero(); 16];
369 for i in 0..2 {
370 for j in 0..2 {
371 for k in 0..2 {
372 for l in 0..2 {
373 let idx = (i * 2 + k) * 4 + (j * 2 + l);
374 data[idx] = rho_a.get(i, j).mul(rho_b.get(k, l));
375 }
376 }
377 }
378 }
379 let rho_prod = DensityMatrix { dim: 4, data };
380 assert!(rho_prod.is_ppt(2, 2));
381 }
382 #[test]
383 fn test_stabilizer_code_steane() {
384 let code = StabilizerCode::steane_code();
385 assert_eq!(code.n, 7);
386 assert_eq!(code.k, 1);
387 assert_eq!(code.d, 3);
388 let x_err = vec![0u8; 7];
389 let z_err = vec![0u8; 7];
390 let synd = code.syndrome(&x_err, &z_err);
391 assert!(synd.iter().all(|&s| s == 0));
392 let mut x_err1 = vec![0u8; 7];
393 x_err1[0] = 1;
394 assert!(code.detect_errors(&x_err1, &[0u8; 7]));
395 assert!(code.satisfies_singleton_bound());
396 }
397 #[test]
398 fn test_stabilizer_decoder() {
399 let code = StabilizerCode::steane_code();
400 let decoder = SyndromeDecoder::new(code);
401 let mut x_err = vec![0u8; 7];
402 x_err[1] = 1;
403 let z_err = vec![0u8; 7];
404 let synd = decoder.code.syndrome(&x_err, &z_err);
405 let (rec_x, _rec_z) = decoder.decode(&synd);
406 assert_eq!(rec_x, x_err);
407 }
408 #[test]
409 fn test_surface_code() {
410 let sc = SurfaceCode::new(3);
411 assert_eq!(sc.distance(), 3);
412 assert_eq!(sc.num_logical_qubits(), 1);
413 }
414 #[test]
415 fn test_quantum_circuit_complexity() {
416 let mut circ = QuantumCircuit::new(2);
417 circ.add_gate(GateType::H, vec![0]);
418 circ.add_gate(GateType::T, vec![1]);
419 circ.add_gate(GateType::Cnot, vec![0, 1]);
420 circ.add_gate(GateType::T, vec![0]);
421 assert_eq!(circ.gate_count(), 4);
422 assert_eq!(circ.t_gate_count(), 2);
423 assert_eq!(circ.clifford_count(), 2);
424 }
425 #[test]
426 fn test_bqp_qma() {
427 assert!(BQPComplexity::factoring_in_bqp());
428 assert!(BQPComplexity::search_in_bqp());
429 assert!(QMAComplexity::local_hamiltonian_is_qma_complete());
430 let qma = QMAComplexity::standard();
431 assert!(qma.completeness > qma.soundness);
432 }
433 #[test]
434 fn test_build_quantum_information_env() {
435 let mut env = oxilean_kernel::Environment::new();
436 let result = build_quantum_information_env(&mut env);
437 assert!(
438 result.is_ok(),
439 "build_quantum_information_env failed: {:?}",
440 result.err()
441 );
442 }
443}
444#[allow(dead_code)]
446pub fn entanglement_measures_comparison() -> Vec<(&'static str, &'static str, bool)> {
447 vec![
448 (
449 "Entanglement entropy",
450 "S(rho_A) = -Tr(rho_A log rho_A) for pure states",
451 false,
452 ),
453 ("Entanglement of formation", "E_F = min convex hull S", true),
454 (
455 "Concurrence",
456 "C = max(0, lambda1-lambda2-lambda3-lambda4) for 2 qubits",
457 true,
458 ),
459 ("Squashed entanglement", "Esq = inf over extensions", false),
460 (
461 "Entanglement cost",
462 "Rate for preparing rho from singlets",
463 false,
464 ),
465 (
466 "Distillable entanglement",
467 "Rate for extracting singlets from rho",
468 false,
469 ),
470 (
471 "Relative entropy of entanglement",
472 "min over sep states D(rho||sigma)",
473 true,
474 ),
475 ("Negativity", "N = (||rho^T_A||_1 - 1)/2", true),
476 (
477 "Geometric measure",
478 "E_G = -log max|<psi|phi_prod>|^2",
479 false,
480 ),
481 (
482 "Robustness of entanglement",
483 "min s: (rho+s*sigma)/(1+s) sep",
484 true,
485 ),
486 ]
487}
488#[cfg(test)]
489mod qi_ext_tests {
490 use super::*;
491 #[test]
492 fn test_state_discrimination() {
493 let p_e = StateDiscrimination::helstrom_bound_two_states(0.5, 0.5);
494 assert!((p_e - 0.5).abs() < 1e-10);
495 }
496 #[test]
497 fn test_quantum_discord() {
498 let qd = QuantumDiscord::new("Bell state", 1.0, 0.0);
499 assert!((qd.discord_value() - 1.0).abs() < 1e-10);
500 assert!(!qd.is_zero_discord());
501 }
502 #[test]
503 fn test_cv_gaussian() {
504 let cv = CvQuantumInfo::new(1, CvStateType::Coherent);
505 assert!(cv.is_gaussian());
506 assert!(cv.wigner_function_nonnegative());
507 }
508 #[test]
509 fn test_qkd_protocols() {
510 let bb84 = QkdProtocol::bb84();
511 assert!(!bb84.uses_entanglement);
512 assert!(bb84.is_unconditionally_secure());
513 let e91 = QkdProtocol::e91();
514 assert!(e91.uses_entanglement);
515 }
516 #[test]
517 fn test_error_mitigation() {
518 let zne = QuantumErrorMitigation::zne(3.0);
519 assert!(zne.is_exact_in_limit());
520 }
521 #[test]
522 fn test_entanglement_measures_nonempty() {
523 let measures = entanglement_measures_comparison();
524 assert!(!measures.is_empty());
525 }
526}
527#[cfg(test)]
528mod qi_comm_tests {
529 use super::*;
530 #[test]
531 fn test_bell_chsh() {
532 let chsh = BellInequality::chsh();
533 assert!((chsh.classical_bound - 2.0).abs() < 1e-10);
534 assert!((chsh.quantum_bound - 2.0 * 2.0_f64.sqrt()).abs() < 1e-10);
535 assert!(chsh.quantum_violation_ratio() > 1.0);
536 }
537 #[test]
538 fn test_qcc_equality() {
539 let eq = QccProtocol::equality_function();
540 assert!(eq.quantum_advantage_factor() > 1.0);
541 assert!(eq.has_exponential_gap);
542 }
543}
544#[cfg(test)]
545mod resource_theory_tests {
546 use super::*;
547 #[test]
548 fn test_resource_theories() {
549 let ent = ResourceTheory::entanglement();
550 assert!(!ent.free_states.is_empty());
551 let coh = ResourceTheory::coherence();
552 assert!(!coh.monotone.is_empty());
553 let magic = ResourceTheory::magic_states();
554 assert!(!magic.asymptotic_rate_description().is_empty());
555 }
556}
557#[cfg(test)]
558mod holographic_qec_tests {
559 use super::*;
560 #[test]
561 fn test_holographic_code() {
562 let hc = HolographicCode::happy_code(2);
563 assert!(hc.encoding_rate() > 0.0);
564 assert!(hc.is_isometric());
565 assert!(!hc.ryu_takayanagi_formula().is_empty());
566 }
567}