Skip to main content

sdo1/
sdo1.rs

1//!
2//!  Copyright : Copyright (c) MOSEK ApS, Denmark. All rights reserved.
3//!
4//!  File : sdo1.rs
5//!
6//!  Purpose:   Solves the following small semidefinite optimization problem
7//!             using the MOSEK API.
8//!
9//!    minimize    Tr [2, 1, 0; 1, 2, 1; 0, 1, 2]*X + x0
10//!
11//!    subject to  Tr [1, 0, 0; 0, 1, 0; 0, 0, 1]*X + x0           = 1
12//!                Tr [1, 1, 1; 1, 1, 1; 1, 1, 1]*X      + x1 + x2 = 0.5
13//!                (x0,x1,x2) \in Q,  X \in PSD
14//!
15
16extern crate mosek;
17
18use mosek::{Task,Streamtype,Solsta,Soltype};
19
20const INF : f64 = 0.0;
21
22const NUMCON    : usize = 2;   /* Number of constraints.              */
23const NUMVAR    : usize = 3;   /* Number of conic quadratic variables */
24
25fn main() -> Result<(),String>
26{
27    let dimbarvar = vec![3];         /* Dimension of semidefinite cone */
28
29    let bkc = &[ mosek::Boundkey::FX, mosek::Boundkey::FX ];
30    let blc = &[ 1.0, 0.5 ];
31    let buc = &[ 1.0, 0.5 ];
32
33    let barc_i = &[0, 1, 1, 2, 2];
34    let barc_j = &[0, 0, 1, 1, 2];
35    let barc_v = &[2.0, 1.0, 2.0, 1.0, 2.0];
36
37    let aptrb = &[0, 1];
38    let aptre = &[1, 3];
39    let asub  = &[0, 1, 2]; /* column subscripts of A */
40    let aval  = &[1.0, 1.0, 1.0];
41
42    let bara_i = &[0, 1, 2, 0, 1, 2, 1, 2, 2];
43    let bara_j = &[0, 1, 2, 0, 0, 0, 1, 1, 2];
44    let bara_v = &[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0];
45
46    let falpha = 1.0;
47
48
49    /* Create the optimization task. */
50    let mut task = match Task::new() {
51        Some(e) => e,
52        None => return Err("Failed to create task".to_string()),
53        }.with_callbacks();
54
55    task.put_stream_callback(Streamtype::LOG, |msg| print!("{}",msg))?;
56
57    /* Append 'NUMCON' empty constraints.
58     * The constraints will initially have no bounds. */
59    task.append_cons(NUMCON as i32)?;
60
61    /* Append 'NUMVAR' variables.
62     * The variables will initially be fixed at zero (x=0). */
63    task.append_vars(NUMVAR as i32)?;
64
65    /* Append 'NUMBARVAR' semidefinite variables. */
66    task.append_barvars(&dimbarvar[..])?;
67
68    /* Optionally add a constant term to the objective. */
69    task.put_cfix(0.0)?;
70
71    /* Set the linear term c_j in the objective.*/
72    task.put_c_j(0,1.0)?;
73
74    for j in 0..NUMVAR {
75        task.put_var_bound(j as i32,
76                           mosek::Boundkey::FR,
77                           -INF,
78                           INF)?;
79    }
80
81    /* Set the linear term barc_j in the objective.*/
82    let c_symmat_idx = task.append_sparse_sym_mat(dimbarvar[0],
83                                                  barc_i,
84                                                  barc_j,
85                                                  barc_v)?;
86    task.put_barc_j(0, &[c_symmat_idx], &[falpha])?;
87
88    for i in 0..NUMCON
89    {
90        /* Input A row by row */
91        task.put_a_row(i as i32,
92                       & asub[aptrb[i]..aptre[i]],
93                       & aval[aptrb[i]..aptre[i]])?;
94
95        /* Set the bounds on constraints.
96         * for i=1, ...,NUMCON : blc[i] <= constraint i <= buc[i] */
97        task.put_con_bound(i as i32,    /* Index of constraint.*/
98                           bkc[i],      /* Bound key.*/
99                           blc[i],      /* Numerical value of lower bound.*/
100                           buc[i])?;     /* Numerical value of upper bound.*/
101    }
102
103    {
104        /* Append the conic quadratic cone */
105        let afei = task.get_num_afe()?;
106        task.append_afes(3)?;
107        task.put_afe_f_entry_list(&[0,1,2],
108                                  &[0,1,2],
109                                  &[1.0,1.0,1.0])?;
110        let dom = task.append_quadratic_cone_domain(3)?;
111        task.append_acc_seq(dom,afei,&[0.0,0.0,0.0])?;
112    }
113
114    /* Add the first row of barA */
115    let a_symmat_idx1 =
116        task.append_sparse_sym_mat(dimbarvar[0],
117                                   & bara_i[..3],
118                                   & bara_j[..3],
119                                   & bara_v[..3])?;
120
121    task.put_bara_ij(0, 0, &[a_symmat_idx1][..], &[falpha][..])?;
122
123    /* Add the second row of barA */
124    let a_symmat_idx2 =
125        task.append_sparse_sym_mat(dimbarvar[0],
126                                   & bara_i[3..9],
127                                   & bara_j[3..9],
128                                   & bara_v[3..9])?;
129    task.put_bara_ij(1, 0, &[a_symmat_idx2][..], &[falpha][..])?;
130
131    let _trmcode = task.optimize()?;
132
133    task.write_data("sdo1.ptf")?;
134    /* Print a summary containing information
135     * about the solution for debugging purposes*/
136    task.solution_summary (Streamtype::MSG)?;
137
138    let solsta = task.get_sol_sta(Soltype::ITR)?;
139
140    match solsta
141    {
142        Solsta::OPTIMAL =>
143        {
144            let mut xx = vec![0.0,0.0,0.0];
145            task.get_xx(Soltype::ITR,    /* Request the basic solution. */
146                        & mut xx[..])?;
147            let mut barx = vec![0.0,0.0,0.0,0.0,0.0,0.0];
148            task.get_barx_j(Soltype::ITR,    /* Request the interior solution. */
149                            0,
150                            & mut barx[..])?;
151            println!("Optimal primal solution");
152            for j in 0..NUMVAR as usize
153            {
154                println!("x[{}]: {}",j,xx[j]);
155            }
156            let n = dimbarvar[0] as usize;
157            for j in 0..n
158            {
159                for i in j..n
160                {
161                    println!("barx[{},{}]: {}",i,j,barx[j*n+i-j*(j+1)/2]);
162                }
163            }
164          }
165
166        Solsta::DUAL_INFEAS_CER       |
167        Solsta::PRIM_INFEAS_CER       =>
168        {
169            println!("Primal or dual infeasibility certificate found.");
170        }
171
172        Solsta::UNKNOWN =>
173        {
174            /* If the solutions status is unknown, print the termination code
175             * indicating why the optimizer terminated prematurely. */
176
177            println!("The solution status is unknown.");
178            println!("The optimizer terminitated with code: {}",solsta);
179          }
180        _ =>
181        {
182            println!("Other solution status.");
183        }
184    }
185    Ok(())
186} /* main */
187
188
189#[cfg(test)]
190mod tests {
191    #[test]
192    fn test() {
193        super::main().unwrap();
194    }
195}