use crate::{algebra::*, solver::*};
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use std::io::Write;
use std::{fs::File, io, io::Read};
#[derive(Serialize, Deserialize)]
#[serde(bound = "T: Serialize + DeserializeOwned")]
struct JsonProblemData<T: FloatT> {
pub P: CscMatrix<T>,
pub q: Vec<T>,
pub A: CscMatrix<T>,
pub b: Vec<T>,
pub cones: Vec<SupportedConeT<T>>,
#[serde(default)]
pub settings: DefaultSettings<T>,
}
impl<T> SolverJSONReadWrite<T> for DefaultSolver<T>
where
T: FloatT + DeserializeOwned + Serialize,
{
fn save_to_file(&self, file: &mut File) -> Result<(), io::Error> {
let mut json_data = JsonProblemData {
P: self.data.P.clone(),
q: self.data.q.clone(),
A: self.data.A.clone(),
b: self.data.b.clone(),
cones: self.data.cones.clone(),
settings: self.settings.clone(),
};
let dinv = &self.data.equilibration.dinv;
let einv = &self.data.equilibration.einv;
let c = &self.data.equilibration.c;
json_data.P.lrscale(dinv, dinv);
json_data.q.hadamard(dinv);
json_data.P.scale(c.recip());
json_data.q.scale(c.recip());
json_data.A.lrscale(einv, dinv);
json_data.b.hadamard(einv);
sanitize_settings(&mut json_data.settings);
let json = serde_json::to_string(&json_data)?;
file.write_all(json.as_bytes())?;
Ok(())
}
fn load_from_file(
file: &mut File,
settings: Option<DefaultSettings<T>>,
) -> Result<Self, SolverError> {
let mut buffer = String::new();
file.read_to_string(&mut buffer)?;
let json_data: Result<JsonProblemData<T>, _> = serde_json::from_str(&buffer);
let mut json_data = match json_data {
Ok(data) => data,
Err(e) => {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
format!("JSON parsing error: {}", e),
)
.into())
}
};
desanitize_settings(&mut json_data.settings);
let P = json_data.P;
let q = json_data.q;
let A = json_data.A;
let b = json_data.b;
let cones = json_data.cones;
let settings = settings.unwrap_or(json_data.settings);
Self::new(&P, &q, &A, &b, &cones, settings)
}
}
fn sanitize_settings<T: FloatT>(settings: &mut DefaultSettings<T>) {
if settings.time_limit == f64::INFINITY {
settings.time_limit = f64::MAX;
}
}
fn desanitize_settings<T: FloatT>(settings: &mut DefaultSettings<T>) {
if settings.time_limit == f64::MAX {
settings.time_limit = f64::INFINITY;
}
}