impl<N, F> Problem<N, F>
where
N: Display + Zero + Copy + PartialEq,
F: Flag,
{
/// Write the semi-definite program in the file `filename` in the sdpa format.
pub fn write_sdpa_select(&self, filename: &str, select: &Selector, fixed_obj: Option<f64>) -> Result<()> {
self.check();
let mut filename = PathBuf::from(filename);
let _ = filename.set_extension("sdpa");
let mut file = BufWriter::new(File::create(&filename)?);
let problem = self.view(&select); // Selected problem
info!("Writing problem in {}", filename.display());
problem.write_header(&mut file)?;
debug!("Generating Cauchy-Schwarz inequalities");
let cs_mat: Vec<_> = problem.cs.iter().map(|cs|{ cs.get() }).collect();
// Line 1: Number of constraints = size of the basis
// * If the target objective is fixed: add 1 constraint for the objective
if fixed_obj == None {
writeln!(file, "{}", self.obj.data.len())?;
} else {
writeln!(file, "{}", self.obj.data.len() + 1)?;
}
// Line 2: Number of blocks (one for each constraint)
writeln!(file, "{}", self.ineqs.len() + select.cs.len())?;
// Line 3: Sizes of the blocks
for ineq in problem.ineqs.iter() {
write!(file, "-{} ", std::cmp::max(1, ineq.len()))?;
}
for split in &cs_mat {
write!(file, "{} ", split[0].rows())?;
}
writeln!(file)?;
// Line 4: vector ai
// ai is the needed coefficient for the flag Fi
for v in &self.obj.data {
write!(file, "{} ", v)?;
}
// * The last coefficient is the target value, if there is one
if let Some(obj_value) = fixed_obj {
write!(file, "{} ", obj_value)?;
}
writeln!(file)?;
// Lines 5+: body
// Matrix 0: Objective
let mat_obj = match fixed_obj {
None => 0,
Some(_) => self.obj.data.len() + 1, // * Additional matrix, after the ones of the Fis
};
for (block_num, ineq) in problem.ineqs.iter().enumerate() {
for (i, ineq_data) in ineq.iter().enumerate() {
write_coeff(&mut file, mat_obj, block_num, i, i, ineq_data.bound)?;
}
}
writeln!(file)?;
// Matrices 1+:
// Inequaltity blocks
for (block_num, ineq) in problem.ineqs.iter().enumerate() {
for (i, ineq_data) in ineq.iter().enumerate() {
for (mat_num, &v) in ineq_data.flag.iter().enumerate() {
write_coeff(&mut file, mat_num + 1, block_num, i, i, v)?;
}
}
}
writeln!(file)?;
// Cs blocks
let offset = self.ineqs.len();
for (block_num, line) in cs_mat.iter().enumerate() {
for (mat_num, matrix) in line.iter().enumerate() {
for (&v, (i, j)) in matrix.iter() {
if i <= j {
write_coeff(&mut file, mat_num + 1, block_num + offset, i, j, v)?;
}
}
}
}
// * If fixed objective, weight the certificate
if let Some(_) = fixed_obj {
// * Weight coeffs of inequalities
for (block_num, ineq) in problem.ineqs.iter().enumerate() {
for i in 0..ineq.len() {
write_coeff(&mut file, 0, block_num, i, i, -10.)?;
}
}
// * Weight thr trace of Cauchy-Schwarz matrices
for (block_num, line) in cs_mat.iter().enumerate() {
for i in 0..line[0].cols() {
write_coeff(&mut file, 0, block_num + offset, i, i, -1000_000.)?;
}
}
}
Ok(())
}
}