solutionquality/
solutionquality.rs1extern crate mosek;
9
10use mosek::{Task,Streamtype,Solsta,Soltype};
11use std::env;
12
13enum FileOrText {
14 File(String),
15 Text(String)
16}
17
18fn main() -> Result<(),String> {
19 let mut args = env::args();
20 if args.len() < 2 {
21 println!("Syntax: solutionquality FILENAME");
22 return Err("Invalid argument list".to_string())
23 }
24 let _ = args.next();
25 let filename = args.next().unwrap();
26 solutionquality(FileOrText::File(filename))
27}
28
29fn solutionquality(filename : FileOrText) -> Result<(),String> {
30 let mut task = Task::new().unwrap().with_callbacks();
31 task.put_stream_callback(Streamtype::LOG, |msg| print!("{}",msg))?;
32 match filename {
35 FileOrText::File(filename) => task.read_data (filename.as_str())?,
36 FileOrText::Text(data) => task.read_ptf_string(data.as_str())?
37 }
38
39 let _ = task.optimize()?;
41
42 task.solution_summary(Streamtype::LOG)?;
43
44 let solsta = task.get_sol_sta(Soltype::BAS)?;
45
46 let mut pobj : f64 = 0.0;
47 let mut pviolcon : f64 = 0.0;
48 let mut pviolvar : f64 = 0.0;
49 let mut pviolbarvar : f64 = 0.0;
50 let mut pviolcones : f64 = 0.0;
51 let mut pviolitg : f64 = 0.0;
52 let mut dobj : f64 = 0.0;
53 let mut dviolcon : f64 = 0.0;
54 let mut dviolvar : f64 = 0.0;
55 let mut dviolbarvar : f64 = 0.0;
56 let mut dviolcones : f64 = 0.0;
57
58 task.get_solution_info(Soltype::BAS,
59 & mut pobj, & mut pviolcon, & mut pviolvar, & mut pviolbarvar, & mut pviolcones, & mut pviolitg,
60 & mut dobj, & mut dviolcon, & mut dviolvar, & mut dviolbarvar, & mut dviolcones)?;
61 match solsta {
62 Solsta::OPTIMAL => {
63 let abs_obj_gap = (dobj-pobj).abs();
64 let rel_obj_gap = abs_obj_gap / (1.0 + f64::min(pobj.abs(), dobj.abs()));
65 let max_primal_viol = f64::max(pviolcon, pviolvar);
66 let max_primal_viol = f64::max(max_primal_viol , pviolbarvar);
67 let max_primal_viol = f64::max(max_primal_viol , pviolcones);
68
69 let max_dual_viol = f64::max(dviolcon, dviolvar);
70 let max_dual_viol = f64::max(max_dual_viol, dviolbarvar);
71 let max_dual_viol = f64::max(max_dual_viol, dviolcones);
72
73 println!("Customized solution information.");
78 println!(" Absolute objective gap: {:.3e}", abs_obj_gap);
79 println!(" Relative objective gap: {:.3e}", rel_obj_gap);
80 println!(" Max primal violation : {:.3e}", max_primal_viol);
81 println!(" Max dual violation : {:.3e}", max_dual_viol);
82
83 let mut accepted = true;
84
85 if rel_obj_gap > 1e-6 {
86 println!("Warning: The relative objective gap is LARGE.");
87 accepted = false;
88 }
89
90 if max_primal_viol > 1e-8 {
94 println!("Warning: Primal violation is too LARGE");
95 accepted = false;
96 }
97
98 if max_dual_viol > 1e-6 {
99 println!("Warning: Dual violation is too LARGE.");
100 accepted = false;
101 }
102
103 if accepted {
104 let numvar = task.get_num_var()?;
105 println!("Optimal primal solution");
106 let mut xx = vec![0.0; numvar as usize];
107 task.get_xx(Soltype::BAS,xx.as_mut_slice())?;
108 for (j,&xj) in (0..numvar).zip(xx.iter()) {
109 println!("x[{}]: {}",j,xj);
110 }
111 } else {
112 task.analyze_solution(Streamtype::LOG, Soltype::BAS)?;
114 }
115 },
116 Solsta::DUAL_INFEAS_CER => println!("Primal or dual infeasibility certificate found."),
117 Solsta::UNKNOWN => println!("The status of the solution is unknown."),
118 _ => println!("Other solution status"),
119 }
120 Ok(())
121}
122
123
124#[cfg(test)]
125mod tests {
126
127 const DFLT_FILE : &str = "Task
128Objective
129 Maximize + 3 @x0 + @x1 + 5 @x2 + @x3
130Constraints
131 @c0 [30] + 3 @x0 + @x1 + 2 @x2
132 @c1 [15;+inf] + 2 @x0 + @x1 + 3 @x2 + @x3
133 @c2 [-inf;25] + 2 @x1 + 3 @x3
134Variables
135 @x0 [0;+inf]
136 @x1 [0;10]
137 @x2 [0;+inf]
138 @x3 [0;+inf]
139";
140
141 #[test]
142 fn test() {
143 super::solutionquality(super::FileOrText::Text(DFLT_FILE.to_string())).unwrap();
144 }
145}