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 + -
显示快捷键?