qudit_inst/numerical/
instantiation.rs1use std::sync::Arc;
2
3use qudit_circuit::QuditCircuit;
4use qudit_core::ComplexScalar;
5use qudit_core::RealScalar;
6
7use super::Problem;
8use super::Runner;
9use crate::DataMap;
10use crate::Instantiater;
11use crate::InstantiationResult;
12use crate::InstantiationTarget;
13
14pub trait InstantiationProblem<R: RealScalar>: Problem {
15 fn from_instantiation(
16 circuit: Arc<QuditCircuit>,
17 target: Arc<InstantiationTarget<R::C>>,
18 data: Arc<DataMap>,
19 ) -> Self;
20}
21
22#[derive(Clone)]
23pub struct MinimizingInstantiater<R, P> {
24 runner: R,
25 _phantom: std::marker::PhantomData<P>,
26}
27
28impl<R, P> MinimizingInstantiater<R, P> {
29 pub fn new(runner: R) -> Self {
30 Self {
31 runner,
32 _phantom: std::marker::PhantomData::<P>,
33 }
34 }
35}
36
37impl<C, R, P> Instantiater<C> for MinimizingInstantiater<R, P>
38where
39 C: ComplexScalar,
40 P: InstantiationProblem<C::R>,
41 R: Runner<C::R, P>,
42{
43 fn instantiate(
44 &self,
45 circuit: Arc<QuditCircuit>,
46 target: Arc<InstantiationTarget<C>>,
47 data: Arc<DataMap>,
48 ) -> InstantiationResult<C> {
49 let problem = P::from_instantiation(circuit, target, data);
50 self.runner.run(problem).to_instantiation()
51 }
52}
53
54#[cfg(feature = "python")]
55mod python {
56 #![allow(non_snake_case)]
57 use crate::{
58 instantiater::python::{BoxedInstantiater, InstantiaterWrapper},
59 numerical::{
60 functions::HSProblem, initializers::Uniform, minimizers::LM, runners::MultiStartRunner,
61 },
62 python::PyInstantiationRegistrar,
63 };
64
65 use super::*;
66 use pyo3::prelude::*;
67
68 impl InstantiaterWrapper
69 for MinimizingInstantiater<MultiStartRunner<LM<f64>, Uniform<f64>>, HSProblem<f64>>
70 {
71 }
72
73 #[pyfunction]
74 fn DefaultInstantiater() -> BoxedInstantiater {
75 SequentialMultiStartInstantiater(8)
76 }
77
78 #[pyfunction]
79 #[pyo3(signature = (num_starts = 8))]
80 fn SequentialMultiStartInstantiater(num_starts: usize) -> BoxedInstantiater {
81 let minimizer = LM::default();
82 let initializer = Uniform::default();
83 let runner = MultiStartRunner {
84 minimizer,
85 guess_generator: initializer,
86 num_starts,
87 };
88 let instantiater = MinimizingInstantiater::<_, HSProblem<f64>>::new(runner);
89 BoxedInstantiater {
90 inner: Box::new(instantiater),
91 }
92 }
93
94 fn register(parent_module: &Bound<'_, PyModule>) -> PyResult<()> {
96 parent_module.add_function(wrap_pyfunction!(DefaultInstantiater, parent_module)?)?;
97 parent_module.add_function(wrap_pyfunction!(
98 SequentialMultiStartInstantiater,
99 parent_module
100 )?)?;
101 Ok(())
102 }
103 inventory::submit!(PyInstantiationRegistrar { func: register });
104}