1use crate::parser::model_transformer::Model;
2use crate::parser::model_transformer::TransformError;
3use crate::parser::pre_model::PreModel;
4#[allow(unused_imports)]
5use crate::prelude::*;
6use crate::primitives::Constant;
7use crate::runtime_builtin::RoocFunction;
8use crate::solvers::IntOrBoolValue;
9use crate::solvers::{
10 CanonicalTransformError, OptimalTableau, OptimalTableauWithSteps, SimplexError, Tableau,
11};
12use crate::solvers::{LpSolution, SolverError};
13use crate::transformers::LinearModel;
14use crate::transformers::LinearizationError;
15use crate::transformers::StandardLinearModel;
16use crate::utils::CompilationError;
17use crate::{MILPValue, RoocParser, match_pipe_data_to};
18use indexmap::IndexMap;
19use std::fmt::Display;
20
21#[derive(Debug, Clone)]
23pub enum PipeableData {
24 String(String),
25 Parser(RoocParser),
26 PreModel(PreModel),
27 Model(Model),
28 LinearModel(LinearModel),
29 StandardLinearModel(StandardLinearModel),
30 Tableau(Tableau),
31 OptimalTableau(OptimalTableau),
32 OptimalTableauWithSteps(OptimalTableauWithSteps),
33 BinarySolution(LpSolution<bool>),
34 IntegerBinarySolution(LpSolution<IntOrBoolValue>),
35 RealSolution(LpSolution<f64>),
36 MILPSolution(LpSolution<MILPValue>),
37}
38
39#[allow(clippy::result_large_err)]
40#[allow(clippy::wrong_self_convention)]
41impl PipeableData {
42 pub fn get_type(&self) -> PipeDataType {
44 match self {
45 PipeableData::String(_) => PipeDataType::String,
46 PipeableData::Parser(_) => PipeDataType::Parser,
47 PipeableData::Model(_) => PipeDataType::Model,
48 PipeableData::LinearModel(_) => PipeDataType::LinearModel,
49 PipeableData::StandardLinearModel(_) => PipeDataType::StandardLinearModel,
50 PipeableData::Tableau(_) => PipeDataType::Tableau,
51 PipeableData::PreModel(_) => PipeDataType::PreModel,
52 PipeableData::OptimalTableau(_) => PipeDataType::OptimalTableau,
53 PipeableData::OptimalTableauWithSteps(_) => PipeDataType::OptimalTableauWithSteps,
54 PipeableData::BinarySolution(_) => PipeDataType::BinarySolution,
55 PipeableData::IntegerBinarySolution(_) => PipeDataType::IntegerBinarySolution,
56 PipeableData::RealSolution(_) => PipeDataType::RealSolution,
57 PipeableData::MILPSolution(_) => PipeDataType::MILPSolution,
58 }
59 }
60 pub fn to_string_data(self) -> Result<String, PipeError> {
62 match_pipe_data_to!(self, String, String)
63 }
64 pub fn to_parser(self) -> Result<RoocParser, PipeError> {
65 match_pipe_data_to!(self, Parser, Parser)
66 }
67 pub fn to_pre_model(self) -> Result<PreModel, PipeError> {
68 match_pipe_data_to!(self, PreModel, PreModel)
69 }
70 pub fn to_model(self) -> Result<Model, PipeError> {
71 match_pipe_data_to!(self, Model, Model)
72 }
73 pub fn to_linear_model(self) -> Result<LinearModel, PipeError> {
74 match_pipe_data_to!(self, LinearModel, LinearModel)
75 }
76 pub fn to_standard_linear_model(self) -> Result<StandardLinearModel, PipeError> {
77 match_pipe_data_to!(self, StandardLinearModel, StandardLinearModel)
78 }
79 pub fn to_tableau(self) -> Result<Tableau, PipeError> {
80 match_pipe_data_to!(self, Tableau, Tableau)
81 }
82 pub fn to_optimal_tableau(self) -> Result<OptimalTableau, PipeError> {
83 match_pipe_data_to!(self, OptimalTableau, OptimalTableau)
84 }
85 pub fn to_optimal_tableau_with_steps(self) -> Result<OptimalTableauWithSteps, PipeError> {
86 match_pipe_data_to!(self, OptimalTableauWithSteps, OptimalTableauWithSteps)
87 }
88 pub fn to_binary_solution(self) -> Result<LpSolution<bool>, PipeError> {
89 match_pipe_data_to!(self, BinarySolution, BinarySolution)
90 }
91 pub fn to_real_solution(self) -> Result<LpSolution<f64>, PipeError> {
92 match_pipe_data_to!(self, RealSolution, RealSolution)
93 }
94 pub fn to_milp_solution(self) -> Result<LpSolution<MILPValue>, PipeError> {
95 match_pipe_data_to!(self, MILPSolution, MILPSolution)
96 }
97
98 pub fn to_integer_binary_solution(self) -> Result<LpSolution<IntOrBoolValue>, PipeError> {
99 match_pipe_data_to!(self, IntegerBinarySolution, IntegerBinarySolution)
100 }
101 pub fn as_string_data(&self) -> Result<&String, PipeError> {
102 match_pipe_data_to!(self, String, String)
103 }
104 pub fn as_binary_solution(&self) -> Result<&LpSolution<bool>, PipeError> {
105 match_pipe_data_to!(self, BinarySolution, BinarySolution)
106 }
107 pub fn as_integer_binary_solution(&self) -> Result<&LpSolution<IntOrBoolValue>, PipeError> {
108 match_pipe_data_to!(self, IntegerBinarySolution, IntegerBinarySolution)
109 }
110 pub fn as_real_solution(&self) -> Result<&LpSolution<f64>, PipeError> {
111 match_pipe_data_to!(self, RealSolution, RealSolution)
112 }
113
114 pub fn as_parser(&self) -> Result<&RoocParser, PipeError> {
115 match_pipe_data_to!(self, Parser, Parser)
116 }
117 pub fn as_pre_model(&self) -> Result<&PreModel, PipeError> {
118 match_pipe_data_to!(self, PreModel, PreModel)
119 }
120 pub fn as_model(&self) -> Result<&Model, PipeError> {
121 match_pipe_data_to!(self, Model, Model)
122 }
123 pub fn as_linear_model(&self) -> Result<&LinearModel, PipeError> {
124 match_pipe_data_to!(self, LinearModel, LinearModel)
125 }
126 pub fn as_standard_linear_model(&self) -> Result<&StandardLinearModel, PipeError> {
127 match_pipe_data_to!(self, StandardLinearModel, StandardLinearModel)
128 }
129 pub fn as_tableau(&self) -> Result<&Tableau, PipeError> {
130 match_pipe_data_to!(self, Tableau, Tableau)
131 }
132 pub fn as_optimal_tableau(&self) -> Result<&OptimalTableau, PipeError> {
133 match_pipe_data_to!(self, OptimalTableau, OptimalTableau)
134 }
135}
136
137impl Display for PipeableData {
138 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
139 match self {
140 PipeableData::String(s) => write!(f, "{}", s),
141 PipeableData::Parser(p) => write!(f, "{}", p.source),
142 PipeableData::PreModel(p) => write!(f, "{}", p),
143 PipeableData::Model(m) => write!(f, "{}", m),
144 PipeableData::LinearModel(m) => write!(f, "{}", m),
145 PipeableData::StandardLinearModel(m) => write!(f, "{}", m),
146 PipeableData::Tableau(t) => write!(f, "{}", t),
147 PipeableData::OptimalTableau(t) => write!(f, "{}", t),
148 PipeableData::OptimalTableauWithSteps(t) => write!(f, "{}", t),
149 PipeableData::BinarySolution(s) => write!(f, "{}", s),
150 PipeableData::IntegerBinarySolution(s) => write!(f, "{}", s),
151 PipeableData::RealSolution(s) => write!(f, "{}", s),
152 PipeableData::MILPSolution(s) => write!(f, "{}", s),
153 }
154 }
155}
156
157#[cfg_attr(target_arch = "wasm32", wasm_bindgen)]
158#[derive(Debug)]
159pub enum PipeDataType {
161 String,
162 Parser,
163 PreModel,
164 Model,
165 LinearModel,
166 StandardLinearModel,
167 Tableau,
168 OptimalTableau,
169 OptimalTableauWithSteps,
170 BinarySolution,
171 IntegerBinarySolution,
172 RealSolution,
173 MILPSolution,
174}
175impl Display for PipeDataType {
176 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
177 let s = match self {
178 PipeDataType::String => "String".to_string(),
179 PipeDataType::Parser => "Parser".to_string(),
180 PipeDataType::PreModel => "PreModel".to_string(),
181 PipeDataType::Model => "Model".to_string(),
182 PipeDataType::LinearModel => "LinearModel".to_string(),
183 PipeDataType::StandardLinearModel => "StandardLinearModel".to_string(),
184 PipeDataType::Tableau => "Tableau".to_string(),
185 PipeDataType::OptimalTableau => "OptimalTableau".to_string(),
186 PipeDataType::OptimalTableauWithSteps => "OptimalTableauWithSteps".to_string(),
187 PipeDataType::BinarySolution => "BinarySolution".to_string(),
188 PipeDataType::IntegerBinarySolution => "IntegerBinarySolution".to_string(),
189 PipeDataType::RealSolution => "RealSolution".to_string(),
190 PipeDataType::MILPSolution => "MILPSolution".to_string(),
191 };
192
193 f.write_str(&s)
194 }
195}
196
197#[derive(Debug)]
198pub enum PipeError {
199 EmptyPipeData,
200 InvalidData {
201 expected: PipeDataType,
202 got: PipeDataType,
203 },
204 CompilationError {
205 error: CompilationError,
206 source: String,
207 },
208 TransformError {
209 error: TransformError,
210 source: String,
211 },
212 LinearizationError(LinearizationError),
213 StandardizationError(SolverError),
214 CanonicalizationError(CanonicalTransformError),
215 StepByStepSimplexError(SimplexError, Tableau),
216 SolverError(SolverError),
217 Other(String),
218}
219impl Display for PipeError {
220 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
221 match self {
222 PipeError::EmptyPipeData => write!(f, "Pipe data is empty"),
223 PipeError::InvalidData { expected, got } => {
224 write!(
225 f,
226 "Expected data of type \"{}\" but got \"{}\"",
227 expected, got
228 )
229 }
230 PipeError::Other(s) => write!(f, "{}", s),
231 PipeError::CompilationError { error, source } => {
232 write!(f, "{}", error.to_string_from_source(source))
233 }
234 PipeError::TransformError { error, source } => match error.trace_from_source(source) {
235 Ok(trace) => write!(f, "{}", trace),
236 Err(_) => write!(f, "{}", error.traced_error()),
237 },
238 PipeError::LinearizationError(e) => write!(f, "{}", e),
239 PipeError::StandardizationError(e) => write!(f, "{}", e),
240 PipeError::CanonicalizationError(e) => write!(f, "{}", e),
241 PipeError::StepByStepSimplexError(e, _) => write!(f, "{}", e),
242 PipeError::SolverError(e) => write!(f, "{}", e),
243 }
244 }
245}
246
247pub struct PipeContext<'a> {
251 functions: &'a IndexMap<String, Box<dyn RoocFunction>>,
252 constants: Vec<Constant>,
253}
254impl PipeContext<'_> {
255 pub fn new(
256 constants: Vec<Constant>,
257 fns: &IndexMap<String, Box<dyn RoocFunction>>,
258 ) -> PipeContext<'_> {
259 PipeContext {
260 constants,
261 functions: fns,
262 }
263 }
264 pub fn constants(&self) -> &Vec<Constant> {
265 &self.constants
266 }
267 pub fn functions(&self) -> &IndexMap<String, Box<dyn RoocFunction>> {
268 self.functions
269 }
270}
271
272pub trait Pipeable {
273 #[allow(clippy::result_large_err)]
275 fn pipe(
276 &self,
277 data: &mut PipeableData,
278 pipe_context: &PipeContext,
279 ) -> Result<PipeableData, PipeError>;
280}