casadi_convexify.hpp
1 //
2 // MIT No Attribution
3 //
4 // Copyright (C) 2010-2023 Joel Andersson, Joris Gillis, Moritz Diehl, KU Leuven.
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining a copy of this
7 // software and associated documentation files (the "Software"), to deal in the Software
8 // without restriction, including without limitation the rights to use, copy, modify,
9 // merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
10 // permit persons to whom the Software is furnished to do so.
11 //
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
13 // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
14 // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
15 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
16 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
17 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 //
19 
20 
21 
22 // SYMBOL "convexify_strategy_t"
23 typedef enum {
24  CVX_REGULARIZE,
25  CVX_EIGEN_CLIP,
26  CVX_EIGEN_REFLECT
27 } casadi_convexify_strategy_t;
28 
29 // SYMBOL "convexify_type_in_t"
30 typedef enum {
31  CVX_SYMM, CVX_TRIL, CVX_TRIU
32 } casadi_convexify_type_in_t;
33 
34 
35 // SYMBOL "convexify_config"
36 template<typename T1>
38  casadi_convexify_strategy_t strategy;
39  casadi_convexify_type_in_t type_in;
40  const casadi_int * Hsp;
41  const casadi_int * Hrsp;
42  T1 margin;
43  // Projection of Hessian sparsity needed? (cache)
45  // Reordering of Hessian needed for scc? (cache)
48  const casadi_int *scc_offset;
49  const casadi_int *scc_mapping;
50  casadi_int scc_offset_size;
52  // Needs to be "big enough"
53  casadi_int max_iter_eig;
54  int verbose;
55 };
56 // C-REPLACE "casadi_convexify_config<T1>" "struct casadi_convexify_config"
57 
58 
59 // SYMBOL "convexify_eval"
60 template<typename T1>
61 int convexify_eval(const casadi_convexify_config<T1>* c, const T1* Hin, T1* Hout, casadi_int* iw, T1* w) { // NOLINT(whitespace/line_length)
62  casadi_int i, j, k, kk, block_size, offset;
63  int ret;
64  T1 reg, e;
65  T1 *H_block, *w_cvx;
66 
67  casadi_int Hrsp_nnz = c->Hrsp[2+c->Hrsp[1]];
68  casadi_int nnz = c->Hsp[2+c->Hsp[1]];
69 
70  if (c->Hsp_project) {
71  if (Hin==Hout) {
72  casadi_copy(Hin, Hrsp_nnz, w);
73  casadi_project(w, c->Hrsp, Hout, c->Hsp, w+Hrsp_nnz);
74  } else {
75  casadi_project(Hin, c->Hrsp, Hout, c->Hsp, w);
76  }
77  } else {
78  if (Hin!=Hout) casadi_copy(Hin, nnz, Hout);
79  }
80 
81  if (c->strategy==CVX_REGULARIZE) {
82  // Determine regularization parameter with Gershgorin theorem
83  reg = c->margin-casadi_lb_eig(c->Hsp, Hout);
84  if (reg > 0) casadi_regularize(c->Hsp, Hout, reg);
85  } else if (c->strategy==CVX_EIGEN_REFLECT || c->strategy==CVX_EIGEN_CLIP) {
86  offset = 0;
87 
88  // Loop over Hessian blocks
89  for (k=0;k<c->scc_offset_size-1;++k) {
90  block_size = c->scc_offset[k+1]-c->scc_offset[k];
91 
92  H_block = w;
93  w_cvx = w;
94 
95  // Set w_cvx to dense Hessian block from Hout
96  if (c->scc_transform) {
97  kk=0;
98  if (c->type_in==CVX_SYMM) {
99  // Loop over columns of block
100  for (i=0;i<block_size;++i) {
101  // Loop over elements in column
102  for (j=0;j<block_size;++j, ++kk) {
103  H_block[kk] = Hout[c->scc_mapping[offset+kk]];
104  }
105  }
106  } else if (c->type_in==CVX_TRIU) {
107  // Loop over columns of block
108  for (i=0;i<block_size;++i) {
109  // Loop over elements in column
110  for (j=0;j<i+1;++j, ++kk) {
111  e = Hout[c->scc_mapping[offset+kk]];
112  H_block[i*block_size+j] = e;
113  H_block[i+block_size*j] = e;
114  }
115  }
116  } else {
117  // Loop over columns of block
118  for (i=0;i<block_size;++i) {
119  for (j=i;j<block_size;++j, ++kk) {
120  e = Hout[c->scc_mapping[offset+kk]];
121  H_block[i*block_size+j] = e;
122  H_block[i+block_size*j] = e;
123  }
124  }
125  }
126  w_cvx += block_size*block_size;
127  } else {
128  H_block = Hout+offset;
129  }
130 
131  // Perform convexification
132  ret = casadi_cvx(block_size, H_block, c->margin, 1e-10,
133  c->strategy==CVX_EIGEN_REFLECT, c->max_iter_eig, w_cvx, iw);
134  if (ret) return ret;
135 
136  // Fill in upper-rectangular part
137  for (i=0;i<block_size;++i) {
138  for (j=0;j<i+1;++j) {
139  H_block[block_size*i+j] = H_block[block_size*j+i];
140  }
141  }
142 
143  // Put results back in Hout
144  if (c->scc_transform) {
145  kk=0;
146  if (c->type_in==CVX_SYMM) {
147  // Loop over columns of block
148  for (i=0;i<block_size;++i) {
149  // Loop over elements in column
150  for (j=0;j<block_size;++j, ++kk) {
151  Hout[c->scc_mapping[offset+kk]] = H_block[kk];
152  }
153  }
154  } else if (c->type_in==CVX_TRIU) {
155  // Loop over columns of block
156  for (i=0;i<block_size;++i) {
157  // Loop over elements in column
158  for (j=0;j<i+1;++j, ++kk) {
159  Hout[c->scc_mapping[offset+kk]] = H_block[block_size*i+j];
160  }
161  }
162  } else {
163  // Loop over columns of block
164  for (i=0;i<block_size;++i) {
165  // Loop over elements in column
166  for (j=i;j<block_size;++j, ++kk) {
167  Hout[c->scc_mapping[offset+kk]] = H_block[block_size*i+j];
168  }
169  }
170  }
171  }
172 
173  if (c->type_in==CVX_SYMM) {
174  offset += block_size*block_size;
175  } else {
176  offset += block_size*(block_size+1)/2;
177  }
178  }
179  }
180 
181  return 0;
182  }
casadi_int max_iter_eig
For eigen-* convexification strategies: maximum iterations for symmetric Schur decomposition.
casadi_convexify_strategy_t strategy
const casadi_int * Hsp
casadi_convexify_type_in_t type_in
const casadi_int * Hrsp
const casadi_int * scc_offset
Block structure of Hessian for certain convexification methods.
const casadi_int * scc_mapping