flag_algebra/
sdpa.rs

1use std::fmt::Display;
2use std::io;
3use std::num::{ParseFloatError, ParseIntError};
4use std::result::Result;
5use std::str::FromStr;
6use thiserror::Error;
7
8// A line in a .sdpa format
9#[derive(Debug, Clone, Copy)]
10pub struct SdpaCoeff {
11    pub mat: usize,
12    pub block: usize,
13    pub i: usize,
14    pub j: usize,
15    pub val: f64,
16}
17
18#[derive(Error, Debug)]
19pub enum Error {
20    #[error("Error while parsing matrix coefficient: {0}")]
21    ParseError(String),
22    #[error("{0}")]
23    Io(#[from] io::Error),
24    #[error("Solver returned with code {0}")]
25    SdpNotSolved(i32),
26}
27
28use Error::*;
29
30impl From<ParseIntError> for Error {
31    fn from(e: ParseIntError) -> Self {
32        ParseError(format!("{e}"))
33    }
34}
35
36impl From<ParseFloatError> for Error {
37    fn from(e: ParseFloatError) -> Self {
38        ParseError(format!("{e}"))
39    }
40}
41
42impl FromStr for SdpaCoeff {
43    type Err = Error;
44
45    fn from_str(s: &str) -> Result<Self, Self::Err> {
46        let mut iter = s.split_whitespace();
47        let mut next = || {
48            iter.next()
49                .ok_or_else(|| ParseError("Less than 5 elements".into()))
50        };
51        let result = SdpaCoeff {
52            mat: next()?.parse()?,
53            block: next()?.parse()?,
54            i: next()?.parse()?,
55            j: next()?.parse()?,
56            val: next()?.parse()?,
57        };
58        if iter.next().is_some() {
59            return Err(ParseError("Less than 5 elements".into()));
60        };
61        Ok(result)
62    }
63}
64
65impl Display for SdpaCoeff {
66    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
67        write!(
68            f,
69            "{} {} {} {} {}",
70            self.mat, self.block, self.i, self.j, self.val
71        )
72    }
73}