// Copyright (c) 1997-2007  ETH Zurich (Switzerland).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL: https://github.com/CGAL/cgal/blob/v6.1.1/QP_solver/include/CGAL/QP_solver/QP_solver_impl.h $
// $Id: include/CGAL/QP_solver/QP_solver_impl.h 08b27d3db14 $
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s)     : Sven Schoenherr
//                 Bernd Gaertner <gaertner@inf.ethz.ch>
//                 Franz Wessendorp
//                 Kaspar Fischer

#ifndef CGAL_QP_SOLVER_IMPL_H
#define CGAL_QP_SOLVER_IMPL_H

#include <CGAL/license/QP_solver.h>

#include <CGAL/QP_solver/Initialization.h>
#include <CGAL/NT_converter.h>

namespace CGAL {

// =============================
// class implementation (cont'd)
// =============================

// transition (to phase II)
// ------------------------
template < typename Q, typename ET, typename Tags >
void
QP_solver<Q, ET, Tags>::
transition( )
{
    CGAL_qpe_debug {
        if ( vout.verbose()) {
            vout2 << std::endl
                  << "----------------------" << std::endl
                  << 'T';
            vout1 << "[ t"; vout  << "ransition to phase II"; vout1 << " ]";
            vout  << std::endl;
            vout2 << "----------------------";
        }
    }

    // update status
    m_phase    = 2;
    is_phaseI  = false;
    is_phaseII = true;

    // remove artificial variables
    in_B.erase( in_B.begin()+qp_n+slack_A.size(), in_B.end());
    //ensure_size(tmp_x_2, tmp_x.size());
    // update basis inverse
    CGAL_qpe_debug {
        vout4 << std::endl << "basis-inverse:" << std::endl;
    }
    transition( Is_linear());
    CGAL_qpe_debug {
        check_basis_inverse();
    }

    // initialize exact version of `-qp_c' (implicit conversion to ET)
    C_by_index_accessor  c_accessor( qp_c);
    typedef typename std::iterator_traits<C_by_index_iterator>::value_type RT;
    std::transform( C_by_index_iterator( B_O.begin(), c_accessor),
                    C_by_index_iterator( B_O.end  (), c_accessor),
                    minus_c_B.begin(),
                    [](const RT& n){return NT_converter<RT,ET>()(-n);} );

    // compute initial solution of phase II
    compute_solution(Is_nonnegative());

    // diagnostic output
    CGAL_qpe_debug {
        if ( vout.verbose()) print_solution();
    }

    // notify pricing strategy
    strategyP->transition();
}

// access
// ------
// numerator of current solution; the denominator is 2*d*d, so we should
// compute here d*d*(x^T2Dx + x^T2c + 2c0)
template < typename Q, typename ET, typename Tags >
ET QP_solver<Q, ET, Tags>::
solution_numerator( ) const
{
    ET   s, z = et0;
    int  i, j;

    if (check_tag(Is_nonnegative()) || is_phaseI) {
      // standard form or phase I; it suffices to go
      // through the basic variables; all D- and c-entries
      // are obtained through the appropriate iterators
      Index_const_iterator  i_it;
      Value_const_iterator  x_i_it, c_it;

      // foreach i
      x_i_it =       x_B_O.begin();
      c_it = minus_c_B  .begin();
      for ( i_it = B_O.begin(); i_it != B_O.end(); ++i_it, ++x_i_it, ++c_it){
        i = *i_it;

        // compute quadratic part: 2D_i x
        s = et0;
        if ( is_QP && is_phaseII) {
          // half the off-diagonal contribution
          s += std::inner_product(x_B_O.begin(), x_i_it,
                                  D_pairwise_iterator(
                                         B_O.begin(),
                                         D_pairwise_accessor( qp_D, i)),
                                  et0);
          // the other half
          s *= et2;
          // diagonal contribution
          s += ET( (*(qp_D + i))[ i]) * *x_i_it;
        }
        // add linear part: 2c_i
        s -= d * et2 * ET( *c_it);

        // add x_i(2D_i x + 2c_i)
        z += s * *x_i_it; // endowed with a factor of d*d now
      }
    } else {
      // nonstandard form and phase II,
      // take all original variables into account; all D- and c-entries
      // are obtained from the input data directly
      // order in i_it and j_it matches original variable order
      if (is_QP) {
        // quadratic part
        i=0;
        for (Variable_numerator_iterator
               i_it = this->original_variables_numerator_begin();
             i_it < this->original_variables_numerator_end(); ++i_it, ++i) {
          // do something only if *i_it != 0
          if (*i_it == et0) continue;
          s = et0; // contribution of i-th row
          Variable_numerator_iterator j_it =
            this->original_variables_numerator_begin();
          // half the off-diagonal contribution
          j=0;
          for (; j<i; ++j_it, ++j)
            s += ET(*((*(qp_D+i))+j)) * *j_it;
          // the other half
          s *= et2;
          // the diagonal entry
          s += ET(*((*(qp_D+i))+j)) * *j_it;
          // accumulate
          z += s * *i_it;
        }
      }
      // linear part
      j=0; s = et0;
      for (Variable_numerator_iterator
             j_it = this->original_variables_numerator_begin();
           j_it < this->original_variables_numerator_end(); ++j_it, ++j)
        s +=  et2 * ET(*(qp_c+j)) * *j_it;
      z += d * s;
    }
    // finally, add the constant term (phase II only)
    if (is_phaseII) z += et2 * ET(qp_c0) * d * d;
    return z;
}

// pivot step
// ----------
template < typename Q, typename ET, typename Tags >
void
QP_solver<Q, ET, Tags>::
pivot_step( )
{
    ++m_pivots;



    // diagnostic output
    CGAL_qpe_debug {
        vout2 << std::endl
              << "==========" << std::endl
              << "Pivot Step" << std::endl
              << "==========" << std::endl;
    }


    vout  << "[ phase " << ( is_phaseI ? "I" : "II")
          << ", iteration " << m_pivots << " ]" << std::endl;


    // pricing
    // -------
    pricing();


    // check for optimality
    if ( j < 0) {

        if ( is_phaseI) {                               // phase I
            // since we no longer assume full row rank and subsys assumption
            // we have to strengthen the precondition for infeasibility
            if (this->solution_numerator() > et0) {
              // problem is infeasible
                m_phase  = 3;
                m_status = QP_INFEASIBLE;

                vout << "  ";
                vout << "problem is INFEASIBLE" << std::endl;

            } else {  // Drive/remove artificials out of basis
                expel_artificial_variables_from_basis();
                transition();
            }
        } else {                                        // phase II

            // optimal solution found
            m_phase  = 3;
            m_status = QP_OPTIMAL;

            vout << "  ";
            vout  << "solution is OPTIMAL" << std::endl;

        }
        return;
    }


    // ratio test & update (step 1)
    // ----------------------------
    // initialize ratio test
    ratio_test_init();


    // diagnostic output
    CGAL_qpe_debug {
        if ( vout2.verbose() && is_QP && is_phaseII) {
            vout2.out() << std::endl
                        << "----------------------------" << std::endl
                        << "Ratio Test & Update (Step 1)" << std::endl
                        << "----------------------------" << std::endl;
        }
    }

    // loop (step 1)
    do {

        // ratio test
        ratio_test_1();

        // check for unboundedness
        if ( q_i == et0) {
            m_phase  = 3;
            m_status = QP_UNBOUNDED;

            vout << "  ";
            vout << "problem is UNBOUNDED" << std::endl;

            CGAL_qpe_debug {
                //nu should be zero in this case
                // note: (-1)/hat{\nu} is stored instead of \hat{\nu}
                // todo kf: as this is just used for an assertion check,
                // all the following lines should only be executed if
                // assertions are enabled...
                nu = inv_M_B.inner_product(     A_Cj.begin(), two_D_Bj.begin(),
                    q_lambda.begin(),    q_x_O.begin());
                if (is_QP) {
                    if (j < qp_n) {
                        nu -= d*ET(*((*(qp_D+j))+j));
                    }
                }
                CGAL_qpe_assertion(nu == et0);
            }
            return;
        }

        // update
        update_1();

    } while ( j >= 0);

    // ratio test & update (step 2)
    // ----------------------------
/*
    if ( i >= 0) {

        // diagnostic output
        CGAL_qpe_debug {
            vout2 << std::endl
                  << "----------------------------" << std::endl
                  << "Ratio Test & Update (Step 2)" << std::endl
                  << "----------------------------" << std::endl;
        }

        // compute index of entering variable
        j += in_B.size();

        // loop (step 2)
        while ( ( i >= 0) && basis_matrix_stays_regular()) {

            // update
            update_2( Is_linear());

            // ratio test
            ratio_test_2( Is_linear());
        }
    }
*/
    // instead of the above piece of code we now have
    // diagnostic output
    if (is_RTS_transition) {
        is_RTS_transition = false;

        CGAL_qpe_debug {
            vout2 << std::endl
                  << "----------------------------" << std::endl
                  << "Ratio Test & Update (Step 2)" << std::endl
                  << "----------------------------" << std::endl;
        }

        // compute index of entering variable
        j += static_cast<int>(in_B.size());

        ratio_test_2( Is_linear());

        while ((i >= 0) && basis_matrix_stays_regular()) {

            update_2(Is_linear());

            ratio_test_2(Is_linear());

        }
    }



    // ratio test & update (step 3)
    // ----------------------------
    CGAL_qpe_assertion_msg( i < 0, "Step 3 should never be reached!");

    // diagnostic output

    if ( vout.verbose()) print_basis();
    if ( vout.verbose()) print_solution();

    // transition to phase II (if possible)
    // ------------------------------------
    if ( is_phaseI && ( art_basic == 0)) {
        CGAL_qpe_debug {
            if ( vout2.verbose()) {
                vout2.out() << std::endl
                            << "all artificial variables are nonbasic"
                            << std::endl;
            }
        }
        transition();
    }
}

// pricing
template < typename Q, typename ET, typename Tags >
void
QP_solver<Q, ET, Tags>::
pricing( )
{
    // diagnostic output
    CGAL_qpe_debug {
        if ( vout2.verbose()) {
            vout2 << std::endl
                  << "-------" << std::endl
                  << "Pricing" << std::endl
                  << "-------" << std::endl;
        }
    }

    // call pricing strategy
    j = strategyP->pricing(direction);

    // diagnostic output

    if ( vout.verbose()) {
      if ( j < 0) {
        CGAL_qpe_debug {
          vout2 << "entering variable: none" << std::endl;
        }
      } else {
        vout  << "  ";
        vout  << "entering: ";
        vout  << j;
        CGAL_qpe_debug {
          vout2 << " (" << variable_type( j) << ')' << std::endl;
          vout2 << "direction: "
                << ((direction == 1) ? "positive" : "negative") << std::endl;
        }
      }
    }
}

// initialization of ratio-test
template < typename Q, typename ET, typename Tags >
void
QP_solver<Q, ET, Tags>::
ratio_test_init( )
{
    // store exact version of `A_Cj' (implicit conversion)
    ratio_test_init__A_Cj( A_Cj.begin(), j, no_ineq);

    // store exact version of `2 D_{B_O,j}'
    ratio_test_init__2_D_Bj( two_D_Bj.begin(), j, Is_linear());
}

template < typename Q, typename ET, typename Tags >                                         // no ineq.
void  QP_solver<Q, ET, Tags>::
ratio_test_init__A_Cj( Value_iterator A_Cj_it, int j_, Tag_true)
{
    // store exact version of `A_Cj' (implicit conversion)
    if ( j_ < qp_n) {                                   // original variable

        CGAL::transform_n( *(qp_A + j_), qp_m, A_Cj_it,
            NT_converter<A_entry,ET>());

    } else {                                            // artificial variable

        unsigned int  k = j_;
        k -= qp_n;
        std::fill_n( A_Cj_it, qp_m, et0);
        A_Cj_it[ k] = ( art_A[ k].second ? -et1 : et1);
    }
}

template < typename Q, typename ET, typename Tags >                                        // has ineq.
void  QP_solver<Q, ET, Tags>::
ratio_test_init__A_Cj( Value_iterator A_Cj_it, int j_, Tag_false)
{
    // store exact version of `A_Cj' (implicit conversion)
    if ( j_ < qp_n) {                                   // original variable
      A_by_index_accessor  a_accessor( *(qp_A + j_));
      typedef typename std::iterator_traits<A_by_index_iterator>::value_type RT;
      std::transform(A_by_index_iterator( C.begin(), a_accessor),
                     A_by_index_iterator( C.end  (), a_accessor),
                     A_Cj_it,
                     NT_converter<RT,ET>());

    } else {
      unsigned int  k = j_;
      k -= qp_n;
      std::fill_n( A_Cj_it, C.size(), et0);

      if ( k < static_cast<unsigned int>(slack_A.size())) {                      // slack variable

        A_Cj_it[ in_C[ slack_A[ k].first]] = ( slack_A[ k].second ? -et1
                                                                      :  et1);

      } else {                                        // artificial variable
        k -= static_cast<unsigned int>(slack_A.size());

        if ( j_ != art_s_i) {                           // normal art.

          A_Cj_it[ in_C[ art_A[ k].first]] = ( art_A[ k].second ? -et1
                                                                      :  et1);

        } else {                                        // special art.
          S_by_index_accessor  s_accessor( art_s.begin());
          typedef typename std::iterator_traits<S_by_index_iterator>::value_type RT;
          std::transform(S_by_index_iterator( C.begin(), s_accessor),
                         S_by_index_iterator( C.end  (), s_accessor),
                         A_Cj_it,
                         NT_converter<RT,ET>());
        }
      }
    }
}

// ratio test (step 1)
template < typename Q, typename ET, typename Tags >
void
QP_solver<Q, ET, Tags>::
ratio_test_1( )
{

    // diagnostic output
    CGAL_qpe_debug {
        if ( vout2.verbose()) {
            vout2.out() << std::endl;
            if ( is_LP || is_phaseI) {
                vout2.out() << "----------" << std::endl
                            << "Ratio Test" << std::endl
                            << "----------" << std::endl;
            } else {
                vout2.out() << "Ratio Test (Step 1)" << std::endl
                            << "-------------------" << std::endl;
            }
            if ( vout3.verbose()) {
                vout3.out() << "    A_Cj: ";
                std::copy( A_Cj.begin(), A_Cj.begin()+C.size(),
                           std::ostream_iterator<ET>( vout3.out()," "));
                vout3.out() << std::endl;
                if ( is_QP && is_phaseII) {
                    vout3.out() << "  2 D_Bj: ";
                    std::copy( two_D_Bj.begin(), two_D_Bj.begin()+B_O.size(),
                               std::ostream_iterator<ET>( vout3.out()," "));
                    vout3.out() << std::endl;
                }
                vout3.out() << std::endl;
            }
        }
    }

    // compute `q_lambda' and `q_x'
    ratio_test_1__q_x_O( Is_linear());
    ratio_test_1__q_x_S( no_ineq);

    // diagnostic output
    CGAL_qpe_debug {
        if ( vout3.verbose()) {
            if ( is_QP && is_phaseII) {
                vout3.out() << "q_lambda: ";
                std::copy( q_lambda.begin(), q_lambda.begin()+C.size(),
                           std::ostream_iterator<ET>( vout3.out()," "));
                vout3.out() << std::endl;
            }
            vout3.out() << "   q_x_O: ";
            std::copy( q_x_O.begin(), q_x_O.begin()+B_O.size(),
                       std::ostream_iterator<ET>( vout3.out()," "));
            vout3.out() << std::endl;

            if ( has_ineq) {
                vout3.out() << "   q_x_S: ";
                std::copy( q_x_S.begin(), q_x_S.begin()+B_S.size(),
                           std::ostream_iterator<ET>( vout3.out()," "));
                vout3.out() << std::endl;
            }
            vout3.out() << std::endl;
        }
    }

    // check `t_i's
    x_i = et1;                                          // trick: initialize
    q_i = et0;                                          // minimum with +oo

    // computation of t_{min}^{j}
    ratio_test_1__t_min_j(Is_nonnegative());
    CGAL_qpe_debug { // todo kf: at first sight, this debug message should
                     // only be output for problems in nonstandard form...
        if (vout2.verbose()) {
            vout2.out() << "t_min_j: " << x_i << '/' << q_i << std::endl;
            vout2.out() << std::endl;
        }
    }

    // what happens, if all original variables are nonbasic?
/*
    ratio_test_1__t_i(   B_O.begin(),   B_O.end(),
                       x_B_O.begin(), q_x_O.begin(), Tag_false());
    ratio_test_1__t_i(   B_S.begin(),   B_S.end(),
                       x_B_S.begin(), q_x_S.begin(), no_ineq);
*/
    ratio_test_1__t_min_B(no_ineq);

    // check `t_j'
    ratio_test_1__t_j( Is_linear());

    // diagnostic output
    CGAL_qpe_debug {
        if ( vout2.verbose()) {
            for ( unsigned int k = 0; k < static_cast<unsigned int>(B_O.size()); ++k) {
                print_ratio_1_original(k, x_B_O[k], q_x_O[k]);
            }
            if ( has_ineq) {
                for ( unsigned int k = 0; k < static_cast<unsigned int>(B_S.size()); ++k) {
                    /*
                    vout2.out() << "t_S_" << k << ": "
                                    << x_B_S[ k] << '/' << q_x_S[ k]
                                    << ( ( q_i > et0) && ( i == B_S[ k]) ? " *":"")
                                    << std::endl;
                                    */
                                    print_ratio_1_slack(k, x_B_S[k], q_x_S[k]);
                }
            }
            if ( is_QP && is_phaseII) {
                vout2.out() << std::endl
                            << "  t_j: " << mu << '/' << nu
                            << ( ( q_i > et0) && ( i < 0) ? " *" : "")
                            << std::endl;
            }
            vout2.out() << std::endl;
        }
    }
    if ( q_i > et0) {
      if ( i < 0) {
        vout2 << "leaving variable: none" << std::endl;
      } else {
        vout << ", ";
        vout  << "leaving: ";
        vout  << i;
        CGAL_qpe_debug {
          if ( vout2.verbose()) {
            if ( ( i < qp_n) || ( i >= static_cast<int>( qp_n+slack_A.size())) ) {
              vout2.out() << " (= B_O[ " << in_B[ i] << "]: "
                          << variable_type( i) << ')';
            } else {
              vout2.out() << " (= B_S[ " << in_B[ i] << "]: slack)";
            }
          }
          vout2 << std::endl;
        }

      }
    }

}


template < typename Q, typename ET, typename Tags >                         // Standard form
void  QP_solver<Q, ET, Tags>::
ratio_test_1__t_min_j(Tag_true /*is_nonnegative*/)
{
}

// By the pricing step we have the following precondition
// direction == +1 => x_O_v_i[j] == (LOWER v ZERO)
// direction == -1 => x_O_v_i[j] == (UPPER v ZERO)
template < typename Q, typename ET, typename Tags >                         // Upper bounded
void  QP_solver<Q, ET, Tags>::
ratio_test_1__t_min_j(Tag_false /*is_nonnegative*/)
{
    if (j < qp_n) {                                 // original variable
        if (direction == 1) {
            if (x_O_v_i[j] == LOWER) {              // has lower bound value
                if (*(qp_fu+j)) {                   // has finite upper bound
                    x_i = (*(qp_u+j) - *(qp_l+j));
                    q_i = et1;
                    i = j;
                    ratio_test_bound_index = UPPER;
                } else {                            // has infinite upper bound
                    x_i = et1;
                    q_i = et0;
                }
            } else {                                // has value zero
                if (*(qp_fu+j)) {                   // has finite upper bound
                    x_i = *(qp_u+j);
                    q_i = et1;
                    i = j;
                    ratio_test_bound_index = UPPER;
                } else {                            // has infinite upper bound
                    x_i = et1;
                    q_i = et0;
                }
            }
        } else {                                    // direction == -1
            if (x_O_v_i[j] == UPPER) {              // has upper bound value
                if (*(qp_fl+j)) {                   // has finite lower bound
                    x_i = (*(qp_u+j) - *(qp_l+j));
                    q_i = et1;
                    i = j;
                    ratio_test_bound_index = LOWER;
                } else {                            // has infinite lower bound
                    x_i = et1;
                    q_i = et0;
                }
            } else {                                // has value zero
                if (*(qp_fl+j)) {                   // has finite lower bound
                    x_i = -(*(qp_l+j));
                    q_i = et1;
                    i = j;
                    ratio_test_bound_index = LOWER;
                } else {                            // has infinite lower bound
                    x_i = et1;
                    q_i = et0;
                }
            }
        }
    } else {                                        // slack or artificial var
        x_i = et1;
        q_i = et0;
    }
}

template < typename Q, typename ET, typename Tags >
void  QP_solver<Q, ET, Tags>::
ratio_test_1__t_min_B(Tag_true  /*has_equalities_only_and_full_rank*/)
{
    ratio_test_1_B_O__t_i(B_O.begin(), B_O.end(), x_B_O.begin(),
                        q_x_O.begin(), Is_nonnegative());
}

template < typename Q, typename ET, typename Tags >
void  QP_solver<Q, ET, Tags>::
ratio_test_1__t_min_B(Tag_false /*has_equalities_only_and_full_rank*/)
{
    ratio_test_1_B_O__t_i(B_O.begin(), B_O.end(), x_B_O.begin(),
                        q_x_O.begin(), Is_nonnegative());
    ratio_test_1_B_S__t_i(B_S.begin(), B_S.end(), x_B_S.begin(),
                        q_x_S.begin(), Is_nonnegative());
}

// ratio test for the basic original variables
template < typename Q, typename ET, typename Tags >                         // Standard form
void  QP_solver<Q, ET, Tags>::
ratio_test_1_B_O__t_i(Index_iterator i_it, Index_iterator end_it,
                    Value_iterator x_it, Value_iterator q_it,
                    Tag_true  /*is_nonnegative*/)
{
    for ( ; i_it != end_it; ++i_it, ++x_it, ++q_it ) {
        test_implicit_bounds_dir_pos(*i_it, *x_it, *q_it, i, x_i, q_i);
    }
}

// ratio test for the basic original variables
template < typename Q, typename ET, typename Tags >                         // Upper bounded
void  QP_solver<Q, ET, Tags>::
ratio_test_1_B_O__t_i(Index_iterator i_it, Index_iterator end_it,
                    Value_iterator x_it, Value_iterator q_it,
                    Tag_false /*is_nonnegative*/)
{
    if (is_phaseI) {
        if (direction == 1) {
            for ( ; i_it != end_it; ++i_it, ++x_it, ++q_it ) {
                test_mixed_bounds_dir_pos(*i_it, *x_it, *q_it, i, x_i, q_i);
            }
        } else {
            for ( ; i_it != end_it; ++i_it, ++x_it, ++q_it ) {
                test_mixed_bounds_dir_neg(*i_it, *x_it, *q_it, i, x_i, q_i);
            }
        }
    } else {
        if (direction == 1) {
            for ( ; i_it != end_it; ++i_it, ++x_it, ++q_it ) {
                test_explicit_bounds_dir_pos(*i_it, *x_it, *q_it, i, x_i, q_i);
            }
        } else {
            for ( ; i_it != end_it; ++i_it, ++x_it, ++q_it ) {
                test_explicit_bounds_dir_neg(*i_it, *x_it, *q_it, i, x_i, q_i);
            }
        }
    }
}

// ratio test for the basic slack variables
template < typename Q, typename ET, typename Tags >                         // Standard form
void  QP_solver<Q, ET, Tags>::
ratio_test_1_B_S__t_i(Index_iterator i_it, Index_iterator end_it,
                Value_iterator x_it, Value_iterator q_it,
                Tag_true  /*is_nonnegative*/)
{
    for ( ; i_it != end_it; ++i_it, ++x_it, ++q_it ) {
        test_implicit_bounds_dir_pos(*i_it, *x_it, *q_it, i, x_i, q_i);
    }
}

// ratio test for the basic slack variables
template < typename Q, typename ET, typename Tags >                         // Upper bounded
void  QP_solver<Q, ET, Tags>::
ratio_test_1_B_S__t_i(Index_iterator i_it, Index_iterator end_it,
                Value_iterator x_it, Value_iterator q_it,
                Tag_false /*is_nonnegative*/)
{
    if (direction == 1) {
        for ( ; i_it != end_it; ++i_it, ++x_it, ++q_it ) {
            test_implicit_bounds_dir_pos(*i_it, *x_it, *q_it, i, x_i, q_i);
        }
    } else {
        for ( ; i_it != end_it; ++i_it, ++x_it, ++q_it ) {
            test_implicit_bounds_dir_neg(*i_it, *x_it, *q_it, i, x_i, q_i);
        }
    }
}

// test for one basic variable with implicit bounds only,
// note that this function writes the member variables i, x_i, q_i
template < typename Q, typename ET, typename Tags >
void  QP_solver<Q, ET, Tags>::
test_implicit_bounds_dir_pos(int k, const ET& x_k, const ET& q_k,
                                int& i_min, ET& d_min, ET& q_min)
{
    if (q_k > et0) {
      // BLAND rule: In case the ratios are the same, only update if the new index
      // is smaller. The special artificial variable is always made to leave first.
      if ((x_k * q_min < d_min * q_k) || ((k < i_min) && (i_min != art_s_i) && (x_k * q_min == d_min * q_k)) ) {
        i_min = k;
        d_min = x_k;
        q_min = q_k;
      }
    }
}

// test for one basic variable with implicit bounds only,
// note that this function writes the member variables i, x_i, q_i
template < typename Q, typename ET, typename Tags >
void  QP_solver<Q, ET, Tags>::
test_implicit_bounds_dir_neg(int k, const ET& x_k, const ET& q_k,
                                int& i_min, ET& d_min, ET& q_min)
{
    if (q_k < et0) {
      // BLAND rule: In case the ratios are the same, only update if the new index
      // is smaller. The special artificial variable is always made to leave first.
      if ((x_k * q_min < -(d_min * q_k)) || ((k < i_min) && (i_min != art_s_i) && (x_k * q_min == -(d_min * q_k))) ) {
        i_min = k;
        d_min = x_k;
        q_min = -q_k;
      }
    }
}

// test for one basic variable with explicit bounds only,
// note that this function writes the member variables i, x_i, q_i and
// ratio_test_bound_index, although the second and third variable name
// are in the context of upper bounding misnomers
template < typename Q, typename ET, typename Tags >
void  QP_solver<Q, ET, Tags>::
test_explicit_bounds_dir_pos(int k, const ET& x_k, const ET& q_k,
                                int& i_min, ET& d_min, ET& q_min)
{
    if (q_k > et0) {                                // check for lower bound
        if (*(qp_fl+k)) {
            ET  diff = x_k - (d * ET(*(qp_l+k)));
            // BLAND rule: In case the ratios are the same, only update if the new index
            // is smaller. The special artificial variable is always made to leave first.
            if ((diff * q_min < d_min * q_k) || ((k < i_min) && (i_min != art_s_i) && (diff * q_min == d_min * q_k)) ) {
                i_min = k;
                d_min = diff;
                q_min = q_k;
                ratio_test_bound_index = LOWER;
            }
        }
    } else {                                        // check for upper bound
        if ((q_k < et0) && (*(qp_fu+k))) {
            ET  diff = (d * ET(*(qp_u+k))) - x_k;
            // BLAND rule: In case the ratios are the same, only update if the new index
            // is smaller. The special artificial variable is always made to leave first.
            if ((diff * q_min < -(d_min * q_k)) || ((k < i_min) && (i_min != art_s_i) && (diff * q_min == -(d_min * q_k))) ) {
                i_min = k;
                d_min = diff;
                q_min = -q_k;
                ratio_test_bound_index = UPPER;
            }
        }
    }
}

// test for one basic variable with explicit bounds only,
// note that this function writes the member variables i, x_i, q_i and
// ratio_test_bound_index, although the second and third variable name
// are in the context of upper bounding misnomers
template < typename Q, typename ET, typename Tags >
void  QP_solver<Q, ET, Tags>::
test_explicit_bounds_dir_neg(int k, const ET& x_k, const ET& q_k,
                                int& i_min, ET& d_min, ET& q_min)
{
    if (q_k < et0) {                                // check for lower bound
        if (*(qp_fl+k)) {
            ET  diff = x_k - (d * ET(*(qp_l+k)));
            // BLAND rule: In case the ratios are the same, only update if the new index
            // is smaller. The special artificial variable is always made to leave first.
            if ((diff * q_min < -(d_min * q_k)) || ((k < i_min) && (i_min != art_s_i) && (diff * q_min == -(d_min * q_k))) ) {
                i_min = k;
                d_min = diff;
                q_min = -q_k;
                ratio_test_bound_index = LOWER;
            }
        }
    } else {                                        // check for upper bound
        if ((q_k > et0) && (*(qp_fu+k))) {
            ET  diff = (d * ET(*(qp_u+k))) - x_k;
            // BLAND rule: In case the ratios are the same, only update if the new index
            // is smaller. The special artificial variable is always made to leave first.
            if ((diff * q_min < d_min * q_k) || ((k < i_min) && (i_min != art_s_i) && (diff * q_min == d_min * q_k)) ) {
                i_min = k;
                d_min = diff;
                q_min = q_k;
                ratio_test_bound_index = UPPER;
            }
        }
    }
}

// test for one basic variable with mixed bounds,
// note that this function writes the member variables i, x_i, q_i and
// ratio_test_bound_index, although the second and third variable name
// are in the context of upper bounding misnomers
template < typename Q, typename ET, typename Tags >
void  QP_solver<Q, ET, Tags>::
test_mixed_bounds_dir_pos(int k, const ET& x_k, const ET& q_k,
                                int& i_min, ET& d_min, ET& q_min)
{
    if (q_k > et0) {                                // check for lower bound
        if (k < qp_n) {                             // original variable
            if (*(qp_fl+k)) {
                ET  diff = x_k - (d * ET(*(qp_l+k)));
                // BLAND rule: In case the ratios are the same, only update if the new index
                // is smaller. The special artificial variable is always made to leave first.
                if ((diff * q_min < d_min * q_k) || ((k < i_min) && (i_min != art_s_i) && (diff * q_min == d_min * q_k))) {
                  i_min = k;
                  d_min = diff;
                  q_min = q_k;
                  ratio_test_bound_index = LOWER;
              } // phase  I II switch

            }
        } else {                                    // artificial variable
            // BLAND rule: In case the ratios are the same, only update if the new index
            // is smaller. The special artificial variable is always made to leave first.
            if ((x_k * q_min < d_min * q_k) || ((k < i_min) && (i_min != art_s_i) && (x_k * q_min == d_min * q_k))) {
                i_min = k;
                d_min = x_k;
                q_min = q_k;
            }
        }
    } else {                                        // check for upper bound
        if ((q_k < et0) && (k < qp_n) && *(qp_fu+k)) {
            ET  diff = (d * ET(*(qp_u+k))) - x_k;
            // BLAND rule: In case the ratios are the same, only update if the new index
            // is smaller. The special artificial variable is always made to leave first.
            if ((diff * q_min < -(d_min * q_k)) || ((k < i_min) && (i_min != art_s_i) && (diff * q_min == -(d_min * q_k))) ) {
                i_min = k;
                d_min = diff;
                q_min = -q_k;
                ratio_test_bound_index = UPPER;
            }
        }
    }
}

// test for one basic variable with mixed bounds,
// note that this function writes the member variables i, x_i, q_i and
// ratio_test_bound_index, although the second and third variable name
// are in the context of upper bounding misnomers
template < typename Q, typename ET, typename Tags >
void  QP_solver<Q, ET, Tags>::
test_mixed_bounds_dir_neg(int k, const ET& x_k, const ET& q_k,
                                int& i_min, ET& d_min, ET& q_min)
{
    if (q_k < et0) {                                // check for lower bound
        if (k < qp_n) {                             // original variable
            if (*(qp_fl+k)) {
                ET  diff = x_k - (d * ET(*(qp_l+k)));
                // BLAND rule: In case the ratios are the same, only update if the new index
                // is smaller. The special artificial variable is always made to leave first.
                if ((diff * q_min < -(d_min * q_k)) || ((k < i_min) && (i_min != art_s_i) && (diff * q_min == -(d_min * q_k))) ) {
                    i_min = k;
                    d_min = diff;
                    q_min = -q_k;
                    ratio_test_bound_index = LOWER;
                }
            }
        } else {                                    // artificial variable
            // BLAND rule: In case the ratios are the same, only update if the new index
            // is smaller. The special artificial variable is always made to leave first.
            if ((x_k * q_min < -(d_min * q_k)) || ((k < i_min) && (i_min != art_s_i) && (x_k * q_min == -(d_min * q_k))) ) {
                i_min = k;
                d_min = x_k;
                q_min = -q_k;
            }
        }
    } else {                                        // check for upper bound
        if ((q_k > et0) && (k < qp_n) && *(qp_fu+k)) {
            ET  diff = (d * ET(*(qp_u+k))) - x_k;
            // BLAND rule: In case the ratios are the same, only update if the new index
            // is smaller. The special artificial variable is always made to leave first.
            if ((diff * q_min < d_min * q_k) || ((k < i_min) && (i_min != art_s_i) && (diff * q_min == d_min * q_k)) ) {
                i_min = k;
                d_min = diff;
                q_min = q_k;
                ratio_test_bound_index = UPPER;
            }
        }
    }
}


template < typename Q, typename ET, typename Tags >                                         // QP case
void
QP_solver<Q, ET, Tags>::
ratio_test_2( Tag_false)
{
    // diagnostic output
    CGAL_qpe_debug {
        if ( vout2.verbose()) {
            vout2.out() << std::endl
                        << "Ratio Test (Step 2)" << std::endl
                        << "-------------------" << std::endl;
        }
    }

    // compute `p_lambda' and `p_x' (Note: `p_...' is stored in `q_...')
    ratio_test_2__p( no_ineq);

    // diagnostic output
    CGAL_qpe_debug {
        if ( vout3.verbose()) {
            vout3.out() << "p_lambda: ";
            std::copy( q_lambda.begin(), q_lambda.begin()+C.size(),
                       std::ostream_iterator<ET>( vout3.out()," "));
            vout3.out() << std::endl;
            vout3.out() << "   p_x_O: ";
            std::copy( q_x_O.begin(), q_x_O.begin()+B_O.size(),
                       std::ostream_iterator<ET>( vout3.out()," "));
            vout3.out() << std::endl;
            if ( has_ineq) {
                vout3.out() << "   p_x_S: ";
                std::copy( q_x_S.begin(), q_x_S.begin()+B_S.size(),
                           std::ostream_iterator<ET>( vout3.out()," "));
                vout3.out() << std::endl;
            }
            vout3.out() << std::endl;
        }
    }

    // Idea here: At this point, the goal is to increase \mu_j until either we
    // become optimal (\mu_j=0), or one of the variables in x^*_\hat{B} drops
    // down to zero.
    //
    // Let us see first how this is done in the standard-form case (where
    // Sven's thesis applies).  Eq. (2.11) in Sven's thesis holds, and by
    // multlying it by $M_\hat{B}^{-1}$ we obtain an equation for \lambda and
    // x^*_\hat{B}.  The interesting equation (the one for x^*_\hat{B}) looks
    // more or less as follows:
    //
    //    x(mu_j)      = x(0) + mu_j      q_it                          (1)
    //
    // where q_it is the vector from (2.12).  In paritcular, for
    // mu_j=mu_j(t_1) (i.e., if we plug the value of mu_j at the beginning of
    // this ratio step 2 into (1)) we have
    //
    //    x(mu_j(t_1)) = x(0) + mu_j(t_1) q_it                          (2)
    //
    // where x(mu_j(t_1)) is the current solution of the solver at this point
    // (i.e., at the beginning of ratio step 2).
    //
    // By subtracting (2) from (1) we can thus eliminate the "unknown" x(0)
    // (which is cheaper than computing it):
    //
    //    x(mu_j) = x(mu_j(t_1)) + (mu_j-mu_j(t_1)) q_it
    //                             ----------------
    //                                  := delta
    //
    // In order to compute for each variable x_k in \hat{B} the value of mu_j
    // for which x_k(mu_j) = 0, we thus evaluate
    //
    //                x(mu_j(t_1))_k
    //    delta_k:= - --------------
    //                    q_it_k
    //
    // The first variable in \hat{B} that hits zero "in the future" is then
    // the one whose delta_k equals
    //
    //    delta_min:= min {delta_k | k in \hat{B} and (q_it)_k < 0 }
    //
    // So in order to handle the standard-form case, we would compute this
    // minimum.  Once we have delta_min, we need to check whether we get
    // optimal BEFORE a variable drops to zero.  As delta = mu_j - mu_j(t_1),
    // the latter is precisely the case if delta_min >= -mu_j(t_1).
    //
    // (Note: please forget the crap identity between (2.11) and (2.12); the
    // notation is misleading.)
    //
    // Now to the nonstandard-form case.

    // fw: By definition delta_min >= 0, such that initializing
    // delta_min with -mu_j(t_1) has the desired effect that a basic variable
    // is leaving only if 0 <= delta_min < -mu_j(t_1).
    //
    // The only initialization of delta_min as fraction x_i/q_i that works is
    // x_i=mu_j(t_1); q_i=-1; (see below).
    //
    // Since mu_j(t_1) has been computed in ratio test step 1 we can
    // reuse it.

    x_i = mu;                                     // initialize minimum
    q_i = -et1;                                        // with -mu_j(t_1)

    Value_iterator  x_it = x_B_O.begin();
    Value_iterator  q_it = q_x_O.begin();
    Index_iterator  i_it;
    for ( i_it = B_O.begin(); i_it != B_O.end(); ++i_it, ++x_it, ++q_it) {
      // BLAND rule: In case the ratios are the same, only update if the new index
      // is smaller. The special artificial variable is always made to leave first.
      if ( (*q_it < et0) && (
              (( *x_it * q_i) < ( x_i * *q_it)) ||
              ( (*i_it < i) && (i != art_s_i) && (( *x_it * q_i) == ( x_i * *q_it)) )
            )
          ) {
        i = *i_it; x_i = *x_it; q_i = *q_it;
      }
    }
    x_it = x_B_S.begin();
    q_it = q_x_S.begin();
    for ( i_it = B_S.begin(); i_it != B_S.end(); ++i_it, ++x_it, ++q_it) {
      // BLAND rule: In case the ratios are the same, only update if the new index
      // is smaller. The special artificial variable is always made to leave first.
      if ( ( *q_it < et0) && (
             (( *x_it * q_i) < ( x_i * *q_it)) ||
             ( (*i_it < i) && (i != art_s_i) && (( *x_it * q_i) == ( x_i * *q_it)) )
            )
          ){
          i = *i_it; x_i = *x_it; q_i = *q_it;
      }
    }

    CGAL_qpe_debug {
        if ( vout2.verbose()) {
            for ( unsigned int k = 0; k < static_cast<unsigned int>(B_O.size()); ++k) {
                vout2.out() << "mu_j_O_" << k << ": - "
                            << x_B_O[ k] << '/' << q_x_O[ k]
                            << ( ( q_i < et0) && ( i == B_O[ k]) ? " *" : "")
                            << std::endl;
            }
            for ( unsigned int k = 0; k < static_cast<unsigned int>(B_S.size()); ++k) {
                vout2.out() << "mu_j_S_" << k << ": - "
                            << x_B_S[ k] << '/' << q_x_S[ k]
                            << ( ( q_i < et0) && ( i == B_S[ k]) ? " *" : "")
                            << std::endl;
            }
            vout2.out() << std::endl;
        }
    }
    if ( i < 0) {
      vout2 << "leaving variable: none" << std::endl;
    } else {
      vout1 << ", ";
      vout  << "leaving"; vout2 << " variable"; vout << ": ";
      vout  << i;
      if ( vout2.verbose()) {
        if ( i < qp_n) {
          vout2.out() << " (= B_O[ " << in_B[ i] << "]: original)"
                      << std::endl;
        } else {
          vout2.out() << " (= B_S[ " << in_B[ i] << "]: slack)"
                      << std::endl;
        }
      }
    }

}

// update (step 1)
template < typename Q, typename ET, typename Tags >
void
QP_solver<Q, ET, Tags>::
update_1( )
{
    CGAL_qpe_debug {
        if ( vout2.verbose()) {
            vout2.out() << std::endl;
            if ( is_LP || is_phaseI) {
                vout2.out() << "------" << std::endl
                            << "Update" << std::endl
                            << "------" << std::endl;
            } else {
                vout2.out() << "Update (Step 1)" << std::endl
                            << "---------------" << std::endl;
            }
        }
    }

    // update basis & basis inverse
    update_1( Is_linear());
    CGAL_qpe_assertion(check_basis_inverse());

    // check the updated vectors r_C and r_S_B
    CGAL_expensive_assertion(check_r_C(Is_nonnegative()));
    CGAL_expensive_assertion(check_r_S_B(Is_nonnegative()));

    // check the vectors r_B_O and w in phaseII for QPs
    CGAL_qpe_debug {
        if (is_phaseII && is_QP) {
            CGAL_expensive_assertion(check_r_B_O(Is_nonnegative()));
            CGAL_expensive_assertion(check_w(Is_nonnegative()));
        }
    }

    // compute current solution
    compute_solution(Is_nonnegative());

    // check feasibility
    CGAL_qpe_debug {
      if (j < 0 && !is_RTS_transition) // todo kf: is this too conservative?
                 // Note: the above condition is necessary because of the
                 // following.  In theory, it is true that the current
                 // solution is at this point in the solver always
                 // feasible. However, the solution has its x_j-entry equal to
                 // the current t from the pricing, and is not zero (in the
                 // standard-form case) or the current lower/upper bound
                 // of the variable (in the non-standard-form case), resp., as
                 // the routines is_solution_feasible() and
                 // is_solution_feasible_for_auxiliary_problem() assume.
        if (is_phaseI) {
          CGAL_expensive_assertion(
            is_solution_feasible_for_auxiliary_problem());
        } else {
          CGAL_expensive_assertion(is_solution_feasible());
        }
      else
        vout2 << "(feasibility not checked in intermediate step)" << std::endl;
      CGAL_expensive_assertion(check_tag(Is_nonnegative()) ||
                               r_C.size() == C.size());
    }

}

// update (step 2)
template < typename Q, typename ET, typename Tags >                                         // QP case
void
QP_solver<Q, ET, Tags>::
update_2( Tag_false)
{
    CGAL_qpe_debug {
        vout2 << std::endl
              << "Update (Step 2)" << std::endl
              << "---------------" << std::endl;
    }

    // leave variable from basis
    leave_variable();
    CGAL_qpe_debug {
        check_basis_inverse();
    }

    // check the updated vectors r_C, r_S_B, r_B_O and w
    CGAL_expensive_assertion(check_r_C(Is_nonnegative()));
    CGAL_expensive_assertion(check_r_S_B(Is_nonnegative()));
    CGAL_expensive_assertion(check_r_B_O(Is_nonnegative()));
    CGAL_expensive_assertion(check_w(Is_nonnegative()));

    // compute current solution
    compute_solution(Is_nonnegative());
}

template < typename Q, typename ET, typename Tags >
void
QP_solver<Q, ET, Tags>::
expel_artificial_variables_from_basis( )
{
    int row_ind;
    ET r_A_Cj;

    CGAL_qpe_debug {
        vout2 << std::endl
              << "---------------------------------------------" << std::endl
              << "Expelling artificial variables from the basis" << std::endl
              << "---------------------------------------------" << std::endl;
    }



    for (unsigned int i_ = 0; i_ < static_cast<unsigned int>(qp_n + slack_A.size()); ++i_) {
      if (!is_basic(i_)) {
      ratio_test_init__A_Cj( A_Cj.begin(), i_, no_ineq);
      }
    }


    // try to pivot the artificials out of the basis
    // Note that we do not notify the pricing strategy about variables
    // leaving the basis, furthermore the pricing strategy does not
    // know about variables entering the basis.
    // The partial pricing strategies that keep the set of nonbasic vars
    // explicitly are synchronized during transition from phaseI to phaseII
    for (unsigned int i_ = static_cast<unsigned int>(qp_n + slack_A.size()); i_ < static_cast<unsigned int>(in_B.size()); ++i_) {
      if (is_basic(i_)) {                                         // is basic
        row_ind = in_B[i_];

        //CGAL_qpe_assertion(row_ind >= 0);


        // determine first possible entering variable,
        // if there is any
        for (unsigned int j_ = 0; j_ < static_cast<unsigned int>(qp_n + slack_A.size()); ++j_) {
                if (!is_basic(j_)) {                                  // is nonbasic
            ratio_test_init__A_Cj( A_Cj.begin(), j_, no_ineq);

            r_A_Cj = inv_M_B.inv_M_B_row_dot_col(row_ind, A_Cj.begin());

            if (r_A_Cj != et0) {
              ratio_test_1__q_x_O(Is_linear());
              i = i_;
              j = j_;
              update_1(Is_linear());
              break;
            }
          }
        }
      }
    }

    if ((art_basic != 0) && no_ineq) {
      // the vector in_C was not used in phase I, but now we remove redundant
      // constraints and switch to has_ineq treatment, hence we need it to
      // be correct at this stage
      for (int i=0; i<qp_m; ++i)
        in_C.push_back(i);
      }
      diagnostics.redundant_equations = (art_basic != 0);

      // now reset the no_ineq and has_ineq flags to match the situation
      no_ineq = no_ineq && !diagnostics.redundant_equations;
      has_ineq = !no_ineq;

      // remove the remaining ones with their corresponding equality constraints
      // Note: the special artificial variable can always be driven out of the
      // basis
      for (unsigned int i_ = static_cast<unsigned int>(qp_n + slack_A.size()); i_ < static_cast<unsigned int>(in_B.size()); ++i_) {
        if (in_B[i_] >= 0) {
          i = i_;
          CGAL_qpe_debug {
            vout2 << std::endl
            << "~~> removing artificial variable " << i
            << " and its equality constraint" << std::endl
            << std::endl;
          }
        remove_artificial_variable_and_constraint();
      }
    }
}


// replace variable in basis
template < typename Q, typename ET, typename Tags >
void
QP_solver<Q, ET, Tags>::
replace_variable( )
{
    CGAL_qpe_debug {
        vout2 <<   "<--> nonbasic (" << variable_type( j) << ") variable " << j
              << " replaces basic (" << variable_type( i) << ") variable " << i
              << std::endl << std::endl;
    }

    // replace variable
    replace_variable( no_ineq);

    // pivot step done
    i = j = -1;
}

template < typename Q, typename ET, typename Tags >
void  QP_solver<Q, ET, Tags>::
replace_variable_original_original( )
{
    // updates for the upper bounded case
    replace_variable_original_original_upd_r(Is_nonnegative());

    int  k = in_B[ i];

    // replace original variable [ in: j | out: i ]
    in_B  [ i] = -1;
    in_B  [ j] = k;
       B_O[ k] = j;

    minus_c_B[ k] =
      ( is_phaseI ?
        ( j < qp_n ? et0 : ET(-aux_c[j-qp_n-slack_A.size()])) : -ET( *(qp_c+ j)));

    if ( is_phaseI) {
        if ( j >= qp_n) ++art_basic;
        if ( i >= qp_n) --art_basic;
    }

    // diagnostic output
    CGAL_qpe_debug {
        if ( vout2.verbose()) print_basis();
    }

    // update basis inverse
    inv_M_B.enter_original_leave_original( q_x_O.begin(), k);
}

// update of the vector r for U_5 with upper bounding, note that we
// need the headings C, and S_{B} before they are updated
template < typename Q, typename ET, typename Tags >                            // Standard form
void  QP_solver<Q, ET, Tags>::
replace_variable_original_original_upd_r(Tag_true )
{
}

// update of the vector r for U_5 with upper bounding, note that we
// need the headings C, and S_{B} before they are updated
template < typename Q, typename ET, typename Tags >                            // Upper bounded
void  QP_solver<Q, ET, Tags>::
replace_variable_original_original_upd_r(Tag_false )
{
    ET      x_j, x_i;

    if (is_artificial(j)) {
        if (!is_artificial(i)) {
            x_i = (ratio_test_bound_index == LOWER) ? *(qp_l+i) : *(qp_u+i);
            update_r_C_r_S_B__i(x_i);
            // update x_O_v_i
            x_O_v_i[i] = ratio_test_bound_index;
        }
    } else {
        x_j = nonbasic_original_variable_value(j);
        if (is_artificial(i)) {
            update_r_C_r_S_B__j(x_j);
        } else {
            x_i = (ratio_test_bound_index == LOWER) ? *(qp_l+i) : *(qp_u+i);
            update_r_C_r_S_B__j_i(x_j, x_i);
            // update x_O_v_i
            x_O_v_i[i] = ratio_test_bound_index;
        }
        // update x_O_v_i
        x_O_v_i[j] = BASIC;
    }
}


template < typename Q, typename ET, typename Tags >
void  QP_solver<Q, ET, Tags>::
replace_variable_slack_slack( )
{

    // updates for the upper bounded case
    replace_variable_slack_slack_upd_r(Is_nonnegative());

    int  k = in_B[ i];

    // replace slack variable [ in: j | out: i ]
    in_B  [ i] = -1;
    in_B  [ j] = k;
       B_S[ k] = j;
       S_B[ k] = slack_A[ j-qp_n].first;

    // replace inequality constraint [ in: i | out: j ]
    int old_row = S_B[ k];
    int new_row = slack_A[ i-qp_n].first;
    k = in_C[ old_row];

    in_C[ old_row] = -1;
    in_C[ new_row] = k;
       C[ k      ] = new_row;

     b_C[ k] = ET( *(qp_b+ new_row));

    // diagnostic output
    CGAL_qpe_debug {
        if ( vout2.verbose()) print_basis();
    }

    // update basis inverse
    A_row_by_index_accessor  a_accessor =
      [new_row, this](int i){ return A_accessor( this->qp_A, 0, this->qp_n)(i, new_row); };
    typedef typename std::iterator_traits<A_row_by_index_iterator>::value_type RT;
    std::transform(A_row_by_index_iterator( B_O.begin(), a_accessor),
                   A_row_by_index_iterator( B_O.end  (), a_accessor),
                   tmp_x.begin(),
                   NT_converter<RT,ET>());
    if ( art_s_i > 0) {                                 // special artificial
        tmp_x[ in_B[ art_s_i]] = ET( art_s[ new_row]);
    }
    inv_M_B.enter_slack_leave_slack( tmp_x.begin(), k);
}

// update of the vector r for U_6 with upper bounding, note that we
// need the headings C, and S_{B} before they are updated
template < typename Q, typename ET, typename Tags >                            // Standard form
void  QP_solver<Q, ET, Tags>::
replace_variable_slack_slack_upd_r(Tag_true )
{
}

// update of the vector r for U_6 with upper bounding, note that we
// need the headings C, and S_{B} before they are updated
template < typename Q, typename ET, typename Tags >                            // Upper bounded
void  QP_solver<Q, ET, Tags>::
replace_variable_slack_slack_upd_r(Tag_false )
{
    int     sigma_j = slack_A[ j-qp_n].first;

    // swap r_gamma_C(sigma_j) in r_C with r_gamma_S_B(sigma_i) in r_S_B
    std::swap(r_C[in_C[sigma_j]], r_S_B[in_B[i]]);
}


template < typename Q, typename ET, typename Tags >
void  QP_solver<Q, ET, Tags>::
replace_variable_slack_original( )
{
    // updates for the upper bounded case
    replace_variable_slack_original_upd_r(Is_nonnegative());

    int  k = in_B[ i];

    // leave original variable [ out: i ]
    in_B  [ B_O.back()] = k;
       B_O[ k] = B_O.back();
       in_B  [ i         ] = -1;
       B_O.pop_back();

    minus_c_B[ k] = minus_c_B[ B_O.size()];

    if ( is_phaseI && ( i >= qp_n)) --art_basic;

    // enter slack variable [ in: j ]
    int  old_row = slack_A[ j-qp_n].first;
    in_B  [ j] = static_cast<int>(B_S.size());
       B_S.push_back( j);
       S_B.push_back( old_row);

    // leave inequality constraint [ out: j ]
    int  l = in_C[ old_row];
     b_C[ l       ] = b_C[ C.size()-1];
       C[ l       ] = C.back();
    in_C[ C.back()] = l;
    in_C[ old_row ] = -1;
       C.pop_back();
    // diagnostic output
    CGAL_qpe_debug {
        if ( vout2.verbose()) print_basis();
    }

    // update basis inverse
    inv_M_B.swap_variable( k);
    inv_M_B.swap_constraint( l);
    inv_M_B.enter_slack_leave_original();
}

// update of the vector r for U_8 with upper bounding, note that we
// need the headings C, and S_{B} before they are updated
template < typename Q, typename ET, typename Tags >                            // Standard form
void  QP_solver<Q, ET, Tags>::
replace_variable_slack_original_upd_r(Tag_true )
{
}

// update of the vector r for U_8 with upper bounding, note that we
// need the headings C, and S_{B} before they are updated
template < typename Q, typename ET, typename Tags >                            // Upper bounded
void  QP_solver<Q, ET, Tags>::
replace_variable_slack_original_upd_r(Tag_false )
{
    if (!is_artificial(i)) {
        ET  x_i = (ratio_test_bound_index == LOWER) ? *(qp_l+i) : *(qp_u+i);
        update_r_C_r_S_B__i(x_i);
    }

    int     sigma_j = slack_A[ j-qp_n].first;

    // append r_gamma_C(sigma_j) from r_C to r_S_B:
    r_S_B.push_back(r_C[in_C[sigma_j]]);

    // remove r_gamma_C(sigma_j) from r_C:
    r_C[in_C[sigma_j]] = r_C.back();
    r_C.pop_back();

    // update x_O_v_i
    if (!is_artificial(i)) // original and not artificial?
      x_O_v_i[i] = ratio_test_bound_index;
}


template < typename Q, typename ET, typename Tags >
void  QP_solver<Q, ET, Tags>::
replace_variable_original_slack( )
{
    // updates for the upper bounded case
    replace_variable_original_slack_upd_r(Is_nonnegative());

    int  k = in_B[ i];

    // enter original variable [ in: j ]

    minus_c_B[ B_O.size()]
      = ( is_phaseI ?
          ( j < qp_n ? et0 : ET(-aux_c[j-qp_n-slack_A.size()]))
          : -ET( *(qp_c+ j)));


    in_B  [ j] = static_cast<int>(B_O.size());
       B_O.push_back( j);

    if ( is_phaseI && ( j >= qp_n)) ++art_basic;

    // leave slack variable [ out: i ]
       B_S[ k         ] = B_S.back();
       S_B[ k         ] = S_B.back();
    in_B  [ B_S.back()] = k;
    in_B  [ i         ] = -1;
       B_S.pop_back();
       S_B.pop_back();

    // enter inequality constraint [ in: i ]
    int new_row = slack_A[ i-qp_n].first;

     b_C[ C.size()] = ET( *(qp_b+ new_row));
    in_C[ new_row ] = static_cast<int>(C.size());
       C.push_back( new_row);
    // diagnostic output
    CGAL_qpe_debug {
        if ( vout2.verbose()) print_basis();
    }

    // update basis inverse
    A_row_by_index_accessor  a_accessor =
      [new_row, this](int i){ return A_accessor( this->qp_A, 0, this->qp_n)(i, new_row); };
    typedef typename std::iterator_traits<A_row_by_index_iterator>::value_type RT;
    std::transform(A_row_by_index_iterator( B_O.begin(), a_accessor),
                   A_row_by_index_iterator( B_O.end  (), a_accessor),
                   tmp_x.begin(),
                   NT_converter<RT,ET>());
    if ( art_s_i > 0) {                                 // special art.
        tmp_x[ in_B[ art_s_i]] = ET( art_s[ new_row]);
    }
    inv_M_B.enter_original_leave_slack( q_x_O.begin(), tmp_x.begin());

}

// update of the vector r for U_7 with upper bounding, note that we
// need the headings C, and S_{B} before they are updated
template < typename Q, typename ET, typename Tags >                            // Standard form
void  QP_solver<Q, ET, Tags>::
replace_variable_original_slack_upd_r(Tag_true )
{
}

// update of the vector r for U_7 with upper bounding, note that we
// need the headings C, and S_{B} before they are updated
template < typename Q, typename ET, typename Tags >                            // Upper bounded
void  QP_solver<Q, ET, Tags>::
replace_variable_original_slack_upd_r(Tag_false )
{
    if (!is_artificial(j)) {
        ET x_j = nonbasic_original_variable_value(j);
        update_r_C_r_S_B__j(x_j);
    }

    // append r_gamma_S_B(sigma_i) from r_S_B to r_C
    r_C.push_back(r_S_B[in_B[i]]);

    // remove r_gamma_S_B(sigma_i) from r_S_B
    r_S_B[in_B[i]] = r_S_B.back();
    r_S_B.pop_back();

    // update x_O_v_i
    if (!is_artificial(j)) {
        x_O_v_i[j] = BASIC;
    }
}


template < typename Q, typename ET, typename Tags >
void  QP_solver<Q, ET, Tags>::
remove_artificial_variable_and_constraint( )
{
    // updates for the upper bounded case
    remove_artificial_variable_and_constraint_upd_r(Is_nonnegative());

    int  k = in_B[ i];

    // leave artificial (original) variable [ out: i ]
    in_B  [ B_O.back()] = k;
       B_O[ k] = B_O.back();
       in_B  [ i         ] = -1;
       B_O.pop_back();

    minus_c_B[ k] = minus_c_B[ B_O.size()];

    if ( is_phaseI && ( i >= qp_n)) --art_basic;

    int old_row = art_A[i - qp_n - slack_A.size()].first;

    // leave its equality constraint
    int  l = in_C[ old_row];
     b_C[ l       ] = b_C[ C.size()-1];
       C[ l       ] = C.back();
    in_C[ C.back()] = l;
    in_C[ old_row ] = -1;
       C.pop_back();
    // diagnostic output
    CGAL_qpe_debug {
        if ( vout2.verbose()) print_basis();
    }

    // update basis inverse
    inv_M_B.swap_variable( k);
    inv_M_B.swap_constraint( l);
    inv_M_B.enter_slack_leave_original();
}

// update of the vector r with upper bounding for the removal of an
// artificial variable with its equality constraint, note that we
// need the headings C before it is updated
template < typename Q, typename ET, typename Tags >                                 // Standard form
void  QP_solver<Q, ET, Tags>::
remove_artificial_variable_and_constraint_upd_r(Tag_true )
{
}

// update of the vector r with upper bounding for the removal of an
// artificial variable with its equality constraint, note that we
// need the headings C before it is updated
template < typename Q, typename ET, typename Tags >                                 // Upper bounded
void  QP_solver<Q, ET, Tags>::
remove_artificial_variable_and_constraint_upd_r(Tag_false )
{
    int sigma_i = art_A[i - qp_n - slack_A.size()].first;

    // remove r_gamma_C(sigma_i) from r_C
    r_C[in_C[sigma_i]] = r_C.back();
    r_C.pop_back();
}

// update that occurs only with upper bounding in ratio test step 1
template < typename Q, typename ET, typename Tags >
void  QP_solver<Q, ET, Tags>::
enter_and_leave_variable( )
{

    CGAL_qpe_assertion((i == j) && (i >= 0));

    CGAL_qpe_debug {
        vout2 <<   "<--> nonbasic (" << variable_type( j) << ") variable " << j
              << " enters and leaves basis" << std::endl << std::endl;
    }


    ET diff;
    ET x_j = nonbasic_original_variable_value(j);

    if (ratio_test_bound_index == LOWER) {
        diff = x_j - ET(*(qp_l+j));
    } else {
        diff = x_j - ET(*(qp_u+j));
    }

    if (is_phaseI) {
        update_r_C_r_S_B__j(diff);
    } else {
        update_w_r_B_O__j(diff);
        update_r_C_r_S_B__j(diff);
    }

    x_O_v_i[j] = ratio_test_bound_index;

    // notify pricing strategy (it has called enter_basis on i before)
    strategyP->leaving_basis (i);

    // variable entered and left basis
    i = -1; j = -1;
}



// enter variable into basis
template < typename Q, typename ET, typename Tags >
void
QP_solver<Q, ET, Tags>::
enter_variable( )
{
  CGAL_qpe_assertion (is_phaseII);
    CGAL_qpe_debug {
        vout2 << "--> nonbasic (" << variable_type( j) << ") variable "
              << j << " enters basis" << std::endl << std::endl;
    }

    // update basis & basis inverse:
    if (no_ineq || (j < qp_n)) {              // original variable

        // updates for the upper bounded case:
        enter_variable_original_upd_w_r(Is_nonnegative());

        // enter original variable [ in: j ]:
        if (minus_c_B.size() <= B_O.size()) { // Note: minus_c_B and the
                                              // containers resized in this
                                              // if-block are only enlarged
                                              // and never made smaller
                                              // (while B_O always has the
                                              // correct size). We check here
                                              // whether we need to enlarge
                                              // them.
          CGAL_qpe_assertion(minus_c_B.size() == B_O.size());
            minus_c_B.push_back(et0);
                q_x_O.push_back(et0);
              tmp_x  .push_back(et0);
              tmp_x_2.push_back(et0);
             two_D_Bj.push_back(et0);
                x_B_O.push_back(et0);
        }
        minus_c_B[B_O.size()] = -ET(*(qp_c+ j)); // Note: B_O has always the
                                               // correct size.

        in_B[j] = static_cast<int>(B_O.size());
        B_O.push_back(j);

        // diagnostic output
        CGAL_qpe_debug {
            if (vout2.verbose())
              print_basis();
        }

        // update basis inverse
        // note: (-1)\hat{\nu} is stored instead of \hat{\nu}
        inv_M_B.enter_original(q_lambda.begin(), q_x_O.begin(), -nu);

    } else {                                  // slack variable

        // updates for the upper bounded case:
        enter_variable_slack_upd_w_r(Is_nonnegative());

        // enter slack variable [ in: j ]:
        in_B  [ j] = static_cast<int>(B_S.size());
           B_S.push_back( j);
           S_B.push_back( slack_A[ j-qp_n].first);

        // leave inequality constraint [ out: j ]:
        int old_row = slack_A[ j-qp_n].first;
        int k = in_C[old_row];

        // reflect change of active constraints heading C in b_C:
        b_C[ k] = b_C[C.size()-1];

           C[ k] = C.back();
        in_C[ C.back()      ] = k;
        in_C[ old_row       ] = -1;
           C.pop_back();

        // diagnostic output:
        CGAL_qpe_debug {
            if (vout2.verbose())
              print_basis();
        }

        // update basis inverse:
        inv_M_B.swap_constraint(k);  // swap to back
        inv_M_B.enter_slack();       // drop drop
    }

    // variable entered:
    j -= static_cast<int>(in_B.size());
}

// update of the vectors w and r for U_1 with upper bounding, note that we
// need the headings C, S_{B}, B_{O} before they are updated
template < typename Q, typename ET, typename Tags >                            // Standard form
void  QP_solver<Q, ET, Tags>::
enter_variable_original_upd_w_r(Tag_true )
{
}

// update of the vectors w and r for U_1 with upper bounding, note that we
// need the headings C, S_{B}, B_{O} before they are updated
template < typename Q, typename ET, typename Tags >                            // Upper bounded
void  QP_solver<Q, ET, Tags>::
enter_variable_original_upd_w_r(Tag_false )
{

    ET      x_j = nonbasic_original_variable_value(j);

    // Note: w needs to be updated before r_C, r_S_B
    update_w_r_B_O__j(x_j);
    update_r_C_r_S_B__j(x_j);

    // append w_j to r_B_O
    if (!check_tag(Is_linear())) // (kf.)
      r_B_O.push_back(w[j]);

    // update x_O_v_i
    x_O_v_i[j] = BASIC;
}

// update of the vectors w and r for U_3 with upper bounding, note that we
// need the headings C, S_{B}, B_{O} before they are updated
template < typename Q, typename ET, typename Tags >                            // Standard form
void  QP_solver<Q, ET, Tags>::
enter_variable_slack_upd_w_r(Tag_true )
{
}

// update of the vectors w and r for U_3 with upper bounding, note that we
// need the headings C, S_{B}, B_{O} before they are updated
template < typename Q, typename ET, typename Tags >                            // Upper bounded
void  QP_solver<Q, ET, Tags>::
enter_variable_slack_upd_w_r(Tag_false )
{

    int     sigma_j = slack_A[ j-qp_n].first;

    // append r_gamma_C(sigma_j) to r_S_B
    r_S_B.push_back(r_C[in_C[sigma_j]]);

    // remove r_gamma_C(sigma_j) from r_C
    r_C[in_C[sigma_j]] = r_C.back();
    r_C.pop_back();
}

// leave variable from basis
template < typename Q, typename ET, typename Tags >
void
QP_solver<Q, ET, Tags>::
leave_variable( )
{
    CGAL_qpe_debug {
        vout2 << "<-- basic (" << variable_type( i) << ") variable "
              << i << " leaves basis" << std::endl << std::endl;
    }

    // update basis & basis inverse
    int  k = in_B[ i];
    if ( no_ineq || ( i < qp_n)) {                      // original variable

        // updates for the upper bounded case
        leave_variable_original_upd_w_r(Is_nonnegative());

        // leave original variable [ out: i ]
        in_B  [ B_O.back()] = k;
        in_B  [ i         ] = -1;
        //in_B  [ B_O.back()] = k;
           B_O[ k] = B_O.back(); B_O.pop_back();

        minus_c_B [ k] = minus_c_B [ B_O.size()];
          two_D_Bj[ k] =   two_D_Bj[ B_O.size()];


        // diagnostic output
        CGAL_qpe_debug {
            if ( vout2.verbose()) print_basis();
        }

        // update basis inverse
        inv_M_B.swap_variable( k);
        inv_M_B.leave_original();

    } else {                                            // slack variable

        // updates for the upper bounded case
        leave_variable_slack_upd_w_r(Is_nonnegative());

        // leave slack variable [ out: i ]
        in_B  [ B_S.back()] = k;      // former last var moves to position k
        in_B  [ i         ] = -1;     // i gets deleted
           B_S[ k] = B_S.back(); B_S.pop_back();
           S_B[ k] = S_B.back(); S_B.pop_back();

        // enter inequality constraint [ in: i ]
        int new_row = slack_A[ i-qp_n].first;

        A_Cj[ C.size()] = ( j < qp_n ? ET( *((*(qp_A + j))+ new_row)) : et0);

         b_C[ C.size()] = ET( *(qp_b+ new_row));
        in_C[ new_row ] = static_cast<int>(C.size());
           C.push_back( new_row);

        // diagnostic output
        CGAL_qpe_debug {
            if ( vout2.verbose()) print_basis();
        }

        // update basis inverse
        A_row_by_index_accessor  a_accessor =
          [new_row, this](int i){ return A_accessor( this->qp_A, 0, this->qp_n)(i, new_row); };
        std::copy( A_row_by_index_iterator( B_O.begin(), a_accessor),
                   A_row_by_index_iterator( B_O.end  (), a_accessor),
                   tmp_x.begin());
        inv_M_B.leave_slack( tmp_x.begin());
    }

    // notify pricing strategy
    strategyP->leaving_basis( i);

    // variable left
    i = -1;
}

// update of the vectors w and r for U_2 with upper bounding, note that we
// need the headings C, S_{B}, B_{O} before they are updated
template < typename Q, typename ET, typename Tags >                            // Standard form
void  QP_solver<Q, ET, Tags>::
leave_variable_original_upd_w_r(Tag_true )
{
}

// update of the vectors w and r for U_2 with upper bounding, note that we
// need the headings C, S_{B}, B_{O} before they are updated
template < typename Q, typename ET, typename Tags >                            // Upper bounded
void  QP_solver<Q, ET, Tags>::
leave_variable_original_upd_w_r(Tag_false )
{

    ET      x_i = (ratio_test_bound_index == LOWER) ? *(qp_l+i) : *(qp_u+i);

    // Note: w needs to be updated before r_C, r_S_B
    update_w_r_B_O__i(x_i);
    update_r_C_r_S_B__i(x_i);

    // remove r_beta_O(i) from r_B_O
    if (!check_tag(Is_linear())) { // (kf.)
      r_B_O[in_B[i]] = r_B_O.back();
      r_B_O.pop_back();
    }

    // update x_O_v_i
    x_O_v_i[i] = ratio_test_bound_index;
}

// update of the vectors w and r for U_4 with upper bounding, note that we
// need the headings C, S_{B}, B_{O} before they are updated
template < typename Q, typename ET, typename Tags >                            // Standard form
void  QP_solver<Q, ET, Tags>::
leave_variable_slack_upd_w_r(Tag_true )
{
}

// update of the vectors w and r for U_4 with upper bounding, note that we
// need the headings C, S_{B}, B_{O} before they are updated
template < typename Q, typename ET, typename Tags >                            // Upper bounded
void  QP_solver<Q, ET, Tags>::
leave_variable_slack_upd_w_r(Tag_false )
{

    // append r_gamma_S_B(sigma_i) to r_C
    r_C.push_back(r_S_B[in_B[i]]);

    // remove r_gamma_S_B(sigma_i) from r_S_B
    r_S_B[in_B[i]] = r_S_B.back();
    r_S_B.pop_back();
}


// replace variable in basis QP-case, transition to Ratio Test Step 2
template < typename Q, typename ET, typename Tags >
void QP_solver<Q, ET, Tags>::
z_replace_variable( )
{
    CGAL_qpe_debug {
        vout2 <<   "<--> nonbasic (" << variable_type( j) << ") variable " << j
              << " z_replaces basic (" << variable_type( i) << ") variable " << i
              << std::endl << std::endl;
    }

    // replace variable
    z_replace_variable( no_ineq);

    // pivot step not yet completely done
    i = -1;
    j -= static_cast<int>(in_B.size());
    is_RTS_transition = true;
}


template < typename Q, typename ET, typename Tags >  inline                           // no inequalities
void QP_solver<Q, ET, Tags>::
z_replace_variable( Tag_true)
{
    z_replace_variable_original_by_original();
    strategyP->leaving_basis(i);

}


template < typename Q, typename ET, typename Tags >  inline                          // has inequalities
void QP_solver<Q, ET, Tags>::
z_replace_variable( Tag_false)
{
    // determine type of variables
    bool  enter_original = ( (j < qp_n) || (j >= static_cast<int>( qp_n+slack_A.size())));
    bool  leave_original = ( (i < qp_n) || (i >= static_cast<int>( qp_n+slack_A.size())));

    // update basis and basis inverse
    if ( leave_original) {
        if ( enter_original) {
            z_replace_variable_original_by_original();
        } else {
            z_replace_variable_original_by_slack();
        }
    } else {
        if ( enter_original) {
            z_replace_variable_slack_by_original();
        } else {
            z_replace_variable_slack_by_slack();
        }
    }
    strategyP->leaving_basis( i);
}


// replacement with precond det(M_{B \setminus \{i\}})=0
template < typename Q, typename ET, typename Tags >
void  QP_solver<Q, ET, Tags>::
z_replace_variable_original_by_original( )
{
    // updates for the upper bounded case
    z_replace_variable_original_by_original_upd_w_r(Is_nonnegative());

    int  k = in_B[ i];

    // replace original variable [ in: j | out: i ]
    in_B  [ i] = -1;
    in_B  [ j] = k;
       B_O[ k] = j;

    minus_c_B[ k] = -ET( *(qp_c+ j));

    // diagnostic output
    CGAL_qpe_debug {
        if ( vout2.verbose()) print_basis();
    }

    // compute s_delta
    D_pairwise_accessor  d_accessor( qp_D, j);
    ET                   s_delta =d_accessor(j)-d_accessor(i);

    // update basis inverse
    // note: (-1)\hat{\nu} is stored instead of \hat{\nu}
    inv_M_B.z_replace_original_by_original( q_lambda.begin(), q_x_O.begin(),
        s_delta, -nu, k);

}

// update of the vectors w and r for U_Z_1 with upper bounding, note that we
// need the headings C, S_{B}, B_{O} before they are updated
template < typename Q, typename ET, typename Tags >                            // Standard form
void  QP_solver<Q, ET, Tags>::
z_replace_variable_original_by_original_upd_w_r(Tag_true )
{
}

// update of the vectors w and r for U_Z_1 with upper bounding, note that we
// need the headings C, S_{B}, B_{O} before they are updated
template < typename Q, typename ET, typename Tags >
// Upper bounded
void  QP_solver<Q, ET, Tags>::
z_replace_variable_original_by_original_upd_w_r(Tag_false )
{

    ET      x_j = nonbasic_original_variable_value(j);
    ET      x_i = (ratio_test_bound_index == LOWER) ? *(qp_l+i) : *(qp_u+i);

    // Note: w needs to be updated before r_C, r_S_B
    update_w_r_B_O__j_i(x_j, x_i);
    update_r_C_r_S_B__j_i(x_j, x_i);

    // replace r_beta_O(i) with w_j
    r_B_O[in_B[i]] = w[j];

    // update x_O_v_i
    x_O_v_i[j] = BASIC;
    x_O_v_i[i] = ratio_test_bound_index;
}


// replacement with precond det(M_{B \setminus \{i\}})=0
template < typename Q, typename ET, typename Tags >
void  QP_solver<Q, ET, Tags>::
z_replace_variable_original_by_slack( )
{
    // updates for the upper bounded case
    z_replace_variable_original_by_slack_upd_w_r(Is_nonnegative());

    int  k = in_B[ i];

    // leave original variable [ out: i ]
    in_B  [ B_O.back()] = k;
       B_O[ k] = B_O.back();
       in_B  [ i         ] = -1;
       B_O.pop_back();

    minus_c_B[ k] = minus_c_B[ B_O.size()];

    // enter slack variable [ in: j ]
    int  old_row = slack_A[ j-qp_n].first;
    in_B  [ j] = static_cast<int>(B_S.size());
       B_S.push_back( j);
       S_B.push_back( old_row);

    // leave inequality constraint [ out: j ]
    int  l = in_C[ old_row];
     b_C[ l       ] = b_C[ C.size()-1];
       C[ l       ] = C.back();
    in_C[ C.back()] = l;
    in_C[ old_row ] = -1;
       C.pop_back();

    // diagnostic output
    CGAL_qpe_debug {
        if ( vout2.verbose()) print_basis();
    }

    // update basis inverse
    inv_M_B.swap_variable( k);
    inv_M_B.swap_constraint( l);
    inv_M_B.z_replace_original_by_slack( );

}

// update of the vectors w and r for U_Z_2 with upper bounding, note that we
// need the headings C, S_{B}, B_{O} before they are updated
template < typename Q, typename ET, typename Tags >                         // Standard form
void  QP_solver<Q, ET, Tags>::
z_replace_variable_original_by_slack_upd_w_r(Tag_true )
{
}


// update of the vectors w and r for U_Z_2 with upper bounding, note that we
// need the headings C, S_{B}, B_{O} before they are updated
template < typename Q, typename ET, typename Tags >                         // Upper bounded
void  QP_solver<Q, ET, Tags>::
z_replace_variable_original_by_slack_upd_w_r(Tag_false )
{

    ET      x_i = (ratio_test_bound_index == LOWER) ? *(qp_l+i) : *(qp_u+i);

    // Note: w needs to be updated before r_C, r_S_B
    update_w_r_B_O__i(x_i);
    update_r_C_r_S_B__i(x_i);

    int     sigma_j = slack_A[ j-qp_n].first;

    // append r_gamma_C(sigma_j) to r_S_B
    r_S_B.push_back(r_C[in_C[sigma_j]]);

    // remove r_gamma_C(sigma_j) from r_C
    r_C[in_C[sigma_j]] = r_C.back();
    r_C.pop_back();

    // remove r_beta_O(i) from r_B_O
    if (!check_tag(Is_linear())) { // (kf.)
      r_B_O[in_B[i]] = r_B_O.back();
      r_B_O.pop_back();
    }

    // update x_O_v_i
    x_O_v_i[i] = ratio_test_bound_index;
}


// replacement with precond det(M_{B \setminus \{i\}})=0
template < typename Q, typename ET, typename Tags >
void  QP_solver<Q, ET, Tags>::
z_replace_variable_slack_by_original( )
{
    // updates for the upper bounded case
    z_replace_variable_slack_by_original_upd_w_r(Is_nonnegative());

    int  k = in_B[ i];
    if (minus_c_B.size() <= B_O.size()) {  // Note: minus_c_B and the
                                           // containers resized in this
                                           // if-block are only enlarged
                                           // and never made smaller
                                           // (while B_O always has the
                                           // correct size). We check here
                                           // whether we need to enlarge
                                           // them.
      CGAL_qpe_assertion(minus_c_B.size() == B_O.size());
         minus_c_B.push_back(et0);
             q_x_O.push_back(et0);
           tmp_x  .push_back(et0);
           tmp_x_2.push_back(et0);
          two_D_Bj.push_back(et0);
             x_B_O.push_back(et0);
    }

    // enter original variable [ in: j ]

    minus_c_B[ B_O.size()] = -ET( *(qp_c+ j));


    in_B  [ j] = static_cast<int>(B_O.size());
       B_O.push_back( j);


    // leave slack variable [ out: i ]
       B_S[ k         ] = B_S.back();
       S_B[ k         ] = S_B.back();
    in_B  [ B_S.back()] = k;
    in_B  [ i         ] = -1;
       B_S.pop_back();
       S_B.pop_back();

    // enter inequality constraint [ in: i ]
    int new_row = slack_A[ i-qp_n].first;

     b_C[ C.size()] = ET( *(qp_b+ new_row));
    in_C[ new_row ] = static_cast<int>(C.size());
       C.push_back( new_row);

    // diagnostic output
    CGAL_qpe_debug {
        if ( vout2.verbose()) print_basis();
    }

    // update basis inverse
    // --------------------

    // prepare u
    A_row_by_index_accessor  a_accessor =
      [new_row, this](int i){ return A_accessor( this->qp_A, 0, this->qp_n)(i, new_row); };
    std::copy( A_row_by_index_iterator( B_O.begin(), a_accessor),
               A_row_by_index_iterator( B_O.end  (), a_accessor),
               tmp_x.begin());


    // prepare kappa
    ET  kappa = d * ET(*((*(qp_A + j))+new_row))
                - inv_M_B.inner_product_x( tmp_x.begin(), q_x_O.begin());

        // note: (-1)/hat{\nu} is stored instead of \hat{\nu}
    inv_M_B.z_replace_slack_by_original( q_lambda.begin(), q_x_O.begin(),
                                          tmp_x.begin(), kappa, -nu);
}

// update of the vectors w and r for U_Z_3 with upper bounding, note that we
// need the headings C, S_{B}, B_{O} before they are updated
template < typename Q, typename ET, typename Tags >                            // Standard form
void  QP_solver<Q, ET, Tags>::
z_replace_variable_slack_by_original_upd_w_r(Tag_true )
{
}

// update of the vectors w and r for U_Z_3 with upper bounding, note that we
// need the headings C, S_{B}, B_{O} before they are updated
template < typename Q, typename ET, typename Tags >                             // Upper bounded
void  QP_solver<Q, ET, Tags>::
z_replace_variable_slack_by_original_upd_w_r(Tag_false )
{

    ET      x_j = nonbasic_original_variable_value(j);

    // Note: w needs to be updated before r_C, r_S_B
    update_w_r_B_O__j(x_j);
    update_r_C_r_S_B__j(x_j);

    // append r_gamma_S_B(sigma_i) to r_C
    r_C.push_back(r_S_B[in_B[i]]);

    // remove r_gamma_S_B(sigma_i) from r_S_B
    r_S_B[in_B[i]] = r_S_B.back();
    r_S_B.pop_back();

    // append w_j to r_B_O
    if (!check_tag(Is_linear())) // (kf.)
      r_B_O.push_back(w[j]);

    // update x_O_v_i
    x_O_v_i[j] = BASIC;
}


// replacement with precond det(M_{B \setminus \{i\}})=0
template < typename Q, typename ET, typename Tags >
void  QP_solver<Q, ET, Tags>::
z_replace_variable_slack_by_slack( )
{
    // updates for the upper bounded case
    z_replace_variable_slack_by_slack_upd_w_r(Is_nonnegative());

    int  k = in_B[ i];

    // replace slack variable [ in: j | out: i ]
    in_B  [ i] = -1;
    in_B  [ j] = k;
       B_S[ k] = j;
       S_B[ k] = slack_A[ j-qp_n].first;

    // replace inequality constraint [ in: i | out: j ]
    int old_row = S_B[ k];
    int new_row = slack_A[ i-qp_n].first;
    k = in_C[ old_row];

    in_C[ old_row] = -1;
    in_C[ new_row] = k;
       C[ k      ] = new_row;

     b_C[ k] = ET( *(qp_b+ new_row));

    // diagnostic output
    CGAL_qpe_debug {
            if ( vout2.verbose()) print_basis();
    }

    // update basis inverse
    // --------------------
    A_row_by_index_accessor  a_accessor =
      [new_row, this](int i){ return A_accessor( this->qp_A, 0, this->qp_n)(i, new_row); };
    std::copy( A_row_by_index_iterator( B_O.begin(), a_accessor),
               A_row_by_index_iterator( B_O.end  (), a_accessor),
               tmp_x.begin());


    inv_M_B.z_replace_slack_by_slack( tmp_x.begin(), k);
}

// update of the vectors w and r for U_Z_4 with upper bounding, note that we
// need the headings C, S_{B}, B_{O} before they are updated
template < typename Q, typename ET, typename Tags >                             // Standard form
void  QP_solver<Q, ET, Tags>::
z_replace_variable_slack_by_slack_upd_w_r(Tag_true )
{
}


// update of the vectors w and r for U_Z_4 with upper bounding, note that we
// need the headings C, S_{B}, B_{O} before they are updated
template < typename Q, typename ET, typename Tags >                             // Upper bounded
void  QP_solver<Q, ET, Tags>::
z_replace_variable_slack_by_slack_upd_w_r(Tag_false )
{

    int     sigma_j = slack_A[ j-qp_n].first;

    // swap r_sigma_j in r_C with r_sigma_i in r_S_B
    std::swap(r_C[in_C[sigma_j]], r_S_B[in_B[i]]);
}

// update of the vectors r_C and r_S_B with "x_j" column
template < typename Q, typename ET, typename Tags >
void  QP_solver<Q, ET, Tags>::
update_r_C_r_S_B__j(ET& x_j)
{
    // update of vector r_{C}
    A_by_index_accessor     a_accessor_j(*(qp_A + j));

    A_by_index_iterator     A_C_j_it(C.begin(), a_accessor_j);

    for (Value_iterator r_C_it = r_C.begin(); r_C_it != r_C.end();
                                                    ++r_C_it, ++A_C_j_it) {
        *r_C_it -= x_j * ET(*A_C_j_it);
    }

    // update of r_{S_{B}}
    A_by_index_iterator     A_S_B_j_it(S_B.begin(), a_accessor_j);

    for (Value_iterator r_S_B_it = r_S_B.begin(); r_S_B_it != r_S_B.end();
                                                ++r_S_B_it, ++A_S_B_j_it) {
        *r_S_B_it -= x_j * ET(*A_S_B_j_it);
    }
}

// update of the vectors r_C and r_S_B with "x_j" and "x_i" column
template < typename Q, typename ET, typename Tags >
void  QP_solver<Q, ET, Tags>::
update_r_C_r_S_B__j_i(ET& x_j, ET& x_i)
{
    // update of vector r_{C}
    A_by_index_accessor     a_accessor_j(*(qp_A+j));
    A_by_index_accessor     a_accessor_i(*(qp_A+i));

    A_by_index_iterator     A_C_j_it(C.begin(), a_accessor_j);
    A_by_index_iterator     A_C_i_it(C.begin(), a_accessor_i);

    for (Value_iterator r_C_it = r_C.begin(); r_C_it != r_C.end();
                                        ++r_C_it, ++A_C_j_it, ++A_C_i_it) {
        *r_C_it += (x_i * ET(*A_C_i_it)) - (x_j * ET(*A_C_j_it));
    }

    // update of vector r_{S_{B}}
    A_by_index_iterator     A_S_B_j_it(S_B.begin(), a_accessor_j);
    A_by_index_iterator     A_S_B_i_it(S_B.begin(), a_accessor_i);

    for (Value_iterator r_S_B_it = r_S_B.begin(); r_S_B_it != r_S_B.end();
                                    ++r_S_B_it, ++A_S_B_j_it, ++A_S_B_i_it) {
        *r_S_B_it += (x_i * ET(*A_S_B_i_it)) - (x_j * ET(*A_S_B_j_it));
    }
}

// update of the vectors r_C and r_S_B with "x_i'" column
template < typename Q, typename ET, typename Tags >
void  QP_solver<Q, ET, Tags>::
update_r_C_r_S_B__i(ET& x_i)
{
    // update of vector r_{C}
    A_by_index_accessor     a_accessor_i(*(qp_A+i));
    A_by_index_iterator     A_C_i_it(C.begin(), a_accessor_i);

    for (Value_iterator r_C_it = r_C.begin(); r_C_it != r_C.end();
                                                    ++r_C_it, ++A_C_i_it) {
        *r_C_it += x_i * ET(*A_C_i_it);
    }

    // update of r_{S_{B}}
    A_by_index_iterator     A_S_B_i_it(S_B.begin(), a_accessor_i);

    for (Value_iterator r_S_B_it = r_S_B.begin(); r_S_B_it != r_S_B.end();
                                                ++r_S_B_it, ++A_S_B_i_it) {
        *r_S_B_it += x_i * ET(*A_S_B_i_it);
    }
}


// Update of w and r_B_O with "x_j" column.
//
// todo: could be optimized slightly by factoring out the factor 2
// (which is implicitly contained in the pairwise accessor for D).
template < typename Q, typename ET, typename Tags >
void  QP_solver<Q, ET, Tags>::
update_w_r_B_O__j(ET& x_j)
{
  // assertion checking:
  CGAL_expensive_assertion(!check_tag(Is_nonnegative()));

  // Note: we only do anything it we are dealing with a QP.
  if (!check_tag(Is_linear())) {
    D_pairwise_accessor     d_accessor_j(qp_D, j);

    // update of vector w:
    for (int it = 0; it < qp_n; ++it)
      w[it] -= d_accessor_j(it) * x_j;

    // update of r_B_O:
    D_pairwise_iterator D_B_O_j_it(B_O.begin(), d_accessor_j);
    for (Value_iterator r_B_O_it = r_B_O.begin();
         r_B_O_it != r_B_O.end();
         ++r_B_O_it, ++D_B_O_j_it)
        *r_B_O_it -= *D_B_O_j_it * x_j;
  }
}

// update of w and r_B_O with "x_j" and "x_i" column
template < typename Q, typename ET, typename Tags >
void  QP_solver<Q, ET, Tags>::
update_w_r_B_O__j_i(ET& x_j, ET& x_i)
{
  // assertion checking:
  CGAL_expensive_assertion(!check_tag(Is_nonnegative()));

  // Note: we only do anything it we are dealing with a QP.
  if (!check_tag(Is_linear())) {
    D_pairwise_accessor     d_accessor_i(qp_D, i);
    D_pairwise_accessor     d_accessor_j(qp_D, j);

    // update of vector w
    for (int it = 0; it < qp_n; ++it)
        w[it] += (d_accessor_i(it) * x_i) - (d_accessor_j(it) * x_j);

    // update of r_B_O
    D_pairwise_iterator D_B_O_j_it(B_O.begin(), d_accessor_j);
    D_pairwise_iterator D_B_O_i_it(B_O.begin(), d_accessor_i);
    for (Value_iterator r_B_O_it = r_B_O.begin();
         r_B_O_it != r_B_O.end();
         ++r_B_O_it, ++D_B_O_j_it, ++D_B_O_i_it)
        *r_B_O_it += (*D_B_O_i_it * x_i) - (*D_B_O_j_it * x_j);
  }
}

// update of w and r_B_O with "x_i" column
template < typename Q, typename ET, typename Tags >
void  QP_solver<Q, ET, Tags>::
update_w_r_B_O__i(ET& x_i)
{
  CGAL_expensive_assertion(!check_tag(Is_nonnegative()));

  // Note: we only do anything it we are dealing with a QP.
  if (!check_tag(Is_linear())) {

    // update of vector w:
    D_pairwise_accessor     d_accessor_i(qp_D, i);

    for (int it = 0; it < qp_n; ++it)
        w[it] += d_accessor_i(it) * x_i;

    // update of r_B_O:
    D_pairwise_iterator D_B_O_i_it(B_O.begin(), d_accessor_i);
    for (Value_iterator r_B_O_it = r_B_O.begin();
         r_B_O_it != r_B_O.end();
         ++r_B_O_it, ++D_B_O_i_it)
        *r_B_O_it += *D_B_O_i_it * x_i;
  }
}

// Compute solution, meaning compute the solution vector x and the KKT
// coefficients lambda.
template < typename Q, typename ET, typename Tags >                                      // Standard form
void  QP_solver<Q, ET, Tags>::
compute_solution(Tag_true)
{
  // compute current solution, original variables and lambdas
  inv_M_B.multiply( b_C.begin(), minus_c_B.begin(),
                    lambda.begin(), x_B_O.begin());

  // compute current solution, slack variables
  compute__x_B_S(no_ineq, Is_nonnegative());
}

// Compute solution, meaning compute the solution vector x and the KKT
// coefficients lambda.
template < typename Q, typename ET, typename Tags >                                      // Upper bounded
void  QP_solver<Q, ET, Tags>::
compute_solution(Tag_false)
{
  // compute the difference b_C - r_C
  std::transform(b_C.begin(), b_C.begin()+C.size(), // Note: r_C.size() ==
                                                    // C.size() always holds,
                                                    // whereas b_C.size() >=
                                                    // C.size() in general.
                 r_C.begin(),  tmp_l.begin(), std::minus<ET>());

  // compute the difference minus_c_B - r_B_O:
  if (is_phaseII && is_QP) {
    std::transform(minus_c_B.begin(), minus_c_B.begin() + B_O.size(),
                   r_B_O.begin(), tmp_x.begin(), std::minus<ET>());

    // compute current solution, original variables and lambdas:
    inv_M_B.multiply( tmp_l.begin(), tmp_x.begin(),
                      lambda.begin(), x_B_O.begin());
  } else {                                          // r_B_O == 0

    // compute current solution, original variables and lambdas
    inv_M_B.multiply( tmp_l.begin(), minus_c_B.begin(),
                      lambda.begin(), x_B_O.begin());
  }

  // compute current solution, slack variables
  compute__x_B_S( no_ineq, Is_nonnegative());
}

template < typename Q, typename ET, typename Tags >
void  QP_solver<Q, ET, Tags>::
multiply__A_S_BxB_O(Value_iterator in, Value_iterator out) const
{
  // initialize with zero vector
  std::fill_n( out, B_S.size(), et0);

  // foreach original column of A in B_O (artificial columns are zero in S_B
  A_column              a_col;                             // except special)
  Index_const_iterator  row_it, col_it;
  Value_iterator        out_it;
  //ET                    in_value;
  for ( col_it = B_O.begin(); col_it != B_O.end(); ++col_it, ++in) {
    const ET in_value = *in;
    out_it   = out;

    if ( *col_it < qp_n) {                                // original variable
      a_col = *(qp_A+ *col_it);

      // foreach row of A in S_B
      for ( row_it = S_B.begin(); row_it != S_B.end(); ++row_it,
              ++out_it) {
        A_entry x = a_col[*row_it];
        *out_it += ET(x) * in_value;
      }
    } else {
      if ( *col_it == art_s_i) {                  // special artificial

        // foreach row of 'art_s'
        for ( row_it = S_B.begin(); row_it != S_B.end(); ++row_it,
                ++out_it) {
          *out_it += ET( art_s[ *row_it]) * in_value;
        }
      }
    }
  }
}

// compare the updated vector r_{C} with t_r_C=A_{C, N_O}x_{N_O}
template < typename Q, typename ET, typename Tags >                         // Standard form
bool  QP_solver<Q, ET, Tags>::
check_r_C(Tag_true) const
{
    return true;
}

// compare the updated vector r_{C} with t_r_C=A_{C, N_O}x_{N_O}
template < typename Q, typename ET, typename Tags >                         // Upper bounded
bool  QP_solver<Q, ET, Tags>::
check_r_C(Tag_false) const
{
    Values                  t_r_C;
    // compute t_r_C from scratch
    t_r_C.resize(C.size(), et0);
    multiply__A_CxN_O(t_r_C.begin());

    // compare r_C and the from scratch computed t_r_C
    bool failed = false;
    int count = 0;
    Value_const_iterator t_r_C_it = r_C.begin();
    for (Value_const_iterator r_C_it = r_C.begin(); r_C_it != r_C.end();
                                    ++r_C_it, ++t_r_C_it, ++count) {
        if (*r_C_it != *t_r_C_it) {
            failed = true;
        }
    }
    return (!failed);
}

// compare the updated vector r_{S_B} with t_r_S_B=A_{S_B, N_O}x_{N_O}
template < typename Q, typename ET, typename Tags >                             // Standard form
bool  QP_solver<Q, ET, Tags>::
check_r_S_B(Tag_true) const
{
    return true;
}

// compare the updated vector r_{S_B} with t_r_S_B=A_{S_B, N_O}x_{N_O}
template < typename Q, typename ET, typename Tags >                             // Upper bounded
bool  QP_solver<Q, ET, Tags>::
check_r_S_B(Tag_false) const
{
    Values                  t_r_S_B;
    // compute t_r_S_B from scratch
    t_r_S_B.resize(S_B.size(), et0);
    multiply__A_S_BxN_O(t_r_S_B.begin());

    // compare r_S_B and the from scratch computed t_r_S_B
    bool failed = false;
    int count = 0;
    Value_const_iterator    t_r_S_B_it = t_r_S_B.begin();
    for (Value_const_iterator r_S_B_it = r_S_B.begin(); r_S_B_it != r_S_B.end();
                                    ++r_S_B_it, ++t_r_S_B_it, ++count) {
        if (*r_S_B_it != *t_r_S_B_it) {
            failed = true;
        }
    }
    return (!failed);
}


// computes r_{B_{O}}:=2D_{B_O, N_O}x_{N_O} with upper bounding
// OPTIMIZATION: If D is symmetric we can multiply by two at the end of the
// computation of entry of r_B_O instead of each access to D
template < typename Q, typename ET, typename Tags >
void  QP_solver<Q, ET, Tags>::
multiply__2D_B_OxN_O(Value_iterator out) const
{
    //initialize
    std::fill_n( out, B_O.size(), et0);

    Value_iterator          out_it;
    ET                      value;

    // foreach entry in r_B_O
    out_it = out;
    for (Index_const_iterator row_it = B_O.begin(); row_it != B_O.end();
                                                        ++row_it, ++out_it) {
        D_pairwise_accessor d_accessor_i(qp_D, *row_it);
        for (int i = 0; i < qp_n; ++i) {
            if (!is_basic(i)) {
                value = nonbasic_original_variable_value(i);
                *out_it += d_accessor_i(i) * value;
            }
        }
    }
}

// compares the updated vector r_{B_O} with t_r_B_O=2D_{B_O, N_O}x_{N_O}
template < typename Q, typename ET, typename Tags >                                // Standard form
bool  QP_solver<Q, ET, Tags>::
check_r_B_O(Tag_true) const
{
    return true;
}

// compares the updated vector r_{B_O} with t_r_B_O=2D_{B_O, N_O}x_{N_O}
template < typename Q, typename ET, typename Tags >                                 // Upper bounded
bool  QP_solver<Q, ET, Tags>::
check_r_B_O(Tag_false) const
{
    Values                  t_r_B_O;
    // compute t_r_B_O from scratch
    t_r_B_O.resize(B_O.size(), et0);
    multiply__2D_B_OxN_O(t_r_B_O.begin());

    // compare r_B_O and the from scratch computed t_r_B_O
    bool failed = false;
    int count = 0;
    Value_const_iterator    t_r_B_O_it = t_r_B_O.begin();
    for (Value_const_iterator r_B_O_it = r_B_O.begin(); r_B_O_it != r_B_O.end();
                                    ++r_B_O_it, ++t_r_B_O_it, ++count) {
        if (*r_B_O_it != *t_r_B_O_it) {
            failed = true;
        }
    }
    return (!failed);
}

// compares the updated vector w with t_w=2D_{O,N_O}*x_N_O
template < typename Q, typename ET, typename Tags >                             // Standard form
bool  QP_solver<Q, ET, Tags>::
check_w(Tag_true) const
{
    return true;
}

// compares the updated vector w with t_w=2D_O_N_O*x_N_O
template < typename Q, typename ET, typename Tags >                             // Upper bounded
bool  QP_solver<Q, ET, Tags>::
check_w(Tag_false) const
{
    Values              t_w;
    // compute t_w from scratch
    t_w.resize( qp_n, et0);
    multiply__2D_OxN_O(t_w.begin());

    // compare w and the from scratch computed t_w
    bool  failed = false;
    Value_const_iterator    t_w_it = t_w.begin();
    for (int i = 0; i < qp_n; ++i, ++t_w_it) {
        if (w[i] != *t_w_it) {
            failed = true;
        }
    }
    return (!failed);
}

// check basis inverse
template < typename Q, typename ET, typename Tags >
bool
QP_solver<Q, ET, Tags>::
check_basis_inverse()
{
    // diagnostic output
    CGAL_qpe_debug {
        vout4 << "check: " << std::flush;
    }
    bool ok;
    if (is_phaseI) {
            ok = check_basis_inverse(Tag_true());
    } else {
        ok = check_basis_inverse( Is_linear());
    }

    // diagnostic output
    CGAL_qpe_debug {
        if ( ok) {
            vout4 << "check ok";
        } else {
            vout4 << "check failed";
        }
        vout4 << std::endl;
    }

    return ok;
}

template < typename Q, typename ET, typename Tags >                                         // LP case
bool  QP_solver<Q, ET, Tags>::
check_basis_inverse( Tag_true)
{
    CGAL_qpe_debug {
        vout4 << std::endl;
    }
    bool res = true;
    unsigned int    row, rows =   static_cast<unsigned int>(C.size());
    unsigned int    col, cols = static_cast<unsigned int>(B_O.size());
    Index_iterator  i_it = B_O.begin();
    Value_iterator  q_it;


    // BG: is this a real check?? How does the special artificial
    // variable come in, e.g.? OK: it comes in through
    // ratio_test_init__A_Cj
    for ( col = 0; col < cols; ++col, ++i_it) {
        ratio_test_init__A_Cj( tmp_l.begin(), *i_it,
                               no_ineq);
        inv_M_B.multiply_x( tmp_l.begin(), q_x_O.begin());

        CGAL_qpe_debug {
                   if ( vout4.verbose()) {
                std::copy( tmp_l.begin(), tmp_l.begin()+rows,
                           std::ostream_iterator<ET>( vout4.out(), " "));
                vout4.out() << " ||  ";
                std::copy( q_x_O.begin(), q_x_O.begin()+cols,
                           std::ostream_iterator<ET>( vout4.out(), " "));
                vout4.out() << std::endl;
            }
        }

        q_it = q_x_O.begin();
        for ( row = 0; row < rows; ++row, ++q_it) {
            if ( *q_it != ( row == col ? d : et0)) {
                if ( ! vout4.verbose()) {
                    std::cerr << std::endl << "basis-inverse check: ";
                }
                std::cerr << "failed ( row=" << row << " | col=" << col << " )"
                          << std::endl;
                res = false;
            }
        }
    }

    return res;
}

template < typename Q, typename ET, typename Tags >                                         // QP case
bool  QP_solver<Q, ET, Tags>::
check_basis_inverse( Tag_false)
{
    bool res = true;
    unsigned int    row, rows =   static_cast<unsigned int>(C.size());
    unsigned int    col, cols = static_cast<unsigned int>(B_O.size());
    Value_iterator  v_it;
    Index_iterator  i_it;

    CGAL_qpe_debug {
        vout4 << std::endl;
    }
    // left part of M_B
    std::fill_n( tmp_l.begin(), rows, et0);
    for ( col = 0; col < rows; ++col) {

        // get column of A_B^T (i.e. row of A_B)
        row = ( has_ineq ? C[ col] : col);
        v_it = tmp_x.begin();
        for ( i_it = B_O.begin(); i_it != B_O.end(); ++i_it, ++v_it) {
            *v_it = ( *i_it < qp_n ? *((*(qp_A+ *i_it))+ row) :  // original
                      art_A[ *i_it - qp_n].first != static_cast<int>(row) ? et0 :// artific.
                      ( art_A[ *i_it - qp_n].second ? -et1 : et1));
        }
//         if ( art_s_i >= 0) {              // special artificial variable?
//           CGAL_qpe_assertion (static_cast<int>(in_B.size()) == art_s_i+1);
//           // the special artificial variable has never been
//           // removed from the basis, consider it
//           tmp_x[ in_B[ art_s_i]] = art_s[ row];
//         }
// BG: currently, this check only runs in phase II, where we have no
// articficials
        CGAL_qpe_assertion (art_s_i < 0);

        inv_M_B.multiply( tmp_l.begin(), tmp_x.begin(),
                          q_lambda.begin(), q_x_O.begin());

        CGAL_qpe_debug {
            if ( vout4.verbose()) {
                std::copy( tmp_l.begin(), tmp_l.begin()+rows,
                           std::ostream_iterator<ET>( vout4.out(), " "));
                vout4.out() << "| ";
                std::copy( tmp_x.begin(), tmp_x.begin()+cols,
                           std::ostream_iterator<ET>( vout4.out(), " "));
                vout4.out() << " ||  ";
                std::copy( q_lambda.begin(), q_lambda.begin()+rows,
                           std::ostream_iterator<ET>( vout4.out(), " "));
                vout4.out() << " |  ";
                std::copy( q_x_O.begin(), q_x_O.begin()+cols,
                           std::ostream_iterator<ET>( vout4.out(), " "));
                vout4.out() << std::endl;
            }
        }

        v_it = q_lambda.begin();
        for ( row = 0; row < rows; ++row, ++v_it) {
            if ( *v_it != ( row == col ? d : et0)) {
                if ( ! vout4.verbose()) {
                    std::cerr << std::endl << "basis-inverse check: ";
                }
                std::cerr << "failed ( row=" << row << " | col=" << col << " )"
                          << std::endl;
                //                return false;
                res = false;
            }
        }
        v_it = std::find_if( q_x_O.begin(), q_x_O.begin()+cols,
                             [this](const ET& v){ return v != this->et0; });
        if ( v_it != q_x_O.begin()+cols) {
            if ( ! vout4.verbose()) {
                std::cerr << std::endl << "basis-inverse check: ";
            }
            std::cerr << "failed ( row=" << rows+(v_it-q_x_O.begin())
                      << " | col=" << col << " )" << std::endl;
            // ToDo: return false;
            res = false;
        }
    }
    vout4 << "= = = = = = = = = =" << std::endl;

    // right part of M_B
    if ( is_phaseI) std::fill_n( tmp_x.begin(), B_O.size(), et0);
    i_it = B_O.begin();
    for ( col = 0; col < cols; ++col, ++i_it) {
        ratio_test_init__A_Cj  ( tmp_l.begin(), *i_it,
                                 no_ineq);
        ratio_test_init__2_D_Bj( tmp_x.begin(), *i_it, Tag_false());
        inv_M_B.multiply( tmp_l.begin(), tmp_x.begin(),
                          q_lambda.begin(), q_x_O.begin());

        CGAL_qpe_debug {
            if ( vout4.verbose()) {
                std::copy( tmp_l.begin(), tmp_l.begin()+rows,
                           std::ostream_iterator<ET>( vout4.out(), " "));
                vout4.out() << "| ";
                std::copy( tmp_x.begin(), tmp_x.begin()+cols,
                           std::ostream_iterator<ET>( vout4.out(), " "));
                vout4.out() << " ||  ";
                std::copy( q_lambda.begin(), q_lambda.begin()+rows,
                           std::ostream_iterator<ET>( vout4.out(), " "));
                vout4.out() << " |  ";
                std::copy( q_x_O.begin(), q_x_O.begin()+cols,
                           std::ostream_iterator<ET>( vout4.out(), " "));
                vout4.out() << std::endl;
            }
        }

        v_it = std::find_if( q_lambda.begin(), q_lambda.begin()+rows,
                             [this](const ET& v){ return v != this->et0; });
        if ( v_it != q_lambda.begin()+rows) {
            if ( ! vout4.verbose()) {
                std::cerr << std::endl << "basis-inverse check: ";
            }
            std::cerr << "failed ( row=" << v_it-q_lambda.begin()
                      << " | col=" << col << " )" << std::endl;
            //            return false;
            res = false;
        }
        v_it = q_x_O.begin();
        for ( row = 0; row < cols; ++row, ++v_it) {
            if ( *v_it != ( row == col ? d : et0)) {
                if ( ! vout4.verbose()) {
                    std::cerr << std::endl << "basis-inverse check: ";
                }
                std::cerr << "failed ( row=" << row+rows << " | col="
                          << col << " )" << std::endl;
                //                return false;
                res = false;
            }
        }
    }
    return res;
}

// filtered strategies are only allowed if the input type as
// indicated by C_entry is double; this may still fail if the
// types of some other program entries are not double, but
// since the filtered stuff is internal anyway, we can probably
// live with this simple check
template < typename Q, typename ET, typename Tags >
void  QP_solver<Q, ET, Tags>::
set_pricing_strategy
( Quadratic_program_pricing_strategy strategy)
{
    CGAL_qpe_assertion( phase() != 1);
    CGAL_qpe_assertion( phase() != 2);

    if (strategy == QP_DANTZIG)
      strategyP = new QP_full_exact_pricing<Q, ET, Tags>;
    else if (strategy == QP_FILTERED_DANTZIG)
      // choose between FF (double) and FE (anything else)
      strategyP =
        new typename QP_solver_impl::Filtered_pricing_strategy_selector
        <Q, ET, Tags, C_entry>::FF;
    else if (strategy == QP_PARTIAL_DANTZIG)
      strategyP = new QP_partial_exact_pricing<Q, ET, Tags>;
    else if (strategy == QP_PARTIAL_FILTERED_DANTZIG
             || strategy == QP_CHOOSE_DEFAULT)
      // choose between PF (double) and PE (anything else)
      strategyP =
        new typename QP_solver_impl::Filtered_pricing_strategy_selector
        <Q, ET, Tags, C_entry>::PF;
    else if (strategy == QP_BLAND)
      strategyP = new QP_exact_bland_pricing<Q, ET, Tags>;
    CGAL_qpe_assertion(strategyP != static_cast<Pricing_strategy*>(0));

    if ( phase() != -1) strategyP->set( *this, vout2);
}

// diagnostic output
// -----------------
template < typename Q, typename ET, typename Tags >
void  QP_solver<Q, ET, Tags>::
set_verbosity( int verbose, std::ostream& stream)
{
    vout  = Verbose_ostream( verbose >  0, stream);
    vout1 = Verbose_ostream( verbose == 1, stream);
    vout2 = Verbose_ostream( verbose >= 2, stream);
    vout3 = Verbose_ostream( verbose >= 3, stream);
    vout4 = Verbose_ostream( verbose == 4, stream);
    vout5 = Verbose_ostream( verbose == 5, stream);
}

template < typename Q, typename ET, typename Tags >
void  QP_solver<Q, ET, Tags>::
print_program( ) const
{
    int  row, i;

    // objective function
    vout4.out() << std::endl << "objective function:" << std::endl;
    if ( is_QP) {
        vout4.out() << "--> output of MATRIX must go here <--";
        vout4.out() << std::endl;
    }
    std::copy( qp_c, qp_c+qp_n,
               std::ostream_iterator<C_entry>( vout4.out(), " "));
    vout4.out() << "(+ " << qp_c0 << ") ";
    vout4.out() << std::endl;
    vout4.out() << std::endl;

    // constraints
    vout4.out() << "constraints:" << std::endl;
    for ( row = 0; row < qp_m; ++row) {

        // original variables
        for (i = 0; i < qp_n; ++i)
          vout4.out() << *((*(qp_A+ i))+row) << ' ';

        // slack variables
        if ( ! slack_A.empty()) {
            vout4.out() << " |  ";
            for ( i = 0; i < static_cast<int>(slack_A.size()); ++i) {
                vout4.out() << ( slack_A[ i].first != row ? " 0" :
                               ( slack_A[ i].second ? "-1" : "+1")) << ' ';
            }
        }

        // artificial variables
        if ( ! art_A.empty()) {
            vout4.out() << " |  ";
            for ( i = 0; i < static_cast<int>(art_A.size()); ++i) {
              if (art_s_i == i+qp_n+static_cast<int>(slack_A.size()))
                vout4.out() << " * ";          // for special artificial column
              vout4.out() << ( art_A[ i].first != row ? " 0" :
                             ( art_A[ i].second ? "-1" : "+1")) << ' ';
            }
        }
        if ( ! art_s.empty()) vout4.out() << " |  " << art_s[ row] << ' ';

        // rhs
        vout4.out() << " |  "
                    << ( *(qp_r+ row) == CGAL::EQUAL      ? ' ' :
                       ( *(qp_r+ row) == CGAL::SMALLER ? '<' : '>')) << "=  "
                    << *(qp_b+ row);
                    if (!is_nonnegative) {
                        vout4.out() << " - " << multiply__A_ixO(row);
                    }
                    vout4.out() << std::endl;
    }
    vout4.out() << std::endl;

    // explicit bounds
    if (!is_nonnegative) {
        vout4.out() << "explicit bounds:" << std::endl;
        for (int i = 0; i < qp_n; ++i) {
            if (*(qp_fl+i)) {                   // finite lower bound
                vout4.out() << *(qp_l+i);
            } else {                            // infinite lower bound
                vout4.out() << "-inf";
            }
            vout4.out() << " <= x_" << i << " <= ";
            if (*(qp_fu+i)) {
                vout4.out() << *(qp_u+i);
            } else {
                vout4.out() << "inf";
            }
            vout4.out() << std::endl;
        }
    }
}

template < typename Q, typename ET, typename Tags >
void  QP_solver<Q, ET, Tags>::
print_basis( ) const
{
    char label;
    vout << "  basis: ";
    CGAL_qpe_debug {
      vout2 << "basic variables" << ( has_ineq ? "  " : "") << ":  ";
    }
    std::copy( B_O.begin(), B_O.end  (),
               std::ostream_iterator<int>( vout.out(), " "));
    CGAL_qpe_debug {
      if ( vout2.verbose()) {
        if ( has_ineq && ( ! slack_A.empty())) {
          vout2.out() << " |  ";
          std::copy( B_S.begin(), B_S.end(),
                     std::ostream_iterator<int>( vout2.out(), " "));
        }
        if ( is_phaseI) {
          vout2.out() << " (# of artificials: " << art_basic << ')';
        }
        if ( has_ineq) {
          vout2.out() << std::endl
                      << "basic constraints:  ";
          for (Index_const_iterator i_it =
                 C.begin(); i_it != C.end(); ++i_it) {
            label = (*(qp_r+ *i_it) == CGAL::EQUAL) ? 'e' : 'i';
            vout2.out() << *i_it << ":" << label << " ";
          }
          /*
            std::copy( C.begin(), C.begin()+(C.size()-slack_A.size()),
            std::ostream_iterator<int>( vout2.out(), " "));
            if ( ! slack_A.empty()) {
            vout2.out() << " |  ";
            std::copy( C.end() - slack_A.size(), C.end(),
            std::ostream_iterator<int>( vout2.out(), " "));
            }
          */
        }
        if ( vout3.verbose()) {
          vout3.out() << std::endl
                      << std::endl
                      << "    in_B: ";
          std::copy( in_B.begin(), in_B.end(),
                     std::ostream_iterator<int>( vout3.out(), " "));
          if ( has_ineq) {
            vout3.out() << std::endl
                        << "    in_C: ";
            std::copy( in_C.begin(), in_C.end(),
                       std::ostream_iterator<int>( vout3.out(), " "));
          }
        }
      }
    }
    vout.out() << std::endl;
    CGAL_qpe_debug {
      vout4 << std::endl << "basis-inverse:" << std::endl;
    }
}

template < typename Q, typename ET, typename Tags >
void  QP_solver<Q, ET, Tags>::
print_solution( ) const
{
  CGAL_qpe_debug {
    if ( vout3.verbose()) {
           vout3.out() << std::endl
            << "     b_C: ";
           std::copy( b_C.begin(), b_C.begin()+C.size(),
                   std::ostream_iterator<ET>( vout3.out()," "));
           vout3.out() << std::endl
            << "  -c_B_O: ";
           std::copy( minus_c_B.begin(), minus_c_B.begin()+B_O.size(),
                   std::ostream_iterator<ET>( vout3.out()," "));
           if (!is_nonnegative) {
               vout3.out() << std::endl
                << "     r_C: ";
               std::copy( r_C.begin(), r_C.begin()+r_C.size(),
                   std::ostream_iterator<ET>( vout3.out(), " "));
               vout3.out() << std::endl
                   << "   r_B_O: ";
               std::copy( r_B_O.begin(), r_B_O.begin()+r_B_O.size(),
                   std::ostream_iterator<ET>( vout3.out(), " "));
               if (r_B_O.size() == 0)
                 vout3.out() << "< will only be allocated in phase II>";

           }
           vout3.out() << std::endl;
    }
    if ( vout2.verbose()) {
        vout2.out() << std::endl << "  lambda: ";
        std::copy( lambda.begin(), lambda.begin()+C.size(),
            std::ostream_iterator<ET>( vout2.out(), " "));
        vout2.out() << std::endl << "   x_B_O: ";
        std::copy( x_B_O.begin(), x_B_O.begin()+B_O.size(),
            std::ostream_iterator<ET>( vout2.out(), " "));
        vout2.out() << std::endl;
        if (!is_nonnegative) {
            vout2.out() << "   x_N_O: ";
            for (int i = 0; i < qp_n; ++i) {
                if (!is_basic(i)) {
                    vout2.out() << d *
                      nonbasic_original_variable_value(i);
                    vout2.out() << " ";
                }
            }
            vout2.out() << std::endl;
        }
        if ( has_ineq) {
            vout2.out() << "   x_B_S: ";
            std::copy( x_B_S.begin(), x_B_S.begin()+B_S.size(),
                std::ostream_iterator<ET>( vout2.out()," "));
            vout2.out() << std::endl;
        }
        const ET denom = inv_M_B.denominator();
        vout2.out() << "   denominator: " << denom << std::endl;
        vout2.out() << std::endl;
    }
  }
  vout << "  ";
  vout.out()
    << "solution: "
    << solution_numerator() << " / " << solution_denominator()
    << "  ~= "
    << to_double
    (CGAL::Quotient<ET>(solution_numerator(), solution_denominator()))
    << std::endl;
  CGAL_qpe_debug {
      vout2 << std::endl;
  }
}

template < typename Q, typename ET, typename Tags >
void  QP_solver<Q, ET, Tags>::
print_ratio_1_original(int k, const ET& x_k, const ET& q_k)
{
    if (is_nonnegative) {                      // => direction== 1
        if (q_k > et0) {                            // check for lower bound
            vout2.out() << "t_O_" << k << ": "
            << x_k << '/' << q_k
            << ( ( q_i != et0) && ( i == B_O[ k]) ? " *" : "")
            << std::endl;
        } else if (q_k < et0) {                     // check for upper bound
            vout2.out() << "t_O_" << k << ": "
            << "inf" << '/' << q_k
            << ( ( q_i != et0) && ( i == B_O[ k]) ? " *" : "")
            << std::endl;
        } else {                                    // q_k == 0
            vout2.out() << "t_O_" << k << ": "
            << "inf"
            << ( ( q_i != et0) && ( i == B_O[ k]) ? " *" : "")
            << std::endl;
        }
    } else {                                        // upper bounded
        if (q_k * ET(direction) > et0) {            // check for lower bound
            if (B_O[k] < qp_n) {                         // original variable
                if (*(qp_fl+B_O[k])) {                   // finite lower bound
                    vout2.out() << "t_O_" << k << ": "
                    << x_k - (d * ET(*(qp_l+B_O[k]))) << '/' << q_k
                    << ( ( q_i != et0) && ( i == B_O[ k]) ? " *" : "")
                    << std::endl;
                } else {                            // lower bound -infinity
                    vout2.out() << "t_O_" << k << ": "
                    << "-inf" << '/' << q_k
                    << ( ( q_i != et0) && ( i == B_O[ k]) ? " *" : "")
                    << std::endl;
                }
            } else {                                // artificial variable
                vout2.out() << "t_O_" << k << ": "
                << x_k << '/' << q_k
                << ( ( q_i != et0) && ( i == B_O[ k]) ? " *" : "")
                << std::endl;
            }
        } else if (q_k * ET(direction) < et0) {     // check for upper bound
            if (B_O[k] < qp_n) {                         // original variable
                if (*(qp_fu+B_O[k])) {                   // finite upper bound
                    vout2.out() << "t_O_" << k << ": "
                    << (d * ET(*(qp_l+B_O[k]))) - x_k << '/' << q_k
                    << ( ( q_i != et0) && ( i == B_O[ k]) ? " *" : "")
                    << std::endl;
                } else {                            // upper bound infinity
                    vout2.out() << "t_O_" << k << ": "
                    << "inf" << '/' << q_k
                    << ( ( q_i != et0) && ( i == B_O[ k]) ? " *" : "")
                    << std::endl;
                }
            } else {                                // artificial variable
                vout2.out() << "t_O_" << k << ": "
                << "inf" << '/' << q_k
                << ( ( q_i != et0) && ( i == B_O[ k]) ? " *" : "")
                << std::endl;
            }
        } else {                                    // q_k == 0
            vout2.out() << "t_O_" << k << ": "
            <<  "inf"
            << ( ( q_i != et0) && ( i == B_O[ k]) ? " *" : "")
            << std::endl;
        }
    }
}

template < typename Q, typename ET, typename Tags >
void  QP_solver<Q, ET, Tags>::
print_ratio_1_slack(int k, const ET& x_k, const ET& q_k)
{
    if (is_nonnegative) {                      // => direction == 1
        if (q_k > et0) {                            // check for lower bound
            vout2.out() << "t_S_" << k << ": "
            << x_k << '/' << q_k
            << ( ( q_i != et0) && ( i == B_S[ k]) ? " *" : "")
            << std::endl;
        } else {                                    // check for upper bound
            vout2.out() << "t_S_" << k << ": "
            << "inf" << '/' << q_k
            << ( ( q_i != et0) && ( i == B_S[ k]) ? " *" : "")
            << std::endl;
        }
    } else {                                        // upper bounded
        if (q_k * ET(direction) > et0) {            // check for lower bound
            vout2.out() << "t_S_" << k << ": "
            << x_k << '/' << q_k
            << ( ( q_i != et0) && ( i == B_S[ k]) ? " *" : "")
            << std::endl;
        } else if (q_k * ET(direction) < et0) {     // check for upper bound
            vout2.out() << "t_S_" << k << ": "
            << "inf" << '/' << q_k
            << ( ( q_i != et0) && ( i == B_S[ k]) ? " *" : "")
            << std::endl;
        } else {                                    // q_k == 0
            vout2.out() << "t_S_" << k << ": "
            << "inf"
            << ( ( q_i != et0) && ( i == B_S[ k]) ? " *" : "")
            << std::endl;
        }
    }
}


template < typename Q, typename ET, typename Tags >
const char*  QP_solver<Q, ET, Tags>::
variable_type( int k) const
{
    return ( k <        qp_n                 ? "original"  :
           ( k < static_cast<int>( qp_n+slack_A.size()) ? "slack"     :
                                               "artificial"));
}

template < typename Q, typename ET, typename Tags >
bool QP_solver<Q, ET, Tags>::
is_artificial(int k) const
{
    return (k >= static_cast<int>(qp_n+slack_A.size()));
}

template < typename Q, typename ET, typename Tags >
int QP_solver<Q, ET, Tags>::
get_l() const
{
    return l;
}

} //namespace CGAL

// ===== EOF ==================================================================

#endif //CGAL_QP_SOLVER_IMPL_H
