BWAPI
|
00001 // Copyright (c) 1997-2007 ETH Zurich (Switzerland). 00002 // All rights reserved. 00003 // 00004 // This file is part of CGAL (www.cgal.org); you may redistribute it under 00005 // the terms of the Q Public License version 1.0. 00006 // See the file LICENSE.QPL distributed with CGAL. 00007 // 00008 // Licensees holding a valid commercial license may use this file in 00009 // accordance with the commercial license agreement provided with the software. 00010 // 00011 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 00012 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00013 // 00014 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/QP_solver/include/CGAL/QP_solver/QP_solver_nonstandardform_impl.h $ 00015 // $Id: QP_solver_nonstandardform_impl.h 46194 2008-10-09 13:07:49Z gaertner $ 00016 // 00017 // 00018 // Author(s) : Sven Schoenherr 00019 // Bernd Gaertner <gaertner@inf.ethz.ch> 00020 // Franz Wessendorp 00021 // Kaspar Fischer 00022 00023 CGAL_BEGIN_NAMESPACE 00024 00025 // Looks in x_O_v_i which bound is present for variable i and returns 00026 // the variable's value corresponding to this bound. 00027 // 00028 // Precondition: Is_nonnegative is Tag_false. 00029 template < typename Q, typename ET, typename Tags > 00030 ET QP_solver<Q, ET, Tags>::original_variable_value_under_bounds(int i) const 00031 { 00032 CGAL_assertion(!check_tag(Is_nonnegative()) && i<qp_n); 00033 switch (x_O_v_i[i]) { 00034 case UPPER: 00035 return *(qp_u+i); 00036 case ZERO: 00037 return et0; 00038 case LOWER: 00039 case FIXED: 00040 return *(qp_l+i); 00041 case BASIC: 00042 CGAL_qpe_assertion(false); 00043 } 00044 return et0; // dummy 00045 } 00046 00047 template < typename Q, typename ET, typename Tags > 00048 ET QP_solver<Q, ET, Tags>::variable_numerator_value(int i) const 00049 { 00050 // Returns the current value of an *original* variable. 00051 CGAL_qpe_assertion( 0 <= i && i < qp_n ); 00052 if (check_tag(Is_nonnegative())) { 00053 if (in_B[i] < 0) 00054 return et0; 00055 else 00056 return x_B_O[in_B[i]]; 00057 } 00058 00059 // now we have nonstandard form 00060 typedef QP_solver<Q, ET, Tags> QP; 00061 switch (x_O_v_i[i]) { 00062 case QP::UPPER: 00063 return ET(*(qp_u+i)) * d; 00064 case QP::ZERO: 00065 return et0; 00066 case QP::LOWER: 00067 case QP::FIXED: 00068 return ET(*(qp_l+i)) * d; 00069 case QP::BASIC: 00070 return x_B_O[in_B[i]]; 00071 default: // never reached 00072 return et0; 00073 } 00074 } 00075 00076 template < typename Q, typename ET, typename Tags > 00077 ET QP_solver<Q, ET, Tags>::nonbasic_original_variable_value 00078 (int i) const 00079 { 00080 if (check_tag(Is_nonnegative())) 00081 return et0; 00082 00083 CGAL_assertion(!is_basic(i)); 00084 return original_variable_value_under_bounds(i); 00085 } 00086 00087 // Computes r_i:= A_i x_init, for i=row, where x_init is the solution 00088 // with which the solver starts the computation. I.e., computes the 00089 // scalar product of the row-th row of A and the vector x_init which 00090 // contains as its entries the values original_variable_value(i), 00091 // 0<=i<qp_n. 00092 template < typename Q, typename ET, typename Tags > 00093 ET QP_solver<Q, ET, Tags>::multiply__A_ixO(int row) const 00094 { 00095 ET value = et0; 00096 00097 for (int i = 0; i < qp_n; ++i) 00098 // Note: the following computes 00099 // 00100 // value += original_variable_value(i) * qp_A[i][row]; 00101 // 00102 // but for efficiency, we only add summands that are known to be 00103 // nonzero. 00104 switch (x_O_v_i[i]) { 00105 case UPPER: 00106 value += ET(*(qp_u+i)) * ET(*((*(qp_A+i))+row)); 00107 break; 00108 case LOWER: 00109 case FIXED: 00110 value += ET(*(qp_l+i)) * ET(*((*(qp_A+i))+row)); 00111 break; 00112 case BASIC: 00113 CGAL_qpe_assertion(false); 00114 default: 00115 break; 00116 } 00117 00118 return value; 00119 } 00120 00121 // Computes r_{C}:= A_{C, N_O} x_{N_O}. 00122 // 00123 // Precondition: this routine should only be called for nonstandard form 00124 // problems. 00125 template < typename Q, typename ET, typename Tags > 00126 void QP_solver<Q, ET, Tags>:: 00127 multiply__A_CxN_O(Value_iterator out) const 00128 { 00129 CGAL_qpe_assertion(!check_tag(Is_nonnegative())); 00130 00131 // initialize with zero vector: 00132 std::fill_n(out, C.size(), et0); 00133 00134 for (int i = 0; i < qp_n; ++i) 00135 if (!is_basic(i)) { 00136 const ET x_i = nonbasic_original_variable_value(i); 00137 const A_column a_col = *(qp_A+i); 00138 Value_iterator out_it = out; 00139 for (Index_const_iterator row_it = C.begin(); 00140 row_it != C.end(); 00141 ++row_it, ++out_it) 00142 *out_it += x_i * ET(*(a_col+ *row_it)); 00143 } 00144 } 00145 00146 // Computes w:= 2D_{O, N_O} x_{N_O}. 00147 // 00148 // Precondition: this routine should only be called for nonstandard form 00149 // problems. 00150 // 00151 // todo: In order to optimize this routine, we can if D is symmetric, 00152 // multiply by two at the end of the computation instead of at each 00153 // access to D. (Maybe its also faster to call 00154 // nonbasic_original_variable_value() only O(n) times and not O(n^2) 00155 // times.) 00156 template < typename Q, typename ET, typename Tags > 00157 void QP_solver<Q, ET, Tags>:: 00158 multiply__2D_OxN_O(Value_iterator out) const 00159 { 00160 CGAL_qpe_assertion(!check_tag(Is_nonnegative())); 00161 00162 // initialize with zero vector: 00163 std::fill_n(out, B_O.size(), et0); 00164 00165 for (int row_it = 0; row_it < qp_n; ++row_it, ++out) { 00166 D_pairwise_accessor d_row(qp_D, row_it); 00167 for (int i = 0; i < qp_n; ++i) 00168 if (!is_basic(i)) { 00169 const ET value = nonbasic_original_variable_value(i); 00170 *out += d_row(i) * value; 00171 } 00172 } 00173 } 00174 00175 // Computes r_{S_B}:= A_{S_B, N_O} x_{N_O}. 00176 // 00177 // Precondition: this routine should only be called for nonstandard form 00178 // problems. 00179 template < typename Q, typename ET, typename Tags > 00180 void QP_solver<Q, ET, Tags>:: 00181 multiply__A_S_BxN_O(Value_iterator out) const 00182 { 00183 // initialize with zero vector: 00184 std::fill_n(out, S_B.size(), et0); 00185 00186 for (int i = 0; i < qp_n; ++i) 00187 if (!is_basic(i)) { 00188 const ET x_i = nonbasic_original_variable_value(i); 00189 const A_column a_col = *(qp_A+i); 00190 Value_iterator out_it = out; 00191 for (Index_const_iterator row_it = S_B.begin(); 00192 row_it != S_B.end(); 00193 ++row_it, ++out_it) 00194 *out_it += x_i * ET(*(a_col+ *row_it)); 00195 } 00196 } 00197 00198 // Initialize r_B_O. 00199 // 00200 // Note: this routine is called from transition() (and not during the 00201 // initialization of the QP-solver). 00202 template < typename Q, typename ET, typename Tags > 00203 void QP_solver<Q, ET, Tags>:: 00204 init_r_B_O() 00205 { 00206 CGAL_qpe_assertion(!check_tag(Is_nonnegative()) && 00207 !check_tag(Is_linear())); 00208 r_B_O.resize(B_O.size()); 00209 multiply__2D_B_OxN_O(r_B_O.begin()); 00210 } 00211 00212 // Initialize w. 00213 // 00214 // Note: this routine is called from transition() (and not during the 00215 // initialization of the QP-solver). 00216 template < typename Q, typename ET, typename Tags > 00217 void QP_solver<Q, ET, Tags>:: 00218 init_w() 00219 { 00220 CGAL_qpe_assertion(!check_tag(Is_nonnegative()) && 00221 !check_tag(Is_linear())); 00222 w.resize(qp_n); 00223 multiply__2D_OxN_O(w.begin()); 00224 } 00225 00226 CGAL_END_NAMESPACE 00227 00228 // ===== EOF ==================================================================