flag_algebra/tools/
reduction.rs1use crate::flag::Flag;
4use crate::sdp::*;
5use crate::tools::*;
6use log::*;
7use sprs::CsMat;
8
9#[derive(Debug, Clone)]
11pub struct FlagSolver<F: Flag> {
12 pb: Problem<f64, F>,
13 name: String,
14 pub optimal_value: Option<f64>,
15 select: Selector,
17 select_sdpa_file: Option<Selector>,
19 select_certificate_file: Option<Selector>,
21 protected: Vec<bool>,
22}
23
24impl<F> FlagSolver<F>
25where
26 F: Flag,
27{
28 pub fn new<S: Into<String>>(pb: Problem<f64, F>, name: S) -> Self {
30 Self {
31 protected: vec![false; pb.ineqs.len()],
32 select: Selector::new(&pb), name: name.into(),
34 pb,
35 optimal_value: None,
36 select_sdpa_file: None,
37 select_certificate_file: None,
38 }
39 }
40 pub fn protect(mut self, i: usize) -> Self {
42 self.protected[i] = true;
43 self
44 }
45 fn write_sdpa(&mut self, select: Selector) {
46 self.pb
47 .view(&select)
48 .write_sdpa(&self.name)
49 .expect("Cannot write sdpa file");
50 self.select_sdpa_file = Some(select);
51 }
52 fn run_csdp(&mut self) -> Result<f64, ()> {
53 match self.select_sdpa_file.take() {
54 Some(select) => {
55 self.select_certificate_file = Some(select);
56 match self.pb.run_csdp(&self.name, None, false) {
57 Ok(v) => Ok(v),
58 Err(crate::sdpa::Error::SdpNotSolved(_)) => Err(()),
59 Err(e) => panic!("Failed to run csdp {e}"),
60 }
61 }
62 None => panic!("No problem to solve"),
63 }
64 }
65 pub fn init(&mut self) {
66 self.write_sdpa(self.select.clone());
67 self.optimal_value = Some(self.run_csdp().expect("Cannot find initial solution"))
68 }
69 fn use_certificate(&mut self) {
70 self.select = self
71 .select
72 .refine_with_certificate(&self.load_certificate(), &self.protected)
73 }
74 pub fn run(&mut self, select: Selector) -> Result<(), String> {
75 self.write_sdpa(select.clone());
76 if let Ok(v) = self.run_csdp() {
77 if match self.optimal_value {
78 None => {
79 self.optimal_value = Some(v);
80 true
81 }
82 Some(v0) => (v - v0).abs() < 1e-6,
83 } {
84 self.select = select;
85 info!("New certificate of weight {:?}", self.select.weight());
86 return Ok(());
87 } else {
88 trace!("Selector rejected");
89 return Err("Selector rejected".into());
90 }
91 };
92 Err("run_csdp failed".into())
93 }
94 fn load_certificate(&self) -> Certificate<f64> {
95 if let Some(ref select) = self.select_certificate_file {
96 Certificate::from_file_select(&self.pb.view(select), "certificate").unwrap()
97 } else {
98 panic!("No certificate yet")
99 }
100 }
101 pub fn minimize_certificate(&mut self) {
103 self.write_sdpa(self.select.clone());
104 let _ = self.run_csdp().expect("Cannot find the same value");
105 let new_select = self
106 .select
107 .refine_with_certificate(&self.load_certificate(), &self.protected);
108 self.run(new_select).expect("Certificate too simplified")
109 }
110 pub fn cs_elim(&mut self) {
112 info!("Try to remove Cauchy-Schwarz");
113 for &i in self.select.cs_vec().iter().rev() {
114 if let Ok(select) = self.select.remove_cs(i) {
115 let _ = self.run(select);
116 } else {
117 unreachable!()
118 }
119 }
120 }
121 pub fn thin_cs_elim(&mut self) {
122 info!("Try to refine Cauchy-Schwarz");
123 for &id in &self.select.cs_vec() {
124 let dim = self.select.cs_dim(id);
125 for i in 0..dim {
126 let mut mat = CsMat::zero((dim, dim));
127 mat.insert(i, i, 1.);
128 if let Ok(select) = self.select.restrict_cs(id, mat) {
129 let _ = self.run(select);
130 } else {
131 unreachable!()
132 }
133 }
134 }
135 }
136 pub fn ineqs_elim(&mut self) {
137 info!("Try to remove inequalities");
138 for i in 0..self.select.ineqs.len() {
139 if !self.protected[i] {
140 let mut select = self.select.clone();
141 select.ineqs[i].clear();
142 let _ = self.run(select);
143 }
144 }
145 }
146 pub fn thin_ineqs_elim(&mut self) {
147 info!("Try to refine inequalities");
148 for i in (0..self.select.ineqs.len()).rev() {
149 if !self.protected[i] {
150 for j in 0..self.pb.ineqs[i].data.len() {
151 if let Ok(posj) = self.select.ineqs[i].binary_search(&j) {
152 let mut select = self.select.clone();
153 let _ = select.ineqs[i].remove(posj);
154 if let Ok(()) = self.run(select) {
155 self.use_certificate();
156 }
157 }
158 }
159 }
160 }
161 }
162 pub fn print_report(&self)
163 where
164 F: Draw,
165 {
166 assert_eq!(Some(self.select.clone()), self.select_certificate_file);
167 let cert = self.load_certificate();
168 print_report(&self.pb.view(&self.select), &cert, "report").unwrap()
169 }
170 pub fn minimize_once(&mut self)
173 where
174 F: Draw,
175 {
176 if self.optimal_value.is_none() {
177 self.init();
178 }
179 self.print_report()
180 }
181 pub fn minimize(&mut self)
182 where
183 F: Draw,
184 {
185 if self.optimal_value.is_none() {
186 self.init();
187 }
188 self.cs_elim();
189 self.ineqs_elim();
190 self.thin_ineqs_elim();
191 self.write_sdpa(self.select.clone());
192 let _ = self.run_csdp().unwrap();
193 self.print_report()
194 }
195 pub fn minimize2(&mut self)
196 where
197 F: Draw,
198 {
199 if self.optimal_value.is_none() {
200 self.init()
201 };
202 self.cs_elim();
203 self.thin_cs_elim();
204 self.ineqs_elim();
205 self.minimize_certificate();
206 self.write_sdpa(self.select.clone());
207 let _ = self.run_csdp().unwrap();
208 self.print_report()
209 }
210 pub fn minimize3(&mut self)
211 where
212 F: Draw,
213 {
214 info!("Method 3");
215 if self.optimal_value.is_none() {
216 self.init()
217 };
218 self.cs_elim();
219 self.ineqs_elim();
222 self.thin_cs_elim();
223 self.thin_ineqs_elim();
224 self.write_sdpa(self.select.clone());
225 let _ = self.run_csdp().unwrap();
226 println!("{:?}", self.optimal_value);
227 self.print_report()
228 }
229}