So-Bogus
A c++ sparse block matrix library aimed at Second Order cone problems
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Pages
Cadoux.hpp
1 /*
2  * This file is part of So-bogus, a C++ sparse block matrix library and
3  * Second Order Cone solver.
4  *
5  * Copyright 2015 Gilles Daviet <gdaviet@gmail.com>
6  *
7  * So-bogus is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 2 of the License, or
10  * (at your option) any later version.
11 
12  * So-bogus is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16 
17  * You should have received a copy of the GNU General Public License
18  * along with So-bogus. If not, see <http://www.gnu.org/licenses/>.
19 */
20 
21 #ifndef BOGUS_CADOUX_HPP
22 #define BOGUS_CADOUX_HPP
23 
24 #include "../Core/BlockSolvers/ConstrainedSolverBase.impl.hpp"
25 
26 #include "../Extra/SecondOrder.impl.hpp"
27 #include "../Core/Utils/CppTools.hpp"
28 
29 namespace bogus {
30 
32 
44 template< unsigned Dimension, typename WType, typename Method, typename MatrixT >
45 static typename WType::Scalar solveCadoux(
46  const WType& W,
47  const typename WType::Scalar* b, const typename WType::Scalar* mu,
48  ConstrainedSolverBase< Method, MatrixT > &minimizer,
49  typename WType::Scalar *r, const unsigned cadouxIterations,
50  const Signal<unsigned, typename WType::Scalar> *callback = BOGUS_NULL_PTR(const void),
51  const typename WType::Scalar tolTighten = 1.e-1
52  )
53 {
54  //We might experience slow convergence is inner solve not precise enough
55 
56  typedef typename WType::Scalar Scalar ;
57  const std::ptrdiff_t n = W.rowsOfBlocks() ;
58 
59  SOCLaw< Dimension, Scalar, true > coulombLaw ( n, mu ) ;
60  SOCLaw< Dimension, Scalar, false > socLaw ( n, mu ) ;
61 
62  Eigen::Map< Eigen::VectorXd > r_map ( r, W.rows() ) ;
63  Eigen::Map< const Eigen::VectorXd > b_map ( b, W.rows() ) ;
64 
65  Eigen::VectorXd s( W.rows() ) ;
66 
67  Scalar res = -1 ;
68  const Scalar tol = minimizer.tol() ;
69 
70  // Evaluate initial error
71  s = W * r_map + b_map ;
72  res = minimizer.eval( coulombLaw, s, r_map ) ;
73  if( callback ) callback->trigger( 0, res ) ;
74 
75  for( unsigned cdxIter = 0 ; cdxIter < cadouxIterations ; ++cdxIter )
76  {
77  minimizer.setTol( tolTighten * std::max( tol, std::min( res, 1. ) ) ) ;
78 
79  minimizer.dualityCOV( coulombLaw, s, s ) ;
80 
81  s += b_map ;
82  minimizer.solve( socLaw, s, r_map ) ;
83 
84  // Evaluate current error
85  s = W * r_map + b_map ;
86  res = minimizer.eval( coulombLaw, s, r_map ) ;
87 
88  if( callback ) callback->trigger( cdxIter+1, res ) ;
89  if( res < tol ) break ;
90 
91  }
92 
93  minimizer.setTol( tol ) ;
94 
95  return res ;
96 }
97 
99 
100 template< unsigned Dimension, typename WType, typename Method, typename MatrixT >
101 static double solveCadouxVel(
102  const WType& W,
103  const typename WType::Scalar* b, const typename WType::Scalar* mu,
104  ConstrainedSolverBase< Method, MatrixT > &minimizer,
105  typename WType::Scalar* u, const unsigned cadouxIterations,
106  const Signal<unsigned, typename WType::Scalar> *callback = BOGUS_NULL_PTR(const void),
107  const typename WType::Scalar tolTighten = 1.e-1
108  )
109 {
110  // Wu + b = r
111  // u* = u + s n
112  // Wu* + b - W(s n) = r
113 
114  typedef typename WType::Scalar Scalar ;
115  const std::ptrdiff_t n = W.rowsOfBlocks() ;
116 
117  SOCLaw< Dimension, Scalar, false > socLaw ( n, mu ) ;
118 
119  Eigen::Map< Eigen::VectorXd > u_map ( u, W.rows() ) ;
120  Eigen::Map< const Eigen::VectorXd > b_map ( b, W.rows() ) ;
121 
122  Eigen::VectorXd s( W.rows() ), Wsb( W.rows() ), ustar( u_map ), r( W.rows() ) ;
123 
124  double res = -1 ;
125  const double tol = minimizer.tol() ;
126 
127 #ifndef BOGUS_DONT_PARALLELIZE
128 #pragma omp parallel for
129 #endif
130  for( std::ptrdiff_t i = 0 ; i < n ; ++i )
131  {
132  s[ Dimension*i ] = u_map.segment< Dimension-1 >( Dimension*i+1 ).norm() * std::max(0., 1./mu[i]) ;
133  s.segment< Dimension-1 >( Dimension*i+1 ).setZero() ;
134  }
135  ustar = u_map + s ;
136 
137  //Evaluate intial error
138  r = W * u_map + b_map ;
139  res = minimizer.eval( socLaw, r, ustar ) ;
140  if( callback ) callback->trigger( 0, res ) ;
141 
142  for( unsigned cdxIter = 0 ; cdxIter < cadouxIterations ; ++cdxIter )
143  {
144  minimizer.setTol( tolTighten * std::max( tol, std::min( res, 1. ) ) ) ;
145 
146  Wsb = b_map - W * s ;
147 
148  minimizer.solve( socLaw, Wsb, ustar ) ;
149 
150  u_map = ustar - s ;
151 
152 #ifndef BOGUS_DONT_PARALLELIZE
153 #pragma omp parallel for
154 #endif
155  for( std::ptrdiff_t i = 0 ; i < n ; ++i )
156  {
157  s[ Dimension*i ] = ustar.segment< Dimension-1 >( Dimension*i+1 ).norm() * std::max(0., 1./mu[i]) ;
158  s.segment< Dimension-1 >( Dimension*i+1 ).setZero() ;
159  }
160 
161  ustar = u_map + s ;
162 
163  // Evaluate current error
164  r = W * u_map + b_map ;
165  res = minimizer.eval( socLaw, r, ustar ) ;
166 
167  if( callback ) callback->trigger( cdxIter+1, res ) ;
168  if( cdxIter > 0 && res < tol ) break ;
169 
170  }
171 
172  minimizer.setTol( tol ) ;
173 
174  return res ;
175 }
176 
177 
178 } //bogus
179 
180 #endif