sim_lib_interference_runtime/
solver.rs1use std::{any::Any, sync::Arc};
4
5use sim_kernel::{Cx, DefaultFactory, Error, Factory, Object, Result, Symbol, Value};
6use sim_lib_interference_core::{
7 InterferenceProblem, SamplingPlane, SamplingPolicy, SamplingThresholds, WorkBudget,
8};
9use sim_lib_interference_solve::ReferencePhasorSolver;
10use sim_lib_numbers_tensor::active_tensor_executor;
11
12use crate::StudyDescriptor;
13
14pub type InterferenceStudy = StudyDescriptor;
16
17#[derive(Clone, Copy, Debug)]
19pub struct SolveRequest<'a> {
20 problem: &'a InterferenceProblem,
21 plane: &'a SamplingPlane,
22 sampling_policy: SamplingPolicy,
23 sampling_thresholds: SamplingThresholds,
24 work_budget: WorkBudget,
25}
26
27impl<'a> SolveRequest<'a> {
28 pub fn new(
30 problem: &'a InterferenceProblem,
31 plane: &'a SamplingPlane,
32 sampling_policy: SamplingPolicy,
33 sampling_thresholds: SamplingThresholds,
34 work_budget: WorkBudget,
35 ) -> Self {
36 Self {
37 problem,
38 plane,
39 sampling_policy,
40 sampling_thresholds,
41 work_budget,
42 }
43 }
44
45 pub fn problem(self) -> &'a InterferenceProblem {
47 self.problem
48 }
49
50 pub fn plane(self) -> &'a SamplingPlane {
52 self.plane
53 }
54
55 pub fn sampling_policy(self) -> SamplingPolicy {
57 self.sampling_policy
58 }
59
60 pub fn sampling_thresholds(self) -> SamplingThresholds {
62 self.sampling_thresholds
63 }
64
65 pub fn work_budget(self) -> WorkBudget {
67 self.work_budget
68 }
69}
70
71pub trait StudySolver: Send + Sync + 'static {
73 fn solve(&self, cx: &mut Cx, request: &SolveRequest<'_>) -> Result<InterferenceStudy>;
75}
76
77#[derive(Clone)]
79pub struct SolverProvider {
80 solver: Arc<dyn StudySolver>,
81}
82
83impl SolverProvider {
84 pub fn new(solver: Arc<dyn StudySolver>) -> Self {
86 Self { solver }
87 }
88
89 pub fn solver(&self) -> Arc<dyn StudySolver> {
91 self.solver.clone()
92 }
93
94 pub fn into_value(self) -> Result<Value> {
96 DefaultFactory.opaque(Arc::new(self))
97 }
98}
99
100impl Object for SolverProvider {
101 fn display(&self, _cx: &mut Cx) -> Result<String> {
102 Ok("#<interference-study-solver>".to_owned())
103 }
104
105 fn as_any(&self) -> &dyn Any {
106 self
107 }
108}
109
110impl sim_kernel::ObjectCompat for SolverProvider {}
111
112pub fn study_solver_symbol() -> Symbol {
114 Symbol::qualified("interference", "study-solver")
115}
116
117pub fn tensor_study_solver_symbol() -> Symbol {
122 Symbol::qualified("interference", "tensor-study-solver")
123}
124
125pub fn resolve_study_solver(cx: &Cx) -> Result<Arc<dyn StudySolver>> {
132 if let Some(value) = cx.env().get(&study_solver_symbol()) {
133 return solver_from_value(&value, "active environment");
134 }
135 if active_tensor_executor(cx).is_some()
136 && let Some(value) = cx.registry().value_by_symbol(&tensor_study_solver_symbol())
137 {
138 return solver_from_value(value, "Tensor solver registry");
139 }
140 let value = cx
141 .registry()
142 .value_by_symbol(&study_solver_symbol())
143 .ok_or_else(|| Error::Eval(format!("no {} is installed", study_solver_symbol())))?;
144 solver_from_value(value, "runtime registry")
145}
146
147fn solver_from_value(value: &Value, source: &str) -> Result<Arc<dyn StudySolver>> {
148 value
149 .object()
150 .downcast_ref::<SolverProvider>()
151 .map(SolverProvider::solver)
152 .ok_or_else(|| {
153 Error::Eval(format!(
154 "{} in the {source} is not a SolverProvider",
155 study_solver_symbol()
156 ))
157 })
158}
159
160#[derive(Clone, Copy, Debug, Default)]
162pub struct ReferenceStudySolver;
163
164impl StudySolver for ReferenceStudySolver {
165 fn solve(&self, _cx: &mut Cx, request: &SolveRequest<'_>) -> Result<InterferenceStudy> {
166 let solver = ReferencePhasorSolver::new(
167 request.sampling_policy(),
168 request.sampling_thresholds(),
169 request.work_budget(),
170 );
171 let (field, evidence) =
172 solver
173 .solve(request.problem(), request.plane())
174 .map_err(|error| {
175 Error::Eval(format!("interference reference solve failed: {error}"))
176 })?;
177 StudyDescriptor::from_reference(request.problem(), *request.plane(), field, &evidence)
178 }
179}