BonQuadRow.cpp
Go to the documentation of this file.
1 // (C) Copyright International Business Machines Corporation 2007
2 // All Rights Reserved.
3 // This code is published under the Eclipse Public License.
4 //
5 // Authors :
6 // Pierre Bonami, International Business Machines Corporation
7 //
8 // Date : 10/06/2007
9 
10 #include "BonQuadRow.hpp"
11 #include <cfloat>
12 //#define DEBUG
13 namespace Bonmin{
14 
16  c_(0),
17  a_(),
18  Q_(),
19  grad_evaled_(false)
20 {
21 }
22 
23 QuadRow::QuadRow(const QuadRow &other):
24  c_(other.c_),
25  a_(other.a_),
26  Q_(other.Q_),
27  g_(),
28  a_grad_idx_(),
29  Q_row_grad_idx_(),
30  Q_col_grad_idx_(),
31  Q_hessian_idx_(),
32  grad_evaled_(false)
33 {
34  initialize();
35 }
36 
38  if(this != &rhs){
39  c_ = rhs.c_;
40  a_ = rhs.a_;
41  Q_ = rhs.Q_;
42  Q_hessian_idx_.clear();
43  g_.clear();
44  a_grad_idx_.clear();
45  Q_row_grad_idx_.clear();
46  Q_col_grad_idx_.clear();
47  initialize();
48  //H_Hes_idx_ = rhs.H_Hes_idx_;
49  grad_evaled_ = false;
50  }
51  return (*this);
52 }
53 
55  c_(0),
56  a_(cut.row()),
57  Q_(cut.Q(), cut.type())
58  {
59  initialize();
60  }
61 
62 QuadRow&
64  c_ = cut.c();
65  a_ = cut.row();
66  Q_ = cut.Q();
68  g_.clear();
69  a_grad_idx_.clear();
70  Q_row_grad_idx_.clear();
71  Q_col_grad_idx_.clear();
72  //Q_hessian_idx.empty();
73  //H_Hes_idx_.empty()
74  initialize();
75  return (*this);
76 }
77 
78 
79 QuadRow::QuadRow(const OsiRowCut &cut):
80  c_(0),
81  a_(cut.row()),
82  Q_()
83  {
84  initialize();
85  }
86 
87 QuadRow&
88 QuadRow::operator=(const OsiRowCut &cut){
89  c_ = 0;
90  a_ = cut.row();
91  Q_ = TMat();
92  g_.empty();
93  a_grad_idx_.empty();
94  Q_row_grad_idx_.clear();
95  Q_col_grad_idx_.clear();
96  //Q_hessian_idx.empty();
97  //H_Hes_idx_.empty()
98  initialize();
99  return (*this);
100 }
101 
102 void
104  //Check that Q_ is upper triangular
105  for(int i = 0 ; i < Q_.nnz_ ; i++){
106  assert(Q_.jCol_[i] >= Q_.iRow_[i]);}
107  grad_evaled_ = false;
108 
109  int n;
110  // Construct a map to store the non-zero elements of the gradient.
111  n = a_.getNumElements();
112  a_grad_idx_.reserve(n);
113 
114  // Put the linear elements
115  const int * indices = a_.getIndices();
116  const double * elems = a_.getElements();
117 
118  for(int i = 0 ; i < n ; i++){
119  std::pair<gStore::iterator, bool> res = g_.insert(std::make_pair(indices[i], std::make_pair(elems[i],0.)));
120  a_grad_idx_.push_back(res.first);
121  }
122  // Put the quadratics first rows
123  n = Q_.numNonEmptyRows();
124  const TMat::RowS& nonEmptyRows = Q_.nonEmptyRows();
125  Q_row_grad_idx_.reserve(n);
126 
127  for(TMat::RowS::const_iterator i = nonEmptyRows.begin() ; i != nonEmptyRows.end() ; i++){
128  std::pair<gStore::iterator, bool> res = g_.insert(std::make_pair(i->first, std::make_pair(0.,0.)));
129  Q_row_grad_idx_.push_back(res.first);
130  }
131 
132  //Now columns
133  n = Q_.numNonEmptyCols();
134  const TMat::RowS& nonEmptyCols = Q_.nonEmptyCols();
135  Q_col_grad_idx_.reserve(n);
136 
137  for(TMat::RowS::const_iterator i = nonEmptyCols.begin() ; i != nonEmptyCols.end() ; i++){
138  std::pair<gStore::iterator, bool> res = g_.insert(std::make_pair(i->first, std::make_pair(0.,0.)));
139  Q_col_grad_idx_.push_back(res.first);
140  }
141 
142 }
143 
145 void
147  std::cout<<"constant term "<<c_<<std::endl;
148  int * a_ind = a_.getIndices();
149  const double * a_el = a_.getElements();
150  int n = a_.getNumElements();
151  std::cout<<"Linear term (size "<<n<<"): ";
152  for(int i = 0 ; i < n ; i++)
153  {
154  std::cout<<a_el[i]<<" * x["<<a_ind[i]<<"]\t";
155  if(i && ( (i % 5) == 0 ) ) std::cout<<std::endl<<"\t\t";
156  }
157 }
159 double
160 QuadRow::eval_f(const double *x, bool new_x){
161  //if(new_x){
162  internal_eval_grad(x);//}
163  double value = c_;// Constant
164 
165  //Linear part
166  int * a_ind = a_.getIndices();
167  const double * a_el = a_.getElements();
168  int n = a_.getNumElements();
169  for(int i = 0 ; i < n ; i++)
170  {
171  value += a_el[i] * x[a_ind[i]];
172 
173  }
174 
175  //Quadratic part
176  for(gStore::iterator i = g_.begin() ; i != g_.end() ; i++){
177  value += i->second.second * x[i->first];
178  }
179  return value;
180 }
181 
183 int
185  return static_cast<int>(g_.size());}
187 void
188 QuadRow::gradiant_struct(const int nnz, int * indices, bool offset){
189  int n = 0;
190  for(gStore::iterator i = g_.begin() ; i != g_.end() ; i++){
191  indices[n++] = i->first + offset;
192  }
193  assert(n == nnz);
194  assert(nnz == (int) g_.size());
195 }
196 
198 void
199 QuadRow::eval_grad(const int nnz, const double * x, bool new_x, double * values){
200 
201 #ifdef DEBUG
202  // Output relevant components of x
203  for(gStore::iterator i = g_.begin() ; i != g_.end() ; i++){
204  printf("x[%i] = %g, ",i->first, x[i->first]);
205  }
206 #endif
207  //if(new_x){
208  internal_eval_grad(x);//}
209  int n = 0;
210 #ifdef DEBUG
211  std::cout<<"Computing gradient"<<std::endl;
212 #endif
213  for(gStore::iterator i = g_.begin() ; i != g_.end() ; i++){
214 #ifdef DEBUG
215  printf("%i: %g, %g\n", i->first, i->second.second, i->second.first);
216 #endif
217  values[n++] = 2*i->second.second + i->second.first;
218  }
219  assert (nnz == (int) g_.size());
220 }
221 
222 void
224  // Zero out gradiant storage
225  for(gStore::iterator i = g_.begin() ; i != g_.end() ; i++){
226  i->second.second = 0;
227  }
228 
229 
230  const TMat::RowS & nonEmptyRows = Q_.nonEmptyRows();
231  int k = 0;//Iterates on Q_grad_idx_;
232  for(TMat::RowS::const_iterator ii = nonEmptyRows.begin() ; ii != nonEmptyRows.end();
233  ii++, k++){
234  double value = 0;
235  assert(ii->first == Q_.iRow_[Q_.rowOrdering_[ii->second]]);
236  for(int i = ii->second ; i < Q_.nnz_ && ii->first == Q_.iRow_[Q_.rowOrdering_[i]] ; i++)
237  {
238  value += x[Q_.jCol_[Q_.rowOrdering_[i]]] * Q_.value_[Q_.rowOrdering_[i]];
239  }
240  Q_row_grad_idx_[k]->second.second += value;
241  assert(Q_row_grad_idx_[k]->first == ii->first);
242  }
243  const TMat::RowS & nonEmptyCols = Q_.nonEmptyCols();
244  k = 0;//Iterates on Q_grad_idx_;
245  for(TMat::RowS::const_iterator ii = nonEmptyCols.begin() ; ii != nonEmptyCols.end();
246  ii++, k++){
247  double value = 0;
248  assert(ii->first == Q_.jCol_[Q_.columnOrdering_[ii->second]]);
249  for(int i = ii->second ; i < Q_.nnz_ && ii->first == Q_.jCol_[Q_.columnOrdering_[i]] ; i++)
250  {
252  value += x[Q_.iRow_[Q_.columnOrdering_[i]]] * Q_.value_[Q_.columnOrdering_[i]];
253  }
254  Q_col_grad_idx_[k]->second.second += value;
255  assert(Q_col_grad_idx_[k]->first == ii->first);
256  }
257 
258  grad_evaled_ = true;
259 }
260 
261 void
263  assert(Q_hessian_idx_.empty());
264  for(int i = 0 ; i < Q_.nnz_ ; i++){
265  std::pair<int, int> e;
266  e = std::make_pair(Q_.jCol_[i] + offset, Q_.iRow_[i] + offset);
267  AdjustableMat::iterator pos = H.find(e);
268  if(pos != H.end()){//Already exists
269  if(pos->second.second != -1)
270  pos->second.second++;
271  Q_hessian_idx_.push_back(pos);
272  }
273  else {
274  std::pair<AdjustableMat::iterator, bool> res =
275  H.insert(std::make_pair(e, std::make_pair(H.size(), 1)));
276  assert(res.second == true);
277  Q_hessian_idx_.push_back(res.first);
278  }
279  }
280 }
281 
282 void
284  for(int i = 0 ; i < Q_.nnz_ ; i++){
285  if(Q_hessian_idx_[i]->second.second != -1)
286  Q_hessian_idx_[i]->second.second--;
287  if(Q_hessian_idx_[i]->second.second == 0){
288  H.erase(Q_hessian_idx_[i]);
289  }
290  }
291  Q_hessian_idx_.clear();
292 }
293 
295  void
296  QuadRow::eval_hessian(double lambda, double * values){
297  for(int i = 0 ; i < Q_.nnz_ ; i++){
298 #ifdef DEBUG
299  printf("iRow %i, jCol %i, value %g , nnz %i\n",
300  Q_hessian_idx_[i]->first.second,
301  Q_hessian_idx_[i]->first.first,
302  Q_.value_[i],
303  Q_hessian_idx_[i]->second.first);
304 #endif
305  values[Q_hessian_idx_[i]->second.first] += (lambda * 2 * Q_.value_[i]);
306  }
307 }
308 
309 }// Ends Bonmin namespace
310 
double * values
int numNonEmptyCols()
Get number of non empty cols.
Definition: BonTMatrix.cpp:123
CoinPackedVector a_
linear term in sparse storage.
Definition: BonQuadRow.hpp:98
void make_upper_triangular(const MatrixStorageType &T)
Definition: BonTMatrix.cpp:160
pos
position where the operator should be printed when printing the expression
void internal_eval_grad(const double *x)
Does internal work to evaluate gradiant of this in x.
Definition: BonQuadRow.cpp:223
std::vector< AdjustableMat::iterator > Q_hessian_idx_
To have fast access to entries in full hessian of Q_.
Definition: BonQuadRow.hpp:117
TMat Q_
Quadratic term.
Definition: BonQuadRow.hpp:100
CouNumber Q(register int k, CouNumber x)
Definition: rootQ.cpp:21
vector< int > rowOrdering_
Definition: BonTMatrix.hpp:149
std::vector< gStore::iterator > a_grad_idx_
To have fast access to gradiant entries for a_.
Definition: BonQuadRow.hpp:111
std::vector< gStore::iterator > Q_col_grad_idx_
To have fast access to gradient entries for cols Q_.
Definition: BonQuadRow.hpp:115
void eval_grad(const int nnz, const double *x, bool new_x, double *values)
Evaluate gradiant of quadratic form.
Definition: BonQuadRow.cpp:199
CoinPackedMatrix & Q()
Return the matrix stored.
Definition: BonQuadCut.hpp:49
void remove_from_hessian(AdjustableMat &H)
Remove row from a bigger hessian.
Definition: BonQuadRow.cpp:283
double eval_f(const double *x, bool new_x)
Evaluate quadratic form.
Definition: BonQuadRow.cpp:160
void add_to_hessian(AdjustableMat &H, bool offset)
Add row to a bigger hessian.
Definition: BonQuadRow.cpp:262
QuadRow()
Default constructor.
Definition: BonQuadRow.cpp:15
std::vector< gStore::iterator > Q_row_grad_idx_
To have fast access to gradient entries for rows Q_.
Definition: BonQuadRow.hpp:113
Stores a quadratic row of the form l &lt; c + ax + x^T Q x &lt; u.
Definition: BonQuadRow.hpp:32
void fint fint fint real fint real real real real real real real real real * e
QuadRow & operator=(const QuadRow &rhs)
Assignment operator.
Definition: BonQuadRow.cpp:37
void fint fint * k
double * value_
Definition: BonTMatrix.hpp:25
const RowS & nonEmptyCols() const
Get the list of non empty row.
Definition: BonTMatrix.hpp:78
int nnz_grad()
Get number of non-zeroes in the gradiant.
Definition: BonQuadRow.cpp:184
void gradiant_struct(const int nnz, int *indices, bool offset)
Get structure of gradiant.
Definition: BonQuadRow.cpp:188
void initialize()
Initialize once quadratic form is know.
Definition: BonQuadRow.cpp:103
bool grad_evaled_
Flag indicating if gradiant has been evaluated.
Definition: BonQuadRow.hpp:119
double & c()
Acces the constant.
Definition: BonQuadCut.hpp:67
void eval_hessian(double lambda, double *values)
Return hessian value (i.e.
Definition: BonQuadRow.cpp:296
vector< int > columnOrdering_
Definition: BonTMatrix.hpp:147
std::map< matEntry, matIdx > AdjustableMat
Definition: BonQuadRow.hpp:26
double c_
Constant term.
Definition: BonQuadRow.hpp:96
const RowS & nonEmptyRows() const
Get the list of non empty row.
Definition: BonTMatrix.hpp:71
void print()
Print quadratic constraint.
Definition: BonQuadRow.cpp:146
int nnz
ATTENTION: Filter expect the jacobian to be ordered by row.
void fint * n
MatrixStorageType & type()
Acces storage type Acces storage type.
Definition: BonQuadCut.hpp:60
int numNonEmptyRows()
Get number of non empty rows.
Definition: BonTMatrix.cpp:104
void fint fint fint real fint real * x