You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					2152 lines
				
				50 KiB
			
		
		
			
		
	
	
					2152 lines
				
				50 KiB
			| 
								 
											8 years ago
										 
									 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 *	This file is part of qpOASES.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 *	qpOASES -- An Implementation of the Online Active Set Strategy.
							 | 
						||
| 
								 | 
							
								 *	Copyright (C) 2007-2008 by Hans Joachim Ferreau et al. All rights reserved.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 *	qpOASES is free software; you can redistribute it and/or
							 | 
						||
| 
								 | 
							
								 *	modify it under the terms of the GNU Lesser General Public
							 | 
						||
| 
								 | 
							
								 *	License as published by the Free Software Foundation; either
							 | 
						||
| 
								 | 
							
								 *	version 2.1 of the License, or (at your option) any later version.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 *	qpOASES is distributed in the hope that it will be useful,
							 | 
						||
| 
								 | 
							
								 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
							 | 
						||
| 
								 | 
							
								 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
							 | 
						||
| 
								 | 
							
								 *	Lesser General Public License for more details.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 *	You should have received a copy of the GNU Lesser General Public
							 | 
						||
| 
								 | 
							
								 *	License along with qpOASES; if not, write to the Free Software
							 | 
						||
| 
								 | 
							
								 *	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 *	\file SRC/QProblemB.cpp
							 | 
						||
| 
								 | 
							
								 *	\author Hans Joachim Ferreau
							 | 
						||
| 
								 | 
							
								 *	\version 1.3embedded
							 | 
						||
| 
								 | 
							
								 *	\date 2007-2008
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 *	Implementation of the QProblemB class which is able to use the newly
							 | 
						||
| 
								 | 
							
								 *	developed online active set strategy for parametric quadratic programming.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <QProblemB.hpp>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <stdio.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void printmatrix(char *name, double *A, int m, int n) {
							 | 
						||
| 
								 | 
							
								  int i, j;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  printf("%s = [...\n", name);
							 | 
						||
| 
								 | 
							
								  for (i = 0; i < m; i++) {
							 | 
						||
| 
								 | 
							
								    for (j = 0; j < n; j++)
							 | 
						||
| 
								 | 
							
								        printf("  % 9.4f", A[i*n+j]);
							 | 
						||
| 
								 | 
							
								    printf(",\n");
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  printf("];\n");
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*****************************************************************************
							 | 
						||
| 
								 | 
							
								 *  P U B L I C                                                              *
							 | 
						||
| 
								 | 
							
								 *****************************************************************************/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 *	Q P r o b l e m B
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								QProblemB::QProblemB( )
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									/* reset global message handler */
							 | 
						||
| 
								 | 
							
									getGlobalMessageHandler( )->reset( );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									hasHessian = BT_FALSE;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									bounds.init( 0 );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									hasCholesky = BT_FALSE;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									tau = 0.0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									hessianType = HST_POSDEF_NULLSPACE; /* Hessian is assumed to be positive definite by default */
							 | 
						||
| 
								 | 
							
									infeasible = BT_FALSE;
							 | 
						||
| 
								 | 
							
									unbounded = BT_FALSE;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									status = QPS_NOTINITIALISED;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									#ifdef PC_DEBUG
							 | 
						||
| 
								 | 
							
									printlevel = PL_MEDIUM;
							 | 
						||
| 
								 | 
							
									setPrintLevel( PL_MEDIUM );
							 | 
						||
| 
								 | 
							
									#else
							 | 
						||
| 
								 | 
							
									printlevel = QPOASES_PRINTLEVEL;
							 | 
						||
| 
								 | 
							
									#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									count = 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 *	Q P r o b l e m B
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								QProblemB::QProblemB( int _nV )
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									/* consistency check */
							 | 
						||
| 
								 | 
							
									if ( _nV <= 0 )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										_nV = 1;
							 | 
						||
| 
								 | 
							
										THROWERROR( RET_INVALID_ARGUMENTS );
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									hasHessian = BT_FALSE;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* reset global message handler */
							 | 
						||
| 
								 | 
							
									getGlobalMessageHandler( )->reset( );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									bounds.init( _nV );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									hasCholesky = BT_FALSE;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									tau = 0.0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									hessianType = HST_POSDEF_NULLSPACE; /* Hessian is assumed to be positive definite by default */
							 | 
						||
| 
								 | 
							
									infeasible = BT_FALSE;
							 | 
						||
| 
								 | 
							
									unbounded = BT_FALSE;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									status = QPS_NOTINITIALISED;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									#ifdef PC_DEBUG
							 | 
						||
| 
								 | 
							
									printlevel = PL_MEDIUM;
							 | 
						||
| 
								 | 
							
									setPrintLevel( PL_MEDIUM );
							 | 
						||
| 
								 | 
							
									#else
							 | 
						||
| 
								 | 
							
									printlevel = QPOASES_PRINTLEVEL;
							 | 
						||
| 
								 | 
							
									#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									count = 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 *	Q P r o b l e m B
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								QProblemB::QProblemB( const QProblemB& rhs )
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int i, j;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									int _nV = rhs.bounds.getNV( );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for( i=0; i<_nV; ++i )
							 | 
						||
| 
								 | 
							
										for( j=0; j<_nV; ++j )
							 | 
						||
| 
								 | 
							
											H[i*NVMAX + j] = rhs.H[i*NVMAX + j];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									hasHessian = rhs.hasHessian;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for( i=0; i<_nV; ++i )
							 | 
						||
| 
								 | 
							
										g[i] = rhs.g[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for( i=0; i<_nV; ++i )
							 | 
						||
| 
								 | 
							
										lb[i] = rhs.lb[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for( i=0; i<_nV; ++i )
							 | 
						||
| 
								 | 
							
										ub[i] = rhs.ub[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									bounds = rhs.bounds;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for( i=0; i<_nV; ++i )
							 | 
						||
| 
								 | 
							
										for( j=0; j<_nV; ++j )
							 | 
						||
| 
								 | 
							
											R[i*NVMAX + j] = rhs.R[i*NVMAX + j];
							 | 
						||
| 
								 | 
							
									hasCholesky = rhs.hasCholesky;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for( i=0; i<_nV; ++i )
							 | 
						||
| 
								 | 
							
										x[i] = rhs.x[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for( i=0; i<_nV; ++i )
							 | 
						||
| 
								 | 
							
										y[i] = rhs.y[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									tau = rhs.tau;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									hessianType = rhs.hessianType;
							 | 
						||
| 
								 | 
							
									infeasible = rhs.infeasible;
							 | 
						||
| 
								 | 
							
									unbounded = rhs.unbounded;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									status = rhs.status;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									printlevel = rhs.printlevel;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									count = rhs.count;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 *	~ Q P r o b l e m B
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								QProblemB::~QProblemB( )
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 *	o p e r a t o r =
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								QProblemB& QProblemB::operator=( const QProblemB& rhs )
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int i, j;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if ( this != &rhs )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										int _nV = rhs.bounds.getNV( );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										for( i=0; i<_nV; ++i )
							 | 
						||
| 
								 | 
							
											for( j=0; j<_nV; ++j )
							 | 
						||
| 
								 | 
							
												H[i*NVMAX + j] = rhs.H[i*NVMAX + j];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										hasHessian = rhs.hasHessian;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										for( i=0; i<_nV; ++i )
							 | 
						||
| 
								 | 
							
											g[i] = rhs.g[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										for( i=0; i<_nV; ++i )
							 | 
						||
| 
								 | 
							
											lb[i] = rhs.lb[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										for( i=0; i<_nV; ++i )
							 | 
						||
| 
								 | 
							
											ub[i] = rhs.ub[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										bounds = rhs.bounds;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										for( i=0; i<_nV; ++i )
							 | 
						||
| 
								 | 
							
											for( j=0; j<_nV; ++j )
							 | 
						||
| 
								 | 
							
												R[i*NVMAX + j] = rhs.R[i*NVMAX + j];
							 | 
						||
| 
								 | 
							
										hasCholesky = rhs.hasCholesky;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										for( i=0; i<_nV; ++i )
							 | 
						||
| 
								 | 
							
											x[i] = rhs.x[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										for( i=0; i<_nV; ++i )
							 | 
						||
| 
								 | 
							
											y[i] = rhs.y[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										tau = rhs.tau;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										hessianType = rhs.hessianType;
							 | 
						||
| 
								 | 
							
										infeasible = rhs.infeasible;
							 | 
						||
| 
								 | 
							
										unbounded = rhs.unbounded;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										status = rhs.status;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										printlevel = rhs.printlevel;
							 | 
						||
| 
								 | 
							
										setPrintLevel( rhs.printlevel );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										count = rhs.count;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return *this;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 *	r e s e t
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								returnValue QProblemB::reset( )
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int i, j;
							 | 
						||
| 
								 | 
							
									int nV = getNV( );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/** 0) Reset has Hessian flag. */
							 | 
						||
| 
								 | 
							
									hasHessian = BT_FALSE;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* 1) Reset bounds. */
							 | 
						||
| 
								 | 
							
									bounds.init( nV );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* 2) Reset Cholesky decomposition. */
							 | 
						||
| 
								 | 
							
									for( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
										for( j=0; j<nV; ++j )
							 | 
						||
| 
								 | 
							
											R[i*NVMAX + j] = 0.0;
							 | 
						||
| 
								 | 
							
									hasCholesky = BT_FALSE;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* 3) Reset steplength and status flags. */
							 | 
						||
| 
								 | 
							
									tau = 0.0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									hessianType = HST_POSDEF_NULLSPACE; /* Hessian is assumed to be positive definite by default */
							 | 
						||
| 
								 | 
							
									infeasible = BT_FALSE;
							 | 
						||
| 
								 | 
							
									unbounded = BT_FALSE;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									status = QPS_NOTINITIALISED;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return SUCCESSFUL_RETURN;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 *	i n i t
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								returnValue QProblemB::init(	const real_t* const _H, const real_t* const _g,
							 | 
						||
| 
								 | 
							
																const real_t* const _lb, const real_t* const _ub,
							 | 
						||
| 
								 | 
							
																int& nWSR, const real_t* const yOpt, real_t* const cputime
							 | 
						||
| 
								 | 
							
																)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									/* 1) Setup QP data. */
							 | 
						||
| 
								 | 
							
									if (setupQPdata(_H, 0, _g, _lb, _ub) != SUCCESSFUL_RETURN)
							 | 
						||
| 
								 | 
							
										return THROWERROR( RET_INVALID_ARGUMENTS );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* 2) Call to main initialisation routine (without any additional information). */
							 | 
						||
| 
								 | 
							
									return solveInitialQP(0, yOpt, 0, nWSR, cputime);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								returnValue QProblemB::init(	const real_t* const _H, const real_t* const _R, const real_t* const _g,
							 | 
						||
| 
								 | 
							
																const real_t* const _lb, const real_t* const _ub,
							 | 
						||
| 
								 | 
							
																int& nWSR, const real_t* const yOpt, real_t* const cputime
							 | 
						||
| 
								 | 
							
																)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									/* 1) Setup QP data. */
							 | 
						||
| 
								 | 
							
									if (setupQPdata(_H, _R, _g, _lb, _ub) != SUCCESSFUL_RETURN)
							 | 
						||
| 
								 | 
							
										return THROWERROR( RET_INVALID_ARGUMENTS );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* 2) Call to main initialisation routine (without any additional information). */
							 | 
						||
| 
								 | 
							
									return solveInitialQP(0, yOpt, 0, nWSR, cputime);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 *	h o t s t a r t
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								returnValue QProblemB::hotstart(	const real_t* const g_new, const real_t* const lb_new, const real_t* const ub_new,
							 | 
						||
| 
								 | 
							
																	int& nWSR, real_t* const cputime
							 | 
						||
| 
								 | 
							
																	)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int l;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* consistency check */
							 | 
						||
| 
								 | 
							
									if ( ( getStatus( ) == QPS_NOTINITIALISED )       ||
							 | 
						||
| 
								 | 
							
										 ( getStatus( ) == QPS_PREPARINGAUXILIARYQP ) ||
							 | 
						||
| 
								 | 
							
										 ( getStatus( ) == QPS_PERFORMINGHOMOTOPY )   )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										return THROWERROR( RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED );
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* start runtime measurement */
							 | 
						||
| 
								 | 
							
									real_t starttime = 0.0;
							 | 
						||
| 
								 | 
							
									if ( cputime != 0 )
							 | 
						||
| 
								 | 
							
										starttime = getCPUtime( );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* I) PREPARATIONS */
							 | 
						||
| 
								 | 
							
									/* 1) Reset status flags and increase QP counter. */
							 | 
						||
| 
								 | 
							
									infeasible = BT_FALSE;
							 | 
						||
| 
								 | 
							
									unbounded = BT_FALSE;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									++count;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* 2) Allocate delta vectors of gradient and bounds. */
							 | 
						||
| 
								 | 
							
									returnValue returnvalue;
							 | 
						||
| 
								 | 
							
									BooleanType Delta_bB_isZero;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									int FR_idx[NVMAX];
							 | 
						||
| 
								 | 
							
									int FX_idx[NVMAX];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									real_t delta_g[NVMAX];
							 | 
						||
| 
								 | 
							
									real_t delta_lb[NVMAX];
							 | 
						||
| 
								 | 
							
									real_t delta_ub[NVMAX];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									real_t delta_xFR[NVMAX];
							 | 
						||
| 
								 | 
							
									real_t delta_xFX[NVMAX];
							 | 
						||
| 
								 | 
							
									real_t delta_yFX[NVMAX];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									int BC_idx;
							 | 
						||
| 
								 | 
							
									SubjectToStatus BC_status;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									#ifdef PC_DEBUG
							 | 
						||
| 
								 | 
							
									char messageString[80];
							 | 
						||
| 
								 | 
							
									#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* II) MAIN HOMOTOPY LOOP */
							 | 
						||
| 
								 | 
							
									for( l=0; l<nWSR; ++l )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										status = QPS_PERFORMINGHOMOTOPY;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( printlevel == PL_HIGH )
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											#ifdef PC_DEBUG
							 | 
						||
| 
								 | 
							
											sprintf( messageString,"%d ...",l );
							 | 
						||
| 
								 | 
							
											getGlobalMessageHandler( )->throwInfo( RET_ITERATION_STARTED,messageString,__FUNCTION__,__FILE__,__LINE__,VS_VISIBLE );
							 | 
						||
| 
								 | 
							
											#endif
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/* 1) Setup index arrays. */
							 | 
						||
| 
								 | 
							
										if ( bounds.getFree( )->getNumberArray( FR_idx ) != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
											return THROWERROR( RET_HOTSTART_FAILED );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( bounds.getFixed( )->getNumberArray( FX_idx ) != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
											return THROWERROR( RET_HOTSTART_FAILED );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/* 2) Initialize shift direction of the gradient and the bounds. */
							 | 
						||
| 
								 | 
							
										returnvalue = hotstart_determineDataShift(  FX_idx,
							 | 
						||
| 
								 | 
							
																					g_new,lb_new,ub_new,
							 | 
						||
| 
								 | 
							
																					delta_g,delta_lb,delta_ub,
							 | 
						||
| 
								 | 
							
																					Delta_bB_isZero
							 | 
						||
| 
								 | 
							
																					);
							 | 
						||
| 
								 | 
							
										if ( returnvalue != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											nWSR = l;
							 | 
						||
| 
								 | 
							
											THROWERROR( RET_SHIFT_DETERMINATION_FAILED );
							 | 
						||
| 
								 | 
							
											return returnvalue;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/* 3) Determination of step direction of X and Y. */
							 | 
						||
| 
								 | 
							
										returnvalue = hotstart_determineStepDirection(	FR_idx,FX_idx,
							 | 
						||
| 
								 | 
							
																						delta_g,delta_lb,delta_ub,
							 | 
						||
| 
								 | 
							
																						Delta_bB_isZero,
							 | 
						||
| 
								 | 
							
																						delta_xFX,delta_xFR,delta_yFX
							 | 
						||
| 
								 | 
							
																						);
							 | 
						||
| 
								 | 
							
										if ( returnvalue != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											nWSR = l;
							 | 
						||
| 
								 | 
							
											THROWERROR( RET_STEPDIRECTION_DETERMINATION_FAILED );
							 | 
						||
| 
								 | 
							
											return returnvalue;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/* 4) Determination of step length TAU. */
							 | 
						||
| 
								 | 
							
										returnvalue = hotstart_determineStepLength(	FR_idx,FX_idx,
							 | 
						||
| 
								 | 
							
																					delta_lb,delta_ub,
							 | 
						||
| 
								 | 
							
																					delta_xFR,delta_yFX,
							 | 
						||
| 
								 | 
							
																					BC_idx,BC_status );
							 | 
						||
| 
								 | 
							
										if ( returnvalue != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											nWSR = l;
							 | 
						||
| 
								 | 
							
											THROWERROR( RET_STEPLENGTH_DETERMINATION_FAILED );
							 | 
						||
| 
								 | 
							
											return returnvalue;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/* 5) Realization of the homotopy step. */
							 | 
						||
| 
								 | 
							
										returnvalue = hotstart_performStep(	FR_idx,FX_idx,
							 | 
						||
| 
								 | 
							
																			delta_g,delta_lb,delta_ub,
							 | 
						||
| 
								 | 
							
																			delta_xFX,delta_xFR,delta_yFX,
							 | 
						||
| 
								 | 
							
																			BC_idx,BC_status
							 | 
						||
| 
								 | 
							
																			);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( returnvalue != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											nWSR = l;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											/* stop runtime measurement */
							 | 
						||
| 
								 | 
							
											if ( cputime != 0 )
							 | 
						||
| 
								 | 
							
												*cputime = getCPUtime( ) - starttime;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											/* optimal solution found? */
							 | 
						||
| 
								 | 
							
											if ( returnvalue == RET_OPTIMAL_SOLUTION_FOUND )
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												status = QPS_SOLVED;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if ( printlevel == PL_HIGH )
							 | 
						||
| 
								 | 
							
													THROWINFO( RET_OPTIMAL_SOLUTION_FOUND );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												#ifdef PC_DEBUG
							 | 
						||
| 
								 | 
							
									 			if ( printIteration( l,BC_idx,BC_status ) != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
													THROWERROR( RET_PRINT_ITERATION_FAILED ); /* do not pass this as return value! */
							 | 
						||
| 
								 | 
							
												#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												/* check KKT optimality conditions */
							 | 
						||
| 
								 | 
							
												return checkKKTconditions( );
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											else
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												/* checks for infeasibility... */
							 | 
						||
| 
								 | 
							
												if ( infeasible == BT_TRUE )
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													status = QPS_HOMOTOPYQPSOLVED;
							 | 
						||
| 
								 | 
							
													return THROWERROR( RET_HOTSTART_STOPPED_INFEASIBILITY );
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												/* ...unboundedness... */
							 | 
						||
| 
								 | 
							
												if ( unbounded == BT_TRUE ) /* not necessary since objective function convex! */
							 | 
						||
| 
								 | 
							
													return THROWERROR( RET_HOTSTART_STOPPED_UNBOUNDEDNESS );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												/* ... and throw unspecific error otherwise */
							 | 
						||
| 
								 | 
							
												THROWERROR( RET_HOMOTOPY_STEP_FAILED );
							 | 
						||
| 
								 | 
							
												return returnvalue;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/* 6) Output information of successful QP iteration. */
							 | 
						||
| 
								 | 
							
										status = QPS_HOMOTOPYQPSOLVED;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										#ifdef PC_DEBUG
							 | 
						||
| 
								 | 
							
										if ( printIteration( l,BC_idx,BC_status ) != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
											THROWERROR( RET_PRINT_ITERATION_FAILED ); /* do not pass this as return value! */
							 | 
						||
| 
								 | 
							
										#endif
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* stop runtime measurement */
							 | 
						||
| 
								 | 
							
									if ( cputime != 0 )
							 | 
						||
| 
								 | 
							
										*cputime = getCPUtime( ) - starttime;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* if programm gets to here, output information that QP could not be solved
							 | 
						||
| 
								 | 
							
									 * within the given maximum numbers of working set changes */
							 | 
						||
| 
								 | 
							
									if ( printlevel == PL_HIGH )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										#ifdef PC_DEBUG
							 | 
						||
| 
								 | 
							
										sprintf( messageString,"(nWSR = %d)",nWSR );
							 | 
						||
| 
								 | 
							
										return getGlobalMessageHandler( )->throwWarning( RET_MAX_NWSR_REACHED,messageString,__FUNCTION__,__FILE__,__LINE__,VS_VISIBLE );
							 | 
						||
| 
								 | 
							
										#endif
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* Finally check KKT optimality conditions. */
							 | 
						||
| 
								 | 
							
									returnValue returnvalueKKTcheck = checkKKTconditions( );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if ( returnvalueKKTcheck != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
										return returnvalueKKTcheck;
							 | 
						||
| 
								 | 
							
									else
							 | 
						||
| 
								 | 
							
										return RET_MAX_NWSR_REACHED;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 *	g e t N Z
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								int QProblemB::getNZ( )
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									/* if no constraints are present: nZ=nFR */
							 | 
						||
| 
								 | 
							
									return bounds.getFree( )->getLength( );
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 *	g e t O b j V a l
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								real_t QProblemB::getObjVal( ) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									real_t objVal;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* calculated optimal objective function value
							 | 
						||
| 
								 | 
							
									 * only if current QP has been solved */
							 | 
						||
| 
								 | 
							
									if ( ( getStatus( ) == QPS_AUXILIARYQPSOLVED ) ||
							 | 
						||
| 
								 | 
							
										 ( getStatus( ) == QPS_HOMOTOPYQPSOLVED )  ||
							 | 
						||
| 
								 | 
							
										 ( getStatus( ) == QPS_SOLVED ) )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										objVal = getObjVal( x );
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										objVal = INFTY;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return objVal;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 *	g e t O b j V a l
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								real_t QProblemB::getObjVal( const real_t* const _x ) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int i, j;
							 | 
						||
| 
								 | 
							
									int nV = getNV( );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									real_t obj_tmp = 0.0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										obj_tmp += _x[i]*g[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										for( j=0; j<nV; ++j )
							 | 
						||
| 
								 | 
							
											obj_tmp += 0.5*_x[i]*H[i*NVMAX + j]*_x[j];
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return obj_tmp;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 *	g e t P r i m a l S o l u t i o n
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								returnValue QProblemB::getPrimalSolution( real_t* const xOpt ) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int i;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* return optimal primal solution vector
							 | 
						||
| 
								 | 
							
									 * only if current QP has been solved */
							 | 
						||
| 
								 | 
							
									if ( ( getStatus( ) == QPS_AUXILIARYQPSOLVED ) ||
							 | 
						||
| 
								 | 
							
										 ( getStatus( ) == QPS_HOMOTOPYQPSOLVED )  ||
							 | 
						||
| 
								 | 
							
										 ( getStatus( ) == QPS_SOLVED ) )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										for( i=0; i<getNV( ); ++i )
							 | 
						||
| 
								 | 
							
											xOpt[i] = x[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return SUCCESSFUL_RETURN;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										return RET_QP_NOT_SOLVED;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 *	g e t D u a l S o l u t i o n
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								returnValue QProblemB::getDualSolution( real_t* const yOpt ) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int i;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* return optimal dual solution vector
							 | 
						||
| 
								 | 
							
									 * only if current QP has been solved */
							 | 
						||
| 
								 | 
							
									if ( ( getStatus( ) == QPS_AUXILIARYQPSOLVED ) ||
							 | 
						||
| 
								 | 
							
										 ( getStatus( ) == QPS_HOMOTOPYQPSOLVED )  ||
							 | 
						||
| 
								 | 
							
										 ( getStatus( ) == QPS_SOLVED ) )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										for( i=0; i<getNV( ); ++i )
							 | 
						||
| 
								 | 
							
											yOpt[i] = y[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return SUCCESSFUL_RETURN;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										return RET_QP_NOT_SOLVED;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 *	s e t P r i n t L e v e l
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								returnValue QProblemB::setPrintLevel( PrintLevel _printlevel )
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									#ifndef __MATLAB__
							 | 
						||
| 
								 | 
							
									if ( ( printlevel >= PL_MEDIUM ) && ( printlevel != _printlevel ) )
							 | 
						||
| 
								 | 
							
										THROWINFO( RET_PRINTLEVEL_CHANGED );
							 | 
						||
| 
								 | 
							
									#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									printlevel = _printlevel;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* update message handler preferences */
							 | 
						||
| 
								 | 
							
								 	switch ( printlevel )
							 | 
						||
| 
								 | 
							
								 	{
							 | 
						||
| 
								 | 
							
								 		case PL_NONE:
							 | 
						||
| 
								 | 
							
								 			getGlobalMessageHandler( )->setErrorVisibilityStatus( VS_HIDDEN );
							 | 
						||
| 
								 | 
							
											getGlobalMessageHandler( )->setWarningVisibilityStatus( VS_HIDDEN );
							 | 
						||
| 
								 | 
							
											getGlobalMessageHandler( )->setInfoVisibilityStatus( VS_HIDDEN );
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										case PL_LOW:
							 | 
						||
| 
								 | 
							
								 			getGlobalMessageHandler( )->setErrorVisibilityStatus( VS_VISIBLE );
							 | 
						||
| 
								 | 
							
											getGlobalMessageHandler( )->setWarningVisibilityStatus( VS_HIDDEN );
							 | 
						||
| 
								 | 
							
											getGlobalMessageHandler( )->setInfoVisibilityStatus( VS_HIDDEN );
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								 		default: /* PL_MEDIUM, PL_HIGH */
							 | 
						||
| 
								 | 
							
								 			getGlobalMessageHandler( )->setErrorVisibilityStatus( VS_VISIBLE );
							 | 
						||
| 
								 | 
							
											getGlobalMessageHandler( )->setWarningVisibilityStatus( VS_VISIBLE );
							 | 
						||
| 
								 | 
							
											getGlobalMessageHandler( )->setInfoVisibilityStatus( VS_VISIBLE );
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
								 	}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return SUCCESSFUL_RETURN;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*****************************************************************************
							 | 
						||
| 
								 | 
							
								 *  P R O T E C T E D                                                        *
							 | 
						||
| 
								 | 
							
								 *****************************************************************************/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 *	c h e c k F o r I d e n t i t y H e s s i a n
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								returnValue QProblemB::checkForIdentityHessian( )
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int i, j;
							 | 
						||
| 
								 | 
							
									int nV = getNV( );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* nothing to do as status flag remains unaltered
							 | 
						||
| 
								 | 
							
									 * if Hessian differs from identity matrix */
							 | 
						||
| 
								 | 
							
									if ( hessianType == HST_IDENTITY )
							 | 
						||
| 
								 | 
							
										return SUCCESSFUL_RETURN;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* 1) If Hessian differs from identity matrix,
							 | 
						||
| 
								 | 
							
									 *    return without changing the internal HessianType. */
							 | 
						||
| 
								 | 
							
									for ( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
										if ( getAbs( H[i*NVMAX + i] - 1.0 ) > EPS )
							 | 
						||
| 
								 | 
							
											return SUCCESSFUL_RETURN;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for ( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										for ( j=0; j<i; ++j )
							 | 
						||
| 
								 | 
							
											if ( ( getAbs( H[i*NVMAX + j] ) > EPS ) || ( getAbs( H[j*NVMAX + i] ) > EPS ) )
							 | 
						||
| 
								 | 
							
												return SUCCESSFUL_RETURN;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* 2) If this point is reached, Hessian equals the idetity matrix. */
							 | 
						||
| 
								 | 
							
									hessianType = HST_IDENTITY;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return SUCCESSFUL_RETURN;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 *	s e t u p S u b j e c t T o T y p e
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								returnValue QProblemB::setupSubjectToType( )
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int i;
							 | 
						||
| 
								 | 
							
									int nV = getNV( );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* 1) Check if lower bounds are present. */
							 | 
						||
| 
								 | 
							
									bounds.setNoLower( BT_TRUE );
							 | 
						||
| 
								 | 
							
									for( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
										if ( lb[i] > -INFTY )
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											bounds.setNoLower( BT_FALSE );
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* 2) Check if upper bounds are present. */
							 | 
						||
| 
								 | 
							
									bounds.setNoUpper( BT_TRUE );
							 | 
						||
| 
								 | 
							
									for( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
										if ( ub[i] < INFTY )
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											bounds.setNoUpper( BT_FALSE );
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* 3) Determine implicitly fixed and unbounded variables. */
							 | 
						||
| 
								 | 
							
									int nFV = 0;
							 | 
						||
| 
								 | 
							
									int nUV = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
										if ( ( lb[i] < -INFTY + BOUNDTOL ) && ( ub[i] > INFTY - BOUNDTOL ) )
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											bounds.setType( i,ST_UNBOUNDED );
							 | 
						||
| 
								 | 
							
											++nUV;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										else
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											if ( lb[i] > ub[i] - BOUNDTOL )
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												bounds.setType( i,ST_EQUALITY );
							 | 
						||
| 
								 | 
							
												++nFV;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											else
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												bounds.setType( i,ST_BOUNDED );
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* 4) Set dimensions of bounds structure. */
							 | 
						||
| 
								 | 
							
									bounds.setNFV( nFV );
							 | 
						||
| 
								 | 
							
									bounds.setNUV( nUV );
							 | 
						||
| 
								 | 
							
									bounds.setNBV( nV - nFV - nUV );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return SUCCESSFUL_RETURN;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 *	c h o l e s k y D e c o m p o s i t i o n
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								returnValue QProblemB::setupCholeskyDecomposition( )
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int i, j, k, ii, jj;
							 | 
						||
| 
								 | 
							
									int nV  = getNV( );
							 | 
						||
| 
								 | 
							
									int nFR = getNFR( );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* If Hessian flag is false, it means that H & R already contain Cholesky
							 | 
						||
| 
								 | 
							
									 * factorization -- provided from outside. */
							 | 
						||
| 
								 | 
							
									if (hasHessian == BT_FALSE)
							 | 
						||
| 
								 | 
							
										return SUCCESSFUL_RETURN;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* 1) Initialises R with all zeros. */
							 | 
						||
| 
								 | 
							
									for( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
										for( j=0; j<nV; ++j )
							 | 
						||
| 
								 | 
							
											R[i*NVMAX + j] = 0.0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* 2) Calculate Cholesky decomposition of H (projected to free variables). */
							 | 
						||
| 
								 | 
							
									if ( hessianType == HST_IDENTITY )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										/* if Hessian is identity, so is its Cholesky factor. */
							 | 
						||
| 
								 | 
							
										for( i=0; i<nFR; ++i )
							 | 
						||
| 
								 | 
							
											R[i*NVMAX + i] = 1.0;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										if ( nFR > 0 )
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											int FR_idx[NVMAX];
							 | 
						||
| 
								 | 
							
											if ( bounds.getFree( )->getNumberArray( FR_idx ) != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
												return THROWERROR( RET_INDEXLIST_CORRUPTED );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											/* R'*R = H */
							 | 
						||
| 
								 | 
							
											real_t sum;
							 | 
						||
| 
								 | 
							
											real_t inv;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											for( i=0; i<nFR; ++i )
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												/* j == i */
							 | 
						||
| 
								 | 
							
												ii = FR_idx[i];
							 | 
						||
| 
								 | 
							
												sum = H[ii*NVMAX + ii];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												for( k=(i-1); k>=0; --k )
							 | 
						||
| 
								 | 
							
													sum -= R[k*NVMAX + i] * R[k*NVMAX + i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if ( sum > 0.0 )
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													R[i*NVMAX + i] = sqrt( sum );
							 | 
						||
| 
								 | 
							
													inv = 1.0 / R[i*NVMAX + i];
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													hessianType = HST_SEMIDEF;
							 | 
						||
| 
								 | 
							
													return THROWERROR( RET_HESSIAN_NOT_SPD );
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												/* j > i */
							 | 
						||
| 
								 | 
							
												for( j=(i+1); j<nFR; ++j )
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													jj = FR_idx[j];
							 | 
						||
| 
								 | 
							
													sum = H[jj*NVMAX + ii];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													for( k=(i-1); k>=0; --k )
							 | 
						||
| 
								 | 
							
														sum -= R[k*NVMAX + i] * R[k*NVMAX + j];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													R[i*NVMAX + j] = sum * inv;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return SUCCESSFUL_RETURN;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 *	s o l v e I n i t i a l Q P
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								returnValue QProblemB::solveInitialQP(	const real_t* const xOpt, const real_t* const yOpt,
							 | 
						||
| 
								 | 
							
																		const Bounds* const guessedBounds,
							 | 
						||
| 
								 | 
							
																		int& nWSR, real_t* const cputime
							 | 
						||
| 
								 | 
							
																		)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int i, nFR;
							 | 
						||
| 
								 | 
							
									int nV = getNV( );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* start runtime measurement */
							 | 
						||
| 
								 | 
							
									real_t starttime = 0.0;
							 | 
						||
| 
								 | 
							
									if ( cputime != 0 )
							 | 
						||
| 
								 | 
							
										starttime = getCPUtime( );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									status = QPS_NOTINITIALISED;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* I) ANALYSE QP DATA: */
							 | 
						||
| 
								 | 
							
									/* 1) Check if Hessian happens to be the identity matrix. */
							 | 
						||
| 
								 | 
							
									if ( checkForIdentityHessian( ) != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
										return THROWERROR( RET_INIT_FAILED );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* 2) Setup type of bounds (i.e. unbounded, implicitly fixed etc.). */
							 | 
						||
| 
								 | 
							
									if ( setupSubjectToType( ) != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
										return THROWERROR( RET_INIT_FAILED );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									status = QPS_PREPARINGAUXILIARYQP;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* II) SETUP AUXILIARY QP WITH GIVEN OPTIMAL SOLUTION: */
							 | 
						||
| 
								 | 
							
									/* 1) Setup bounds data structure. */
							 | 
						||
| 
								 | 
							
									if ( bounds.setupAllFree( ) != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
										return THROWERROR( RET_INIT_FAILED );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* 2) Setup optimal primal/dual solution for auxiliary QP. */
							 | 
						||
| 
								 | 
							
									if ( setupAuxiliaryQPsolution( xOpt,yOpt ) != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
										return THROWERROR( RET_INIT_FAILED );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* 3) Obtain linear independent working set for auxiliary QP. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									static Bounds auxiliaryBounds;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									auxiliaryBounds.init( nV );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if ( obtainAuxiliaryWorkingSet( xOpt,yOpt,guessedBounds, &auxiliaryBounds ) != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
										return THROWERROR( RET_INIT_FAILED );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* 4) Setup working set of auxiliary QP and setup cholesky decomposition. */
							 | 
						||
| 
								 | 
							
									if ( setupAuxiliaryWorkingSet( &auxiliaryBounds,BT_TRUE ) != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
										return THROWERROR( RET_INIT_FAILED );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									nFR = getNFR();
							 | 
						||
| 
								 | 
							
									/* At the moment we can only provide a Cholesky of the Hessian if
							 | 
						||
| 
								 | 
							
									 * the solver is cold-started. */
							 | 
						||
| 
								 | 
							
									if (hasCholesky == BT_FALSE || nFR != nV)
							 | 
						||
| 
								 | 
							
										if (setupCholeskyDecomposition() != SUCCESSFUL_RETURN)
							 | 
						||
| 
								 | 
							
											return THROWERROR( RET_INIT_FAILED_CHOLESKY );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* 5) Store original QP formulation... */
							 | 
						||
| 
								 | 
							
									real_t g_original[NVMAX];
							 | 
						||
| 
								 | 
							
									real_t lb_original[NVMAX];
							 | 
						||
| 
								 | 
							
									real_t ub_original[NVMAX];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
										g_original[i] = g[i];
							 | 
						||
| 
								 | 
							
									for( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
										lb_original[i] = lb[i];
							 | 
						||
| 
								 | 
							
									for( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
										ub_original[i] = ub[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* ... and setup QP data of an auxiliary QP having an optimal solution
							 | 
						||
| 
								 | 
							
									 * as specified by the user (or xOpt = yOpt = 0, by default). */
							 | 
						||
| 
								 | 
							
									if ( setupAuxiliaryQPgradient( ) != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
										return THROWERROR( RET_INIT_FAILED );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if ( setupAuxiliaryQPbounds( BT_TRUE ) != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
										return THROWERROR( RET_INIT_FAILED );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									status = QPS_AUXILIARYQPSOLVED;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* III) SOLVE ACTUAL INITIAL QP: */
							 | 
						||
| 
								 | 
							
									/* Use hotstart method to find the solution of the original initial QP,... */
							 | 
						||
| 
								 | 
							
									returnValue returnvalue = hotstart( g_original,lb_original,ub_original, nWSR,0 );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* ... check for infeasibility and unboundedness... */
							 | 
						||
| 
								 | 
							
									if ( isInfeasible( ) == BT_TRUE )
							 | 
						||
| 
								 | 
							
										return THROWERROR( RET_INIT_FAILED_INFEASIBILITY );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if ( isUnbounded( ) == BT_TRUE )
							 | 
						||
| 
								 | 
							
										return THROWERROR( RET_INIT_FAILED_UNBOUNDEDNESS );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* ... and internal errors. */
							 | 
						||
| 
								 | 
							
									if ( ( returnvalue != SUCCESSFUL_RETURN ) && ( returnvalue != RET_MAX_NWSR_REACHED )  &&
							 | 
						||
| 
								 | 
							
									     ( returnvalue != RET_INACCURATE_SOLUTION ) && ( returnvalue != RET_NO_SOLUTION ) )
							 | 
						||
| 
								 | 
							
										return THROWERROR( RET_INIT_FAILED_HOTSTART );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* stop runtime measurement */
							 | 
						||
| 
								 | 
							
									if ( cputime != 0 )
							 | 
						||
| 
								 | 
							
										*cputime = getCPUtime( ) - starttime;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if ( printlevel == PL_HIGH )
							 | 
						||
| 
								 | 
							
										THROWINFO( RET_INIT_SUCCESSFUL );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return returnvalue;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 *	o b t a i n A u x i l i a r y W o r k i n g S e t
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								returnValue QProblemB::obtainAuxiliaryWorkingSet(	const real_t* const xOpt, const real_t* const yOpt,
							 | 
						||
| 
								 | 
							
																					const Bounds* const guessedBounds, Bounds* auxiliaryBounds
							 | 
						||
| 
								 | 
							
																					) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int i = 0;
							 | 
						||
| 
								 | 
							
									int nV = getNV( );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* 1) Ensure that desiredBounds is allocated (and different from guessedBounds). */
							 | 
						||
| 
								 | 
							
									if ( ( auxiliaryBounds == 0 ) || ( auxiliaryBounds == guessedBounds ) )
							 | 
						||
| 
								 | 
							
										return THROWERROR( RET_INVALID_ARGUMENTS );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* 2) Setup working set for auxiliary initial QP. */
							 | 
						||
| 
								 | 
							
									if ( guessedBounds != 0 )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										/* If an initial working set is specific, use it!
							 | 
						||
| 
								 | 
							
										 * Moreover, add all implictly fixed variables if specified. */
							 | 
						||
| 
								 | 
							
										for( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											if ( bounds.getType( i ) == ST_EQUALITY )
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												if ( auxiliaryBounds->setupBound( i,ST_LOWER ) != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
													return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											else
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												if ( auxiliaryBounds->setupBound( i,guessedBounds->getStatus( i ) ) != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
													return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else	/* No initial working set specified. */
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										if ( ( xOpt != 0 ) && ( yOpt == 0 ) )
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											/* Obtain initial working set by "clipping". */
							 | 
						||
| 
								 | 
							
											for( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												if ( xOpt[i] <= lb[i] + BOUNDTOL )
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													if ( auxiliaryBounds->setupBound( i,ST_LOWER ) != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
														return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
							 | 
						||
| 
								 | 
							
													continue;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if ( xOpt[i] >= ub[i] - BOUNDTOL )
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													if ( auxiliaryBounds->setupBound( i,ST_UPPER ) != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
														return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
							 | 
						||
| 
								 | 
							
													continue;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												/* Moreover, add all implictly fixed variables if specified. */
							 | 
						||
| 
								 | 
							
												if ( bounds.getType( i ) == ST_EQUALITY )
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													if ( auxiliaryBounds->setupBound( i,ST_LOWER ) != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
														return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													if ( auxiliaryBounds->setupBound( i,ST_INACTIVE ) != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
														return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( ( xOpt == 0 ) && ( yOpt != 0 ) )
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											/* Obtain initial working set in accordance to sign of dual solution vector. */
							 | 
						||
| 
								 | 
							
											for( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												if ( yOpt[i] > ZERO )
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													if ( auxiliaryBounds->setupBound( i,ST_LOWER ) != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
														return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
							 | 
						||
| 
								 | 
							
													continue;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if ( yOpt[i] < -ZERO )
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													if ( auxiliaryBounds->setupBound( i,ST_UPPER ) != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
														return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
							 | 
						||
| 
								 | 
							
													continue;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												/* Moreover, add all implictly fixed variables if specified. */
							 | 
						||
| 
								 | 
							
												if ( bounds.getType( i ) == ST_EQUALITY )
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													if ( auxiliaryBounds->setupBound( i,ST_LOWER ) != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
														return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													if ( auxiliaryBounds->setupBound( i,ST_INACTIVE ) != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
														return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/* If xOpt and yOpt are null pointer and no initial working is specified,
							 | 
						||
| 
								 | 
							
										 * start with empty working set (or implicitly fixed bounds only)
							 | 
						||
| 
								 | 
							
										 * for auxiliary QP. */
							 | 
						||
| 
								 | 
							
										if ( ( xOpt == 0 ) && ( yOpt == 0 ) )
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											for( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												/* Only add all implictly fixed variables if specified. */
							 | 
						||
| 
								 | 
							
												if ( bounds.getType( i ) == ST_EQUALITY )
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													if ( auxiliaryBounds->setupBound( i,ST_LOWER ) != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
														return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													if ( auxiliaryBounds->setupBound( i,ST_INACTIVE ) != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
														return THROWERROR( RET_OBTAINING_WORKINGSET_FAILED );
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return SUCCESSFUL_RETURN;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 *	s e t u p A u x i l i a r y W o r k i n g S e t
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								returnValue QProblemB::setupAuxiliaryWorkingSet( 	const Bounds* const auxiliaryBounds,
							 | 
						||
| 
								 | 
							
																					BooleanType setupAfresh
							 | 
						||
| 
								 | 
							
																					)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int i;
							 | 
						||
| 
								 | 
							
									int nV = getNV( );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* consistency checks */
							 | 
						||
| 
								 | 
							
									if ( auxiliaryBounds != 0 )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										for( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
											if ( ( bounds.getStatus( i ) == ST_UNDEFINED ) || ( auxiliaryBounds->getStatus( i ) == ST_UNDEFINED ) )
							 | 
						||
| 
								 | 
							
												return THROWERROR( RET_UNKNOWN_BUG );
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										return THROWERROR( RET_INVALID_ARGUMENTS );
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* I) SETUP CHOLESKY FLAG:
							 | 
						||
| 
								 | 
							
									 *    Cholesky decomposition shall only be updated if working set
							 | 
						||
| 
								 | 
							
									 *    shall be updated (i.e. NOT setup afresh!) */
							 | 
						||
| 
								 | 
							
									BooleanType updateCholesky;
							 | 
						||
| 
								 | 
							
									if ( setupAfresh == BT_TRUE )
							 | 
						||
| 
								 | 
							
										updateCholesky = BT_FALSE;
							 | 
						||
| 
								 | 
							
									else
							 | 
						||
| 
								 | 
							
										updateCholesky = BT_TRUE;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* II) REMOVE FORMERLY ACTIVE BOUNDS (IF NECESSARY): */
							 | 
						||
| 
								 | 
							
									if ( setupAfresh == BT_FALSE )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										/* Remove all active bounds that shall be inactive AND
							 | 
						||
| 
								 | 
							
										*  all active bounds that are active at the wrong bound. */
							 | 
						||
| 
								 | 
							
										for( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											if ( ( bounds.getStatus( i ) == ST_LOWER ) && ( auxiliaryBounds->getStatus( i ) != ST_LOWER ) )
							 | 
						||
| 
								 | 
							
												if ( removeBound( i,updateCholesky ) != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
													return THROWERROR( RET_SETUP_WORKINGSET_FAILED );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if ( ( bounds.getStatus( i ) == ST_UPPER ) && ( auxiliaryBounds->getStatus( i ) != ST_UPPER ) )
							 | 
						||
| 
								 | 
							
												if ( removeBound( i,updateCholesky ) != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
													return THROWERROR( RET_SETUP_WORKINGSET_FAILED );
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* III) ADD NEWLY ACTIVE BOUNDS: */
							 | 
						||
| 
								 | 
							
									/*      Add all inactive bounds that shall be active AND
							 | 
						||
| 
								 | 
							
									 *      all formerly active bounds that have been active at the wrong bound. */
							 | 
						||
| 
								 | 
							
									for( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										if ( ( bounds.getStatus( i ) == ST_INACTIVE ) && ( auxiliaryBounds->getStatus( i ) != ST_INACTIVE ) )
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											if ( addBound( i,auxiliaryBounds->getStatus( i ),updateCholesky ) != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
												return THROWERROR( RET_SETUP_WORKINGSET_FAILED );
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return SUCCESSFUL_RETURN;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 *	s e t u p A u x i l i a r y Q P s o l u t i o n
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								returnValue QProblemB::setupAuxiliaryQPsolution(	const real_t* const xOpt, const real_t* const yOpt
							 | 
						||
| 
								 | 
							
																					)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int i;
							 | 
						||
| 
								 | 
							
									int nV = getNV( );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* Setup primal/dual solution vectors for auxiliary initial QP:
							 | 
						||
| 
								 | 
							
									 * if a null pointer is passed, a zero vector is assigned;
							 | 
						||
| 
								 | 
							
									 * old solution vector is kept if pointer to internal solution vector is passed. */
							 | 
						||
| 
								 | 
							
									if ( xOpt != 0 )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										if ( xOpt != x )
							 | 
						||
| 
								 | 
							
											for( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
												x[i] = xOpt[i];
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										for( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
											x[i] = 0.0;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if ( yOpt != 0 )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										if ( yOpt != y )
							 | 
						||
| 
								 | 
							
											for( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
												y[i] = yOpt[i];
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										for( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
											y[i] = 0.0;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return SUCCESSFUL_RETURN;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 *	s e t u p A u x i l i a r y Q P g r a d i e n t
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								returnValue QProblemB::setupAuxiliaryQPgradient( )
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int i, j;
							 | 
						||
| 
								 | 
							
									int nV = getNV( );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* Setup gradient vector: g = -H*x + y'*Id. */
							 | 
						||
| 
								 | 
							
									for ( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										/* y'*Id */
							 | 
						||
| 
								 | 
							
										g[i] = y[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/* -H*x */
							 | 
						||
| 
								 | 
							
										for ( j=0; j<nV; ++j )
							 | 
						||
| 
								 | 
							
											g[i] -= H[i*NVMAX + j] * x[j];
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return SUCCESSFUL_RETURN;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 *	s e t u p A u x i l i a r y Q P b o u n d s
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								returnValue QProblemB::setupAuxiliaryQPbounds( BooleanType useRelaxation )
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int i;
							 | 
						||
| 
								 | 
							
									int nV = getNV( );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* Setup bound vectors. */
							 | 
						||
| 
								 | 
							
									for ( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										switch ( bounds.getStatus( i ) )
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											case ST_INACTIVE:
							 | 
						||
| 
								 | 
							
												if ( useRelaxation == BT_TRUE )
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													if ( bounds.getType( i ) == ST_EQUALITY )
							 | 
						||
| 
								 | 
							
													{
							 | 
						||
| 
								 | 
							
														lb[i] = x[i];
							 | 
						||
| 
								 | 
							
														ub[i] = x[i];
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
													else
							 | 
						||
| 
								 | 
							
													{
							 | 
						||
| 
								 | 
							
														lb[i] = x[i] - BOUNDRELAXATION;
							 | 
						||
| 
								 | 
							
														ub[i] = x[i] + BOUNDRELAXATION;
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											case ST_LOWER:
							 | 
						||
| 
								 | 
							
												lb[i] = x[i];
							 | 
						||
| 
								 | 
							
												if ( bounds.getType( i ) == ST_EQUALITY )
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													ub[i] = x[i];
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													if ( useRelaxation == BT_TRUE )
							 | 
						||
| 
								 | 
							
														ub[i] = x[i] + BOUNDRELAXATION;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											case ST_UPPER:
							 | 
						||
| 
								 | 
							
												ub[i] = x[i];
							 | 
						||
| 
								 | 
							
												if ( bounds.getType( i ) == ST_EQUALITY )
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													lb[i] = x[i];
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												else
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													if ( useRelaxation == BT_TRUE )
							 | 
						||
| 
								 | 
							
														lb[i] = x[i] - BOUNDRELAXATION;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											default:
							 | 
						||
| 
								 | 
							
												return THROWERROR( RET_UNKNOWN_BUG );
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return SUCCESSFUL_RETURN;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 *	a d d B o u n d
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								returnValue QProblemB::addBound(	int number, SubjectToStatus B_status,
							 | 
						||
| 
								 | 
							
																	BooleanType updateCholesky
							 | 
						||
| 
								 | 
							
																	)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int i, j;
							 | 
						||
| 
								 | 
							
									int nFR = getNFR( );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* consistency check */
							 | 
						||
| 
								 | 
							
									if ( ( getStatus( ) == QPS_NOTINITIALISED )    ||
							 | 
						||
| 
								 | 
							
										 ( getStatus( ) == QPS_AUXILIARYQPSOLVED ) ||
							 | 
						||
| 
								 | 
							
										 ( getStatus( ) == QPS_HOMOTOPYQPSOLVED )  ||
							 | 
						||
| 
								 | 
							
										 ( getStatus( ) == QPS_SOLVED )            )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										return THROWERROR( RET_UNKNOWN_BUG );
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* Perform cholesky updates only if QProblemB has been initialised! */
							 | 
						||
| 
								 | 
							
									if ( ( getStatus( ) == QPS_PREPARINGAUXILIARYQP ) || ( updateCholesky == BT_FALSE ) )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										/* UPDATE INDICES */
							 | 
						||
| 
								 | 
							
										if ( bounds.moveFreeToFixed( number,B_status ) != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
											return THROWERROR( RET_ADDBOUND_FAILED );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return SUCCESSFUL_RETURN;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* I) PERFORM CHOLESKY UPDATE: */
							 | 
						||
| 
								 | 
							
									/* 1) Index of variable to be added within the list of free variables. */
							 | 
						||
| 
								 | 
							
									int number_idx = bounds.getFree( )->getIndex( number );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									real_t c, s;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* 2) Use row-wise Givens rotations to restore upper triangular form of R. */
							 | 
						||
| 
								 | 
							
									for( i=number_idx+1; i<nFR; ++i )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										computeGivens( R[(i-1)*NVMAX + i],R[i*NVMAX + i], R[(i-1)*NVMAX + i],R[i*NVMAX + i],c,s );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										for( j=(1+i); j<nFR; ++j ) /* last column of R is thrown away */
							 | 
						||
| 
								 | 
							
											applyGivens( c,s,R[(i-1)*NVMAX + j],R[i*NVMAX + j], R[(i-1)*NVMAX + j],R[i*NVMAX + j] );
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* 3) Delete <number_idx>th column and ... */
							 | 
						||
| 
								 | 
							
									for( i=0; i<nFR-1; ++i )
							 | 
						||
| 
								 | 
							
										for( j=number_idx+1; j<nFR; ++j )
							 | 
						||
| 
								 | 
							
											R[i*NVMAX + j-1] = R[i*NVMAX + j];
							 | 
						||
| 
								 | 
							
									/* ... last column of R. */
							 | 
						||
| 
								 | 
							
									for( i=0; i<nFR; ++i )
							 | 
						||
| 
								 | 
							
										R[i*NVMAX + nFR-1] = 0.0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* II) UPDATE INDICES */
							 | 
						||
| 
								 | 
							
									if ( bounds.moveFreeToFixed( number,B_status ) != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
										return THROWERROR( RET_ADDBOUND_FAILED );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return SUCCESSFUL_RETURN;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								returnValue QProblemB::removeBound(	int number,
							 | 
						||
| 
								 | 
							
																	BooleanType updateCholesky
							 | 
						||
| 
								 | 
							
																	)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int i, ii;
							 | 
						||
| 
								 | 
							
									int nFR = getNFR( );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* consistency check */
							 | 
						||
| 
								 | 
							
									if ( ( getStatus( ) == QPS_NOTINITIALISED )    ||
							 | 
						||
| 
								 | 
							
										 ( getStatus( ) == QPS_AUXILIARYQPSOLVED ) ||
							 | 
						||
| 
								 | 
							
										 ( getStatus( ) == QPS_HOMOTOPYQPSOLVED )  ||
							 | 
						||
| 
								 | 
							
										 ( getStatus( ) == QPS_SOLVED )            )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										return THROWERROR( RET_UNKNOWN_BUG );
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* I) UPDATE INDICES */
							 | 
						||
| 
								 | 
							
									if ( bounds.moveFixedToFree( number ) != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
										return THROWERROR( RET_REMOVEBOUND_FAILED );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* Perform cholesky updates only if QProblemB has been initialised! */
							 | 
						||
| 
								 | 
							
									if ( ( getStatus( ) == QPS_PREPARINGAUXILIARYQP ) || ( updateCholesky == BT_FALSE ) )
							 | 
						||
| 
								 | 
							
										return SUCCESSFUL_RETURN;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* II) PERFORM CHOLESKY UPDATE */
							 | 
						||
| 
								 | 
							
									int FR_idx[NVMAX];
							 | 
						||
| 
								 | 
							
									if ( bounds.getFree( )->getNumberArray( FR_idx ) != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
										return THROWERROR( RET_REMOVEBOUND_FAILED );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* 1) Calculate new column of cholesky decomposition. */
							 | 
						||
| 
								 | 
							
									real_t rhs[NVMAX];
							 | 
						||
| 
								 | 
							
									real_t r[NVMAX];
							 | 
						||
| 
								 | 
							
									real_t r0 = H[number*NVMAX + number];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for( i=0; i<nFR; ++i )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										ii = FR_idx[i];
							 | 
						||
| 
								 | 
							
										rhs[i] = H[number*NVMAX + ii];
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if ( backsolveR( rhs,BT_TRUE,BT_TRUE,r ) != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
										return THROWERROR( RET_REMOVEBOUND_FAILED );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for( i=0; i<nFR; ++i )
							 | 
						||
| 
								 | 
							
										r0 -= r[i]*r[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* 2) Store new column into R. */
							 | 
						||
| 
								 | 
							
									for( i=0; i<nFR; ++i )
							 | 
						||
| 
								 | 
							
										R[i*NVMAX + nFR] = r[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if ( r0 > 0.0 )
							 | 
						||
| 
								 | 
							
										R[nFR*NVMAX + nFR] = sqrt( r0 );
							 | 
						||
| 
								 | 
							
									else
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										hessianType = HST_SEMIDEF;
							 | 
						||
| 
								 | 
							
										return THROWERROR( RET_HESSIAN_NOT_SPD );
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return SUCCESSFUL_RETURN;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 *	b a c k s o l v e R  (CODE DUPLICATED IN QProblem CLASS!!!)
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								returnValue QProblemB::backsolveR(	const real_t* const b, BooleanType transposed,
							 | 
						||
| 
								 | 
							
																	real_t* const a
							 | 
						||
| 
								 | 
							
																	)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									/* Call standard backsolve procedure (i.e. removingBound == BT_FALSE). */
							 | 
						||
| 
								 | 
							
									return backsolveR( b,transposed,BT_FALSE,a );
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 *	b a c k s o l v e R  (CODE DUPLICATED IN QProblem CLASS!!!)
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								returnValue QProblemB::backsolveR(	const real_t* const b, BooleanType transposed,
							 | 
						||
| 
								 | 
							
																	BooleanType removingBound,
							 | 
						||
| 
								 | 
							
																	real_t* const a
							 | 
						||
| 
								 | 
							
																	)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int i, j;
							 | 
						||
| 
								 | 
							
									int nR = getNZ( );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									real_t sum;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* if backsolve is called while removing a bound, reduce nZ by one. */
							 | 
						||
| 
								 | 
							
									if ( removingBound == BT_TRUE )
							 | 
						||
| 
								 | 
							
										--nR;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* nothing to do */
							 | 
						||
| 
								 | 
							
									if ( nR <= 0 )
							 | 
						||
| 
								 | 
							
										return SUCCESSFUL_RETURN;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* Solve Ra = b, where R might be transposed. */
							 | 
						||
| 
								 | 
							
									if ( transposed == BT_FALSE )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										/* solve Ra = b */
							 | 
						||
| 
								 | 
							
										for( i=(nR-1); i>=0; --i )
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											sum = b[i];
							 | 
						||
| 
								 | 
							
											for( j=(i+1); j<nR; ++j )
							 | 
						||
| 
								 | 
							
												sum -= R[i*NVMAX + j] * a[j];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if ( getAbs( R[i*NVMAX + i] ) > ZERO )
							 | 
						||
| 
								 | 
							
												a[i] = sum / R[i*NVMAX + i];
							 | 
						||
| 
								 | 
							
											else
							 | 
						||
| 
								 | 
							
												return THROWERROR( RET_DIV_BY_ZERO );
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										/* solve R^T*a = b */
							 | 
						||
| 
								 | 
							
										for( i=0; i<nR; ++i )
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											sum = b[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											for( j=0; j<i; ++j )
							 | 
						||
| 
								 | 
							
												sum -= R[j*NVMAX + i] * a[j];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if ( getAbs( R[i*NVMAX + i] ) > ZERO )
							 | 
						||
| 
								 | 
							
												a[i] = sum / R[i*NVMAX + i];
							 | 
						||
| 
								 | 
							
											else
							 | 
						||
| 
								 | 
							
												return THROWERROR( RET_DIV_BY_ZERO );
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return SUCCESSFUL_RETURN;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 *	h o t s t a r t _ d e t e r m i n e D a t a S h i f t
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								returnValue QProblemB::hotstart_determineDataShift(	const int* const FX_idx,
							 | 
						||
| 
								 | 
							
																					const real_t* const g_new, const real_t* const lb_new, const real_t* const ub_new,
							 | 
						||
| 
								 | 
							
																					real_t* const delta_g, real_t* const delta_lb, real_t* const delta_ub,
							 | 
						||
| 
								 | 
							
																					BooleanType& Delta_bB_isZero
							 | 
						||
| 
								 | 
							
																					)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int i, ii;
							 | 
						||
| 
								 | 
							
									int nV  = getNV( );
							 | 
						||
| 
								 | 
							
									int nFX = getNFX( );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* 1) Calculate shift directions. */
							 | 
						||
| 
								 | 
							
									for( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
										delta_g[i]  = g_new[i]  - g[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if ( lb_new != 0 )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										for( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
											delta_lb[i] = lb_new[i] - lb[i];
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										/* if no lower bounds exist, assume the new lower bounds to be -infinity */
							 | 
						||
| 
								 | 
							
										for( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
											delta_lb[i] = -INFTY - lb[i];
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if ( ub_new != 0 )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										for( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
											delta_ub[i] = ub_new[i] - ub[i];
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										/* if no upper bounds exist, assume the new upper bounds to be infinity */
							 | 
						||
| 
								 | 
							
										for( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
											delta_ub[i] = INFTY - ub[i];
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* 2) Determine if active bounds are to be shifted. */
							 | 
						||
| 
								 | 
							
									Delta_bB_isZero = BT_TRUE;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for ( i=0; i<nFX; ++i )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										ii = FX_idx[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( ( getAbs( delta_lb[ii] ) > EPS ) || ( getAbs( delta_ub[ii] ) > EPS ) )
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											Delta_bB_isZero = BT_FALSE;
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return SUCCESSFUL_RETURN;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 *	a r e B o u n d s C o n s i s t e n t
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								BooleanType QProblemB::areBoundsConsistent(	const real_t* const delta_lb, const real_t* const delta_ub
							 | 
						||
| 
								 | 
							
																			) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int i;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* Check if delta_lb[i] is greater than delta_ub[i]
							 | 
						||
| 
								 | 
							
									 * for a component i whose bounds are already (numerically) equal. */
							 | 
						||
| 
								 | 
							
									for( i=0; i<getNV( ); ++i )
							 | 
						||
| 
								 | 
							
										if ( ( lb[i] > ub[i] - BOUNDTOL ) && ( delta_lb[i] > delta_ub[i] + EPS ) )
							 | 
						||
| 
								 | 
							
											return BT_FALSE;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return BT_TRUE;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 *	s e t u p Q P d a t a
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								returnValue QProblemB::setupQPdata(	const real_t* const _H, const real_t* const _R, const real_t* const _g,
							 | 
						||
| 
								 | 
							
																	const real_t* const _lb, const real_t* const _ub
							 | 
						||
| 
								 | 
							
																	)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int i, j;
							 | 
						||
| 
								 | 
							
									int nV = getNV( );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* 1) Setup Hessian matrix and it's Cholesky factorization. */
							 | 
						||
| 
								 | 
							
									if (_H != 0)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										for( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
											for( j=0; j<nV; ++j )
							 | 
						||
| 
								 | 
							
												H[i*NVMAX + j] = _H[i*nV + j];
							 | 
						||
| 
								 | 
							
										hasHessian = BT_TRUE;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else
							 | 
						||
| 
								 | 
							
										hasHessian = BT_FALSE;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (_R != 0)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										for( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
											for( j=0; j<nV; ++j )
							 | 
						||
| 
								 | 
							
												R[i*NVMAX + j] = _R[i*nV + j];
							 | 
						||
| 
								 | 
							
										hasCholesky = BT_TRUE;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/* If Hessian is not provided, store it's factorization in H, and that guy
							 | 
						||
| 
								 | 
							
										 * is going to be used for H * x products (R^T * R * x in this case). */
							 | 
						||
| 
								 | 
							
										if (hasHessian == BT_FALSE)
							 | 
						||
| 
								 | 
							
											for( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
												for( j=0; j<nV; ++j )
							 | 
						||
| 
								 | 
							
													H[i*NVMAX + j] = _R[i*nV + j];
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else
							 | 
						||
| 
								 | 
							
										hasCholesky = BT_FALSE;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (hasHessian == BT_FALSE && hasCholesky == BT_FALSE)
							 | 
						||
| 
								 | 
							
										return THROWERROR( RET_INVALID_ARGUMENTS );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* 2) Setup gradient vector. */
							 | 
						||
| 
								 | 
							
									if ( _g == 0 )
							 | 
						||
| 
								 | 
							
										return THROWERROR( RET_INVALID_ARGUMENTS );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
										g[i] = _g[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* 3) Setup lower bounds vector. */
							 | 
						||
| 
								 | 
							
									if ( _lb != 0 )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										for( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
											lb[i] = _lb[i];
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										/* if no lower bounds are specified, set them to -infinity */
							 | 
						||
| 
								 | 
							
										for( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
											lb[i] = -INFTY;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* 4) Setup upper bounds vector. */
							 | 
						||
| 
								 | 
							
									if ( _ub != 0 )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										for( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
											ub[i] = _ub[i];
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										/* if no upper bounds are specified, set them to infinity */
							 | 
						||
| 
								 | 
							
										for( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
											ub[i] = INFTY;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									//printmatrix( "H",H,nV,nV );
							 | 
						||
| 
								 | 
							
									//printmatrix( "R",R,nV,nV );
							 | 
						||
| 
								 | 
							
									//printmatrix( "g",g,1,nV );
							 | 
						||
| 
								 | 
							
									//printmatrix( "lb",lb,1,nV );
							 | 
						||
| 
								 | 
							
									//printmatrix( "ub",ub,1,nV );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return SUCCESSFUL_RETURN;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*****************************************************************************
							 | 
						||
| 
								 | 
							
								 *  P R I V A T E                                                            *
							 | 
						||
| 
								 | 
							
								 *****************************************************************************/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 *	h o t s t a r t _ d e t e r m i n e S t e p D i r e c t i o n
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								returnValue QProblemB::hotstart_determineStepDirection(	const int* const FR_idx, const int* const FX_idx,
							 | 
						||
| 
								 | 
							
																						const real_t* const delta_g, const real_t* const delta_lb, const real_t* const delta_ub,
							 | 
						||
| 
								 | 
							
																						BooleanType Delta_bB_isZero,
							 | 
						||
| 
								 | 
							
																						real_t* const delta_xFX, real_t* const delta_xFR,
							 | 
						||
| 
								 | 
							
																						real_t* const delta_yFX
							 | 
						||
| 
								 | 
							
																						)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int i, j, ii, jj;
							 | 
						||
| 
								 | 
							
									int nFR = getNFR( );
							 | 
						||
| 
								 | 
							
									int nFX = getNFX( );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* initialise auxiliary vectors */
							 | 
						||
| 
								 | 
							
									real_t HMX_delta_xFX[NVMAX];
							 | 
						||
| 
								 | 
							
									for( i=0; i<nFR; ++i )
							 | 
						||
| 
								 | 
							
										HMX_delta_xFX[i] = 0.0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* I) DETERMINE delta_xFX */
							 | 
						||
| 
								 | 
							
									if ( nFX > 0 )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										for( i=0; i<nFX; ++i )
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											ii = FX_idx[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if ( bounds.getStatus( ii ) == ST_LOWER )
							 | 
						||
| 
								 | 
							
												delta_xFX[i] = delta_lb[ii];
							 | 
						||
| 
								 | 
							
											else
							 | 
						||
| 
								 | 
							
												delta_xFX[i] = delta_ub[ii];
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* II) DETERMINE delta_xFR */
							 | 
						||
| 
								 | 
							
									if ( nFR > 0 )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										/* auxiliary variables */
							 | 
						||
| 
								 | 
							
										real_t delta_xFRz_TMP[NVMAX];
							 | 
						||
| 
								 | 
							
										real_t delta_xFRz_RHS[NVMAX];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/* Determine delta_xFRz. */
							 | 
						||
| 
								 | 
							
										if ( Delta_bB_isZero == BT_FALSE )
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											for( i=0; i<nFR; ++i )
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												ii = FR_idx[i];
							 | 
						||
| 
								 | 
							
												for( j=0; j<nFX; ++j )
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													jj = FX_idx[j];
							 | 
						||
| 
								 | 
							
													HMX_delta_xFX[i] += H[ii*NVMAX + jj] * delta_xFX[j];
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( Delta_bB_isZero == BT_TRUE )
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											for( j=0; j<nFR; ++j )
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												jj = FR_idx[j];
							 | 
						||
| 
								 | 
							
												delta_xFRz_RHS[j] = delta_g[jj];
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										else
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											for( j=0; j<nFR; ++j )
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												jj = FR_idx[j];
							 | 
						||
| 
								 | 
							
												delta_xFRz_RHS[j] = delta_g[jj] + HMX_delta_xFX[j]; /* *ZFR */
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										for( i=0; i<nFR; ++i )
							 | 
						||
| 
								 | 
							
											delta_xFR[i] = -delta_xFRz_RHS[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( backsolveR( delta_xFR,BT_TRUE,delta_xFRz_TMP ) != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
											return THROWERROR( RET_STEPDIRECTION_FAILED_CHOLESKY );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( backsolveR( delta_xFRz_TMP,BT_FALSE,delta_xFR ) != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
											return THROWERROR( RET_STEPDIRECTION_FAILED_CHOLESKY );
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* III) DETERMINE delta_yFX */
							 | 
						||
| 
								 | 
							
									if ( nFX > 0 )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										for( i=0; i<nFX; ++i )
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											ii = FX_idx[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											delta_yFX[i] = 0.0;
							 | 
						||
| 
								 | 
							
											for( j=0; j<nFR; ++j )
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												jj = FR_idx[j];
							 | 
						||
| 
								 | 
							
												delta_yFX[i] += H[ii*NVMAX + jj] * delta_xFR[j];
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if ( Delta_bB_isZero == BT_FALSE )
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												for( j=0; j<nFX; ++j )
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													jj = FX_idx[j];
							 | 
						||
| 
								 | 
							
													delta_yFX[i] += H[ii*NVMAX + jj] * delta_xFX[j];
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											delta_yFX[i] += delta_g[ii];
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return SUCCESSFUL_RETURN;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 *	h o t s t a r t _ d e t e r m i n e S t e p L e n g t h
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								returnValue QProblemB::hotstart_determineStepLength(	const int* const FR_idx, const int* const FX_idx,
							 | 
						||
| 
								 | 
							
																						const real_t* const delta_lb, const real_t* const delta_ub,
							 | 
						||
| 
								 | 
							
																						const real_t* const delta_xFR,
							 | 
						||
| 
								 | 
							
																						const real_t* const delta_yFX,
							 | 
						||
| 
								 | 
							
																						int& BC_idx, SubjectToStatus& BC_status
							 | 
						||
| 
								 | 
							
																						)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int i, ii;
							 | 
						||
| 
								 | 
							
									int nFR = getNFR( );
							 | 
						||
| 
								 | 
							
									int nFX = getNFX( );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									real_t tau_tmp;
							 | 
						||
| 
								 | 
							
									real_t tau_new = 1.0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									BC_idx = 0;
							 | 
						||
| 
								 | 
							
									BC_status = ST_UNDEFINED;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* I) DETERMINE MAXIMUM DUAL STEPLENGTH, i.e. ensure that
							 | 
						||
| 
								 | 
							
									 *    active dual bounds remain valid (ignoring implicitly fixed variables): */
							 | 
						||
| 
								 | 
							
									for( i=0; i<nFX; ++i )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										ii = FX_idx[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( bounds.getType( ii ) != ST_EQUALITY )
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											if ( bounds.getStatus( ii ) == ST_LOWER )
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												/* 1) Active lower bounds. */
							 | 
						||
| 
								 | 
							
												if ( ( delta_yFX[i] < -ZERO ) && ( y[ii] >= 0.0 ) )
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													tau_tmp = y[ii] / ( -delta_yFX[i] );
							 | 
						||
| 
								 | 
							
													if ( tau_tmp < tau_new )
							 | 
						||
| 
								 | 
							
													{
							 | 
						||
| 
								 | 
							
														if ( tau_tmp >= 0.0 )
							 | 
						||
| 
								 | 
							
														{
							 | 
						||
| 
								 | 
							
															tau_new = tau_tmp;
							 | 
						||
| 
								 | 
							
															BC_idx = ii;
							 | 
						||
| 
								 | 
							
															BC_status = ST_INACTIVE;
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											else
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												/* 2) Active upper bounds. */
							 | 
						||
| 
								 | 
							
												if ( ( delta_yFX[i] > ZERO ) && ( y[ii] <= 0.0 ) )
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													tau_tmp = y[ii] / ( -delta_yFX[i] );
							 | 
						||
| 
								 | 
							
													if ( tau_tmp < tau_new )
							 | 
						||
| 
								 | 
							
													{
							 | 
						||
| 
								 | 
							
														if ( tau_tmp >= 0.0 )
							 | 
						||
| 
								 | 
							
														{
							 | 
						||
| 
								 | 
							
															tau_new = tau_tmp;
							 | 
						||
| 
								 | 
							
															BC_idx = ii;
							 | 
						||
| 
								 | 
							
															BC_status = ST_INACTIVE;
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* II) DETERMINE MAXIMUM PRIMAL STEPLENGTH, i.e. ensure that
							 | 
						||
| 
								 | 
							
									 *     inactive bounds remain valid (ignoring unbounded variables). */
							 | 
						||
| 
								 | 
							
									/* 1) Inactive lower bounds. */
							 | 
						||
| 
								 | 
							
									if ( bounds.isNoLower( ) == BT_FALSE )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										for( i=0; i<nFR; ++i )
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											ii = FR_idx[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if ( bounds.getType( ii ) != ST_UNBOUNDED )
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												if ( delta_lb[ii] > delta_xFR[i] )
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													if ( x[ii] > lb[ii] )
							 | 
						||
| 
								 | 
							
														tau_tmp = ( x[ii] - lb[ii] ) / ( delta_lb[ii] - delta_xFR[i] );
							 | 
						||
| 
								 | 
							
													else
							 | 
						||
| 
								 | 
							
														tau_tmp = 0.0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													if ( tau_tmp < tau_new )
							 | 
						||
| 
								 | 
							
													{
							 | 
						||
| 
								 | 
							
														if ( tau_tmp >= 0.0 )
							 | 
						||
| 
								 | 
							
														{
							 | 
						||
| 
								 | 
							
															tau_new = tau_tmp;
							 | 
						||
| 
								 | 
							
															BC_idx = ii;
							 | 
						||
| 
								 | 
							
															BC_status = ST_LOWER;
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* 2) Inactive upper bounds. */
							 | 
						||
| 
								 | 
							
									if ( bounds.isNoUpper( ) == BT_FALSE )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										for( i=0; i<nFR; ++i )
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											ii = FR_idx[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if ( bounds.getType( ii ) != ST_UNBOUNDED )
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												if ( delta_ub[ii] < delta_xFR[i] )
							 | 
						||
| 
								 | 
							
												{
							 | 
						||
| 
								 | 
							
													if ( x[ii] < ub[ii] )
							 | 
						||
| 
								 | 
							
														tau_tmp = ( x[ii] - ub[ii] ) / ( delta_ub[ii] - delta_xFR[i] );
							 | 
						||
| 
								 | 
							
													else
							 | 
						||
| 
								 | 
							
														tau_tmp = 0.0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													if ( tau_tmp < tau_new )
							 | 
						||
| 
								 | 
							
													{
							 | 
						||
| 
								 | 
							
														if ( tau_tmp >= 0.0 )
							 | 
						||
| 
								 | 
							
														{
							 | 
						||
| 
								 | 
							
															tau_new = tau_tmp;
							 | 
						||
| 
								 | 
							
															BC_idx = ii;
							 | 
						||
| 
								 | 
							
															BC_status = ST_UPPER;
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* III) SET MAXIMUM HOMOTOPY STEPLENGTH */
							 | 
						||
| 
								 | 
							
									tau = tau_new;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if ( printlevel ==  PL_HIGH )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										#ifdef PC_DEBUG
							 | 
						||
| 
								 | 
							
										char messageString[80];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( BC_status == ST_UNDEFINED )
							 | 
						||
| 
								 | 
							
											sprintf( messageString,"Stepsize is %.6e!",tau );
							 | 
						||
| 
								 | 
							
										else
							 | 
						||
| 
								 | 
							
											sprintf( messageString,"Stepsize is %.6e! (BC_idx = %d, BC_status = %d)",tau,BC_idx,BC_status );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										getGlobalMessageHandler( )->throwInfo( RET_STEPSIZE_NONPOSITIVE,messageString,__FUNCTION__,__FILE__,__LINE__,VS_VISIBLE );
							 | 
						||
| 
								 | 
							
										#endif
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return SUCCESSFUL_RETURN;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 *	h o t s t a r t _ p e r f o r m S t e p
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								returnValue QProblemB::hotstart_performStep(	const int* const FR_idx, const int* const FX_idx,
							 | 
						||
| 
								 | 
							
																				const real_t* const delta_g, const real_t* const  delta_lb, const real_t* const delta_ub,
							 | 
						||
| 
								 | 
							
																				const real_t* const delta_xFX, const real_t* const delta_xFR,
							 | 
						||
| 
								 | 
							
																				const real_t* const delta_yFX,
							 | 
						||
| 
								 | 
							
																				int BC_idx, SubjectToStatus BC_status
							 | 
						||
| 
								 | 
							
																				)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int i, ii;
							 | 
						||
| 
								 | 
							
									int nV  = getNV( );
							 | 
						||
| 
								 | 
							
									int nFR = getNFR( );
							 | 
						||
| 
								 | 
							
									int nFX = getNFX( );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* I) CHECK BOUNDS' CONSISTENCY */
							 | 
						||
| 
								 | 
							
									if ( areBoundsConsistent( delta_lb,delta_ub ) == BT_FALSE )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										infeasible = BT_TRUE;
							 | 
						||
| 
								 | 
							
										tau = 0.0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return THROWERROR( RET_QP_INFEASIBLE );
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* II) GO TO ACTIVE SET CHANGE */
							 | 
						||
| 
								 | 
							
									if ( tau > ZERO )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										/* 1) Perform step in primal und dual space. */
							 | 
						||
| 
								 | 
							
										for( i=0; i<nFR; ++i )
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											ii = FR_idx[i];
							 | 
						||
| 
								 | 
							
											x[ii] += tau*delta_xFR[i];
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										for( i=0; i<nFX; ++i )
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											ii = FX_idx[i];
							 | 
						||
| 
								 | 
							
											x[ii] += tau*delta_xFX[i];
							 | 
						||
| 
								 | 
							
											y[ii] += tau*delta_yFX[i];
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/* 2) Shift QP data. */
							 | 
						||
| 
								 | 
							
										for( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											g[i]  += tau*delta_g[i];
							 | 
						||
| 
								 | 
							
											lb[i] += tau*delta_lb[i];
							 | 
						||
| 
								 | 
							
											ub[i] += tau*delta_ub[i];
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										/* print a stepsize warning if stepsize is zero */
							 | 
						||
| 
								 | 
							
										#ifdef PC_DEBUG
							 | 
						||
| 
								 | 
							
										char messageString[80];
							 | 
						||
| 
								 | 
							
										sprintf( messageString,"Stepsize is %.6e",tau );
							 | 
						||
| 
								 | 
							
										getGlobalMessageHandler( )->throwWarning( RET_STEPSIZE,messageString,__FUNCTION__,__FILE__,__LINE__,VS_VISIBLE );
							 | 
						||
| 
								 | 
							
										#endif
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* setup output preferences */
							 | 
						||
| 
								 | 
							
									#ifdef PC_DEBUG
							 | 
						||
| 
								 | 
							
									char messageString[80];
							 | 
						||
| 
								 | 
							
								  	VisibilityStatus visibilityStatus;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  	if ( printlevel == PL_HIGH )
							 | 
						||
| 
								 | 
							
										visibilityStatus = VS_VISIBLE;
							 | 
						||
| 
								 | 
							
									else
							 | 
						||
| 
								 | 
							
										visibilityStatus = VS_HIDDEN;
							 | 
						||
| 
								 | 
							
									#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* III) UPDATE ACTIVE SET */
							 | 
						||
| 
								 | 
							
									switch ( BC_status )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										/* Optimal solution found as no working set change detected. */
							 | 
						||
| 
								 | 
							
										case ST_UNDEFINED:
							 | 
						||
| 
								 | 
							
											return RET_OPTIMAL_SOLUTION_FOUND;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/* Remove one variable from active set. */
							 | 
						||
| 
								 | 
							
										case ST_INACTIVE:
							 | 
						||
| 
								 | 
							
											#ifdef PC_DEBUG
							 | 
						||
| 
								 | 
							
											sprintf( messageString,"bound no. %d.", BC_idx );
							 | 
						||
| 
								 | 
							
											getGlobalMessageHandler( )->throwInfo( RET_REMOVE_FROM_ACTIVESET,messageString,__FUNCTION__,__FILE__,__LINE__,visibilityStatus );
							 | 
						||
| 
								 | 
							
											#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if ( removeBound( BC_idx,BT_TRUE ) != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
												return THROWERROR( RET_REMOVE_FROM_ACTIVESET_FAILED );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											y[BC_idx] = 0.0;
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/* Add one variable to active set. */
							 | 
						||
| 
								 | 
							
										default:
							 | 
						||
| 
								 | 
							
											#ifdef PC_DEBUG
							 | 
						||
| 
								 | 
							
											if ( BC_status == ST_LOWER )
							 | 
						||
| 
								 | 
							
												sprintf( messageString,"lower bound no. %d.", BC_idx );
							 | 
						||
| 
								 | 
							
											else
							 | 
						||
| 
								 | 
							
												sprintf( messageString,"upper bound no. %d.", BC_idx );
							 | 
						||
| 
								 | 
							
												getGlobalMessageHandler( )->throwInfo( RET_ADD_TO_ACTIVESET,messageString,__FUNCTION__,__FILE__,__LINE__,visibilityStatus );
							 | 
						||
| 
								 | 
							
											#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if ( addBound( BC_idx,BC_status,BT_TRUE ) != SUCCESSFUL_RETURN )
							 | 
						||
| 
								 | 
							
												return THROWERROR( RET_ADD_TO_ACTIVESET_FAILED );
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return SUCCESSFUL_RETURN;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef PC_DEBUG  /* Define print functions only for debugging! */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 *	p r i n t I t e r a t i o n
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								returnValue QProblemB::printIteration( 	int iteration,
							 | 
						||
| 
								 | 
							
																		int BC_idx,	SubjectToStatus BC_status
							 | 
						||
| 
								 | 
							
										  								)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									char myPrintfString[160];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* consistency check */
							 | 
						||
| 
								 | 
							
									if ( iteration < 0 )
							 | 
						||
| 
								 | 
							
										return THROWERROR( RET_INVALID_ARGUMENTS );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* nothing to do */
							 | 
						||
| 
								 | 
							
									if ( printlevel != PL_MEDIUM )
							 | 
						||
| 
								 | 
							
										return SUCCESSFUL_RETURN;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* 1) Print header at first iteration. */
							 | 
						||
| 
								 | 
							
								 	if ( iteration == 0 )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										sprintf( myPrintfString,"\n##############  qpOASES  --  QP NO.%4.1d  ###############\n", count );
							 | 
						||
| 
								 | 
							
										myPrintf( myPrintfString );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										sprintf( myPrintfString,"   Iter   |   StepLength    |       Info      |   nFX   \n" );
							 | 
						||
| 
								 | 
							
										myPrintf( myPrintfString );
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* 2) Print iteration line. */
							 | 
						||
| 
								 | 
							
									if ( BC_status == ST_UNDEFINED )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										sprintf( myPrintfString,"   %4.1d   |   %1.5e   |    QP SOLVED    |  %4.1d   \n", iteration,tau,getNFX( ) );
							 | 
						||
| 
								 | 
							
										myPrintf( myPrintfString );
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										char info[8];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( BC_status == ST_INACTIVE )
							 | 
						||
| 
								 | 
							
											sprintf( info,"REM BND" );
							 | 
						||
| 
								 | 
							
										else
							 | 
						||
| 
								 | 
							
											sprintf( info,"ADD BND" );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										sprintf( myPrintfString,"   %4.1d   |   %1.5e   |   %s%4.1d   |  %4.1d   \n", iteration,tau,info,BC_idx,getNFX( ) );
							 | 
						||
| 
								 | 
							
										myPrintf( myPrintfString );
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return SUCCESSFUL_RETURN;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif  /* PC_DEBUG */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 *	c h e c k K K T c o n d i t i o n s
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								returnValue QProblemB::checkKKTconditions( )
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									#ifdef __PERFORM_KKT_TEST__
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									int i, j;
							 | 
						||
| 
								 | 
							
									int nV = getNV( );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									real_t tmp;
							 | 
						||
| 
								 | 
							
									real_t maxKKTviolation = 0.0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* 1) Check for Hx + g - y*A' = 0  (here: A = Id). */
							 | 
						||
| 
								 | 
							
									for( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										tmp = g[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										for( j=0; j<nV; ++j )
							 | 
						||
| 
								 | 
							
											tmp += H[i*nV + j] * x[j];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										tmp -= y[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( getAbs( tmp ) > maxKKTviolation )
							 | 
						||
| 
								 | 
							
											maxKKTviolation = getAbs( tmp );
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* 2) Check for lb <= x <= ub. */
							 | 
						||
| 
								 | 
							
									for( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										if ( lb[i] - x[i] > maxKKTviolation )
							 | 
						||
| 
								 | 
							
											maxKKTviolation = lb[i] - x[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if ( x[i] - ub[i] > maxKKTviolation )
							 | 
						||
| 
								 | 
							
											maxKKTviolation = x[i] - ub[i];
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* 3) Check for correct sign of y and for complementary slackness. */
							 | 
						||
| 
								 | 
							
									for( i=0; i<nV; ++i )
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										switch ( bounds.getStatus( i ) )
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											case ST_LOWER:
							 | 
						||
| 
								 | 
							
												if ( -y[i] > maxKKTviolation )
							 | 
						||
| 
								 | 
							
													maxKKTviolation = -y[i];
							 | 
						||
| 
								 | 
							
												if ( getAbs( ( x[i] - lb[i] ) * y[i] ) > maxKKTviolation )
							 | 
						||
| 
								 | 
							
													maxKKTviolation = getAbs( ( x[i] - lb[i] ) * y[i] );
							 | 
						||
| 
								 | 
							
												break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											case ST_UPPER:
							 | 
						||
| 
								 | 
							
												if ( y[i] > maxKKTviolation )
							 | 
						||
| 
								 | 
							
													maxKKTviolation = y[i];
							 | 
						||
| 
								 | 
							
												if ( getAbs( ( ub[i] - x[i] ) * y[i] ) > maxKKTviolation )
							 | 
						||
| 
								 | 
							
													maxKKTviolation = getAbs( ( ub[i] - x[i] ) * y[i] );
							 | 
						||
| 
								 | 
							
												break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											default: /* inactive */
							 | 
						||
| 
								 | 
							
											if ( getAbs( y[i] ) > maxKKTviolation )
							 | 
						||
| 
								 | 
							
													maxKKTviolation = getAbs( y[i] );
							 | 
						||
| 
								 | 
							
												break;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if ( maxKKTviolation > CRITICALACCURACY )
							 | 
						||
| 
								 | 
							
										return RET_NO_SOLUTION;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if ( maxKKTviolation > DESIREDACCURACY )
							 | 
						||
| 
								 | 
							
										return RET_INACCURATE_SOLUTION;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									#endif /* __PERFORM_KKT_TEST__ */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return SUCCESSFUL_RETURN;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 *	end of file
							 | 
						||
| 
								 | 
							
								 */
							 |