qp_solver.c
来自「CGAL is a collaborative effort of severa」· C语言 代码 · 共 568 行
C
568 行
// Copyright (c) 1997-2001 ETH Zurich (Switzerland).// All rights reserved.//// This file is part of CGAL (www.cgal.org); you may redistribute it under// the terms of the Q Public License version 1.0.// See the file LICENSE.QPL distributed with CGAL.//// Licensees holding a valid commercial license may use this file in// accordance with the commercial license agreement provided with the software.//// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.//// $Source: /CVSROOT/CGAL/Packages/_QP_solver/include/CGAL/_QP_solver/QP_solver.C,v $// $Revision: 1.10 $ $Date: 2004/09/03 17:41:15 $// $Name: $//// Author(s) : Sven Schoenherr <sven@inf.ethz.ch> CGAL_BEGIN_NAMESPACE // Class Implementation (continued)// ================================// initialization// --------------// set-up of QPtemplate < class Rep_ >voidQP_solver<Rep_>::set( int n, int m, int max_b, typename QP_solver<Rep_>::A_iterator A_it, typename QP_solver<Rep_>::B_iterator b_it, typename QP_solver<Rep_>::C_iterator c_it, typename QP_solver<Rep_>::D_iterator D_it){ CGAL_optimisation_debug { vout2 << std::endl << "------" << std::endl << "Set-Up" << std::endl << "------" << std::endl; vout << "[ " << ( CGAL::check_tag( Is_lp()) ? "L" : "Q") << "P, " << n << " variables, " << m << " constraints ]" << std::endl; } // store QP CGAL_optimisation_precondition( m > 0); CGAL_optimisation_precondition( n >= m); qp_n = n; qp_m = m; qp_A = A_it; qp_b = b_it; qp_c = c_it; qp_D = D_it; max_basis = max_b; // set up pricing strategy strategyP->set( *this, vout2); }// set-up of auxiliary problemtemplate < class Rep_ >voidQP_solver<Rep_>::set_up_auxiliary_problem( ){ int ii; // delete artifical part of `A' and auxiliary `c', if necessary art_A.clear(); aux_c.clear(); // initialize artificial part of `A' and auxiliary `c' art_A.reserve( qp_m); aux_c.reserve( qp_n+qp_m); aux_c.insert( aux_c.end(), qp_n, nt_0); for ( ii = 0; ii < qp_m; ++ii) { Artificial_column art_col; art_col.push_back( std::make_pair( ii, qp_b[ ii] >= nt_0 ? nt_1 : nt_minus_1)); art_A.push_back( art_col); aux_c.push_back( nt_1); } // handling of zero `b_i's, if any if ( std::find( qp_b, qp_b+qp_m, nt_0) != qp_b+qp_m) { int k = 0; while ( ( k < qp_m) && ( qp_b[ k] == nt_0)) { ++k; } CGAL_optimisation_precondition( k < qp_m); for ( ii = 0; ii < qp_m; ++ii) { if ( qp_b[ ii] == nt_0) { art_A[ k].push_back( std::make_pair( ii, nt_minus_1)); } } }}// set-up of basis and basis inversetemplate < class Rep_ >voidQP_solver<Rep_>::set_up_basis( ){ int ii; // initialize basis (with artificial variables) if ( B.size() > 0) B.clear(); B.insert( B.end(), std::vector<int>::size_type(qp_m), 0); for ( ii = 0; ii < qp_m; ++ii) B[ ii] = qp_n+ii; art_basic = qp_m; CGAL_optimisation_debug { vout1 << " "; vout2 << "initial "; vout << "basis: "; if ( vout.verbose()) { std::copy( B.begin(), B.end(), std::ostream_iterator<int>( vout.out(), " ")); vout.out() << std::endl; } vout3 << "initial basis-inverse:" << std::endl; } // initialize positions in basis if ( in_B.size() > 0) in_B.clear(); in_B.reserve( qp_n+qp_m); in_B.insert( in_B.end(), std::vector<int>::size_type(qp_n), -1); for ( ii = 0; ii < qp_m; ++ii) in_B.push_back( ii); // initialize basis inverse int k = 0; while ( qp_b[ k] == nt_0) { ++k; } std::vector<NT> u, w; u.reserve( qp_m); w.reserve( qp_m); NT u_k = ( qp_b[ k] > nt_0 ? nt_1 : nt_minus_1); /***** NT u_k = nt_0; *****/ for ( ii = 0; ii < qp_m; ++ii) { if ( qp_b[ ii] < nt_0) { u.push_back( nt_minus_1); w.push_back( nt_0); } else { u.push_back( nt_1); w.push_back( qp_b[ ii] > nt_0 ? nt_0 : u_k); } } inv_M_B.init( qp_m, k, u.begin(), w.begin());}// set-up of initial solutiontemplate < class Rep_ >voidQP_solver<Rep_>::set_up_initial_solution( ){ // initialize exact version of `qp_b' (implicit conversion to ET)#ifndef CGAL_CFG_RWSTD_NO_MEMBER_TEMPLATES b = Values( qp_b, qp_b+qp_m);#else b = Values ( qp_m ); std::copy(qp_b, qp_b+qp_m, b.begin());#endif // initialize exact version of `-aux_c' (implicit conversion to ET) minus_c_B.clear(); minus_c_B.reserve( qp_m); std::transform( aux_c.begin()+qp_n, aux_c.end(), std::back_inserter( minus_c_B), std::negate<ET>()); // allocate storage lambda = Values( qp_m); x_B = Values( qp_m); // compute initial solution inv_M_B.multiply( b.begin(), minus_c_B.begin(), lambda.begin(), x_B.begin());}// set-up of additional variablestemplate < class Rep_ >voidQP_solver<Rep_>::set_up_additional_variables( ){ A_j = Values( qp_m); two_D_Bj = Values( qp_m); q_lambda = Values( qp_m); q_x = Values( qp_m); strategyP->init();}// initialization of phase Itemplate < class Rep_ >voidQP_solver<Rep_>::init( ){ CGAL_optimisation_debug { vout2 << std::endl << "--------------" << std::endl << "Initialization" << std::endl << "--------------" << std::endl; } // set up auxiliary problem set_up_auxiliary_problem(); // set up basis and basis inverse set_up_basis(); // set up initial solution set_up_initial_solution(); // set up additional variables set_up_additional_variables(); // set up status m_phase = 1; m_status = UPDATE; m_iterations = 0; is_phase_I = true; CGAL_optimisation_debug { vout2 << std::endl; vout2 << " b: "; if ( vout2.verbose()) { std::copy( b.begin(), b.begin()+qp_m, std::ostream_iterator<ET>( vout2.out(), " ")); vout2.out() << std::endl; } vout2 << " -c_B: "; if ( vout2.verbose()) { std::copy( minus_c_B.begin(), minus_c_B.begin()+B.size(), std::ostream_iterator<ET>( vout2.out(), " ")); vout2.out() << std::endl; } vout2 << "lambda: "; if ( vout2.verbose()) { std::copy( lambda.begin(), lambda.begin()+qp_m, std::ostream_iterator<ET>( vout2.out(), " ")); vout2.out() << std::endl; } vout2 << " x_B: "; if ( vout2.verbose()) { std::copy( x_B.begin(), x_B.begin()+B.size(), std::ostream_iterator<ET>( vout2.out(), " ")); vout2.out() << std::endl; } vout1 << " "; vout2 << std::endl << "initial "; vout << "solution: "; CGAL::Quotient<ET> s = solution(); vout << s << " ~= " << CGAL::to_double( s) << std::endl; } }// transition to phase IItemplate < class Rep_ >voidQP_solver<Rep_>::transition( ){ CGAL_optimisation_debug { vout1 << " t"; vout2 << std::endl << "T"; vout << "ransition to phase II" << std::endl; vout2 << "----------------------" << std::endl; } // remove artificial variables in_B.erase( in_B.begin()+qp_n, in_B.end()); // initialize exact version of `-qp_c' (implicit conversion to ET) Access_c_B access_c_B( qp_c); std::transform( c_B_iterator( B.begin(), access_c_B), c_B_iterator( B.end (), access_c_B), minus_c_B.begin(), std::negate<ET>()); // compute initial solution of phase II inv_M_B.multiply( b.begin(), minus_c_B.begin(), lambda.begin(), x_B.begin()); // update status m_phase = 2; is_phase_I = false; // notify pricing strategy strategyP->transition(); CGAL_optimisation_debug { vout2 << " b: "; if ( vout2.verbose()) { std::copy( b.begin(), b.begin()+qp_m, std::ostream_iterator<ET>( vout2.out(), " ")); vout2.out() << std::endl; } vout2 << " -c_B: "; if ( vout2.verbose()) { std::copy( minus_c_B.begin(), minus_c_B.begin()+B.size(), std::ostream_iterator<ET>( vout2.out(), " ")); vout2.out() << std::endl; } vout2 << "lambda: "; if ( vout2.verbose()) { std::copy( lambda.begin(), lambda.begin()+qp_m, std::ostream_iterator<ET>( vout2.out(), " ")); vout2.out() << std::endl; } vout2 << " x_B: "; if ( vout2.verbose()) { std::copy( x_B.begin(), x_B.begin()+B.size(), std::ostream_iterator<ET>( vout2.out(), " ")); vout2.out() << std::endl; } vout1 << " "; vout2 << std::endl; vout << "solution: "; CGAL::Quotient<ET> s = solution(); vout << s << " ~= " << CGAL::to_double( s) << std::endl; } CGAL_optimisation_assertion( check_basis( Is_lp()));}// access functions// ----------------// numerator of current solutiontemplate < class Rep_ >typename QP_solver<Rep_>::ETQP_solver<Rep_>::solution_numerator( ) const{ Basic_variable_index_iterator i_it, j_it; Basic_variable_numerator_iterator x_i_it, x_j_it; ET s = et_0, sum; int ii; bool is_phase_II = (phase() == 1); // compute c^T x + x^T D x (D is symmetric) // ------------------------------------------ // i: 0..|B|-1 i_it = basic_variables_index_begin(); x_i_it = basic_variables_numerator_begin(); for ( ; i_it != basic_variables_index_end(); ++i_it, ++x_i_it) { sum = et_0; ii = *i_it; if ( ! ( CGAL::check_tag( Is_lp()) || is_phase_II)) { // j: 0..i-1 j_it = basic_variables_index_begin(); x_j_it = basic_variables_numerator_begin(); for ( ; j_it != i_it; ++j_it, ++x_j_it) { // D_{ii,j} x_j sum += ET( qp_D[ ii][ *j_it]) * *x_j_it; } sum *= et_2; // D_{ii,ii} x_i sum += ET( qp_D[ ii][ ii]) * *x_i_it; } // d c_i sum += d * ( is_phase_II ? aux_c[ ii] : qp_c[ ii]); s += sum * *x_i_it; } return s;}// variables of dual LPtemplate < class Rep_ >typename QP_solver<Rep_>::ETQP_solver<Rep_>::dual_variable( int ii) const{ Assert_compile_time_tag( Tag_true(), Is_lp()); Values unity( qp_m), col; unity[ ii] = et_1; col.reserve( qp_m); inv_M_B.multiply_x( unity.begin(), std::back_inserter( col)); return std::inner_product( col.begin(), col.end(), minus_c_B.begin(), et_0);}// pivot function// --------------template < class Rep_ >voidQP_solver<Rep_>::pivot_step( ){ ++m_iterations; CGAL_optimisation_debug { vout2 << std::endl << "----------" << std::endl << "Pivot Step" << std::endl << "----------" << std::endl; vout << "[ phase " << ( is_phase_I ? "I" : "II") << ", iteration " << m_iterations << " ]" << std::endl; } // pricing // ------- pricing(); // check for optimality if ( j < 0 ) { // which phase? if ( is_phase_I) { // phase I // check for infeasibility if ( art_basic > 0 ) { m_phase = 3; m_status = INFEASIBLE; CGAL_optimisation_debug { vout1 << " "; vout << "problem is INFEASIBLE" << std::endl; } } else { // QP feasible, transition to phase II transition(); } } else { // phase II m_phase = 3; m_status = OPTIMAL; CGAL_optimisation_debug { vout1 << " "; vout << "solution is OPTIMAL" << std::endl; } } return; } /* // loop until new basis is found init_ratio_test_update_loop(); do { // ratio test // ---------- ratio_test(); // check for unboundedness if ( q_i == et_0 ) { m_phase = 3; m_status = UNBOUNDED; CGAL_optimisation_debug { vout1 << " "; vout << "problem is UNBOUNDED" << std::endl; } return; } // update // ------ update(); } while ( j >= 0 ); */ // ratio test // ---------- ratio_test(); // check for unboundedness if ( q_i == et_0 ) { m_phase = 3; m_status = UNBOUNDED; CGAL_optimisation_debug { vout1 << " "; vout << "problem is UNBOUNDED" << std::endl; } return; } // update // ------ update(); // loop until new basis is found // ----------------------------- iterated_ratio_test_update(); CGAL_optimisation_debug { vout1 << std::endl << " "; vout1 << "basis: "; if ( vout1.verbose()) { std::copy( B.begin(), B.end(), std::ostream_iterator<int>( vout1.out(), " ")); vout1.out() << std::endl; } vout1 << " "; vout2 << std::endl << "new "; vout << "solution: "; CGAL::Quotient<ET> s = solution(); vout << s << " ~= " << CGAL::to_double( s) << std::endl; } } CGAL_END_NAMESPACE// ===== EOF ==================================================================
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?