/*
 *	This file is part of qpOASES.
 *
 *	qpOASES -- An Implementation of the Online Active Set Strategy.
 *	Copyright (C) 2007-2015 by Hans Joachim Ferreau, Andreas Potschka,
 *	Christian Kirches 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 include/qpOASES/Constraints.hpp
 *	\author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches
 *	\version 3.2
 *	\date 2007-2015
 *
 *	Declaration of the Constraints class designed to manage working sets of
 *	constraints within a QProblem.
 */


#ifndef QPOASES_CONSTRAINTS_HPP
#define QPOASES_CONSTRAINTS_HPP


#include <qpOASES/SubjectTo.hpp>


BEGIN_NAMESPACE_QPOASES


/** 
 *	\brief Manages working sets of constraints.
 *
 *	This class manages working sets of constraints by storing
 *	index sets and other status information.
 *
 *	\author Hans Joachim Ferreau
 *	\version 3.2
 *	\date 2007-2015
 */
class Constraints : public SubjectTo
{
	/*
	 *	PUBLIC MEMBER FUNCTIONS
	 */
	public:
		/** Default constructor. */
		Constraints( );

		/** Constructor which takes the number of constraints. */
		Constraints(	int_t _n						/**< Number of constraints. */
						);

		/** Copy constructor (deep copy). */
		Constraints(	const Constraints& rhs			/**< Rhs object. */
						);

		/** Destructor. */
		virtual ~Constraints( );

		/** Assignment operator (deep copy). */
		Constraints& operator=(	const Constraints& rhs	/**< Rhs object. */
								);


		/** Initialises object with given number of constraints.
		 *	\return SUCCESSFUL_RETURN \n
		 			RET_INVALID_ARGUMENTS */
		returnValue init(	int_t _n = 0				/**< Number of constraints. */
							);


		/** Initially adds number of a new (i.e. not yet in the list) constraint to
		 *  a given index set.
		 *	\return SUCCESSFUL_RETURN \n
		 			RET_SETUP_CONSTRAINT_FAILED \n
					RET_INDEX_OUT_OF_BOUNDS \n
					RET_INVALID_ARGUMENTS */
		returnValue setupConstraint(	int_t number,			/**< Number of new constraint. */
										SubjectToStatus _status	/**< Status of new constraint. */
										);

		/** Initially adds all enabled numbers of new (i.e. not yet in the list) constraints to
		 *  to the index set of inactive constraints; the order depends on the SujectToType
		 *  of each index. Only disabled constraints are added to index set of disabled constraints!
		 *	\return SUCCESSFUL_RETURN \n
		 			RET_SETUP_CONSTRAINT_FAILED */
		returnValue setupAllInactive( );

		/** Initially adds all enabled numbers of new (i.e. not yet in the list) constraints to
		 *  to the index set of active constraints (on their lower bounds); the order depends on the SujectToType
		 *  of each index. Only disabled constraints are added to index set of disabled constraints!
		 *	\return SUCCESSFUL_RETURN \n
		 			RET_SETUP_CONSTRAINT_FAILED */
		returnValue setupAllLower( );

		/** Initially adds all enabled numbers of new (i.e. not yet in the list) constraints to
		 *  to the index set of active constraints (on their upper bounds); the order depends on the SujectToType
		 *  of each index. Only disabled constraints are added to index set of disabled constraints!
		 *	\return SUCCESSFUL_RETURN \n
		 			RET_SETUP_CONSTRAINT_FAILED */
		returnValue setupAllUpper( );


		/** Moves index of a constraint from index list of active to that of inactive constraints.
		 *	\return SUCCESSFUL_RETURN \n
		 			RET_MOVING_CONSTRAINT_FAILED */
		returnValue moveActiveToInactive(	int_t number			/**< Number of constraint to become inactive. */
											);

		/** Moves index of a constraint from index list of inactive to that of active constraints.
		 *	\return SUCCESSFUL_RETURN \n
		 			RET_MOVING_CONSTRAINT_FAILED */
		returnValue moveInactiveToActive(	int_t number,			/**< Number of constraint to become active. */
											SubjectToStatus _status	/**< Status of constraint to become active. */
											);

		/** Flip fixed constraint.
		 *	\return SUCCESSFUL_RETURN \n
		 			RET_MOVING_CONSTRAINT_FAILED \n
					RET_INDEX_OUT_OF_BOUNDS */
		returnValue flipFixed( int_t number );


		/** Returns the number of constraints.
		 *	\return Number of constraints. */
		inline int_t getNC( ) const;

		/** Returns the number of implicit equality constraints.
		 *	\return Number of implicit equality constraints. */
		inline int_t getNEC( ) const;

		/** Returns the number of "real" inequality constraints.
		 *	\return Number of "real" inequality constraints. */
		inline int_t getNIC( ) const;

		/** Returns the number of unbounded constraints (i.e. without any bounds).
		 *	\return Number of unbounded constraints (i.e. without any bounds). */
		inline int_t getNUC( ) const;

		/** Returns the number of active constraints.
		 *	\return Number of active constraints. */
		inline int_t getNAC( ) const;

		/** Returns the number of inactive constraints.
		 *	\return Number of inactive constraints. */
		inline int_t getNIAC( ) const;


		/** Returns a pointer to active constraints index list.
		 *	\return Pointer to active constraints index list. */
		inline Indexlist* getActive( );

		/** Returns a pointer to inactive constraints index list.
		 *	\return Pointer to inactive constraints index list. */
		inline Indexlist* getInactive( );


		/** Shifts forward type and status of all constraints by a given
		 *  offset. This offset has to lie within the range [0,n/2] and has to
		 *  be an integer divisor of the total number of constraints n.
		 *  Type and status of the first \<offset\> constraints  is thrown away,
		 *  type and status of the last \<offset\> constraints is doubled,
		 *  e.g. for offset = 2: \n
		 *  shift( {c1,c2,c3,c4,c5,c6} ) = {c3,c4,c5,c6,c5,c6}
		 *	\return SUCCESSFUL_RETURN \n
		 			RET_INDEX_OUT_OF_BOUNDS \n
		 			RET_INVALID_ARGUMENTS \n
		 			RET_SHIFTING_FAILED */
		virtual returnValue shift(	int_t offset	/**< Shift offset within the range [0,n/2] and integer divisor of n. */
									);

		/** Rotates forward type and status of all constraints by a given
		 *  offset. This offset has to lie within the range [0,n].
		 *  Example for offset = 2: \n
		 *  rotate( {c1,c2,c3,c4,c5,c6} ) = {c3,c4,c5,c6,c1,c2}
		 *	\return SUCCESSFUL_RETURN \n
		 			RET_INDEX_OUT_OF_BOUNDS \n
		 			RET_ROTATING_FAILED */
		virtual returnValue rotate(	int_t offset	/**< Rotation offset within the range [0,n]. */
									);


		/** Prints information on constraints object
		 *  (in particular, lists of inactive and active constraints.
		 * \return SUCCESSFUL_RETURN \n
				   RET_INDEXLIST_CORRUPTED */
		returnValue print( );


	/*
	 *	PROTECTED MEMBER FUNCTIONS
	 */
	protected:
		/** Frees all allocated memory.
		 *  \return SUCCESSFUL_RETURN */
		returnValue clear( );
		
		/** Copies all members from given rhs object.
		 *  \return SUCCESSFUL_RETURN */
		returnValue copy(	const Constraints& rhs	/**< Rhs object. */
							);


		/** Initially adds all numbers of new (i.e. not yet in the list) bounds to
		 *  to the index set corresponding to the desired status;
		 *  the order depends on the SujectToType of each index.
		 *	\return SUCCESSFUL_RETURN \n
		 			RET_SETUP_CONSTRAINT_FAILED */
		returnValue setupAll(	SubjectToStatus _status	/**< Desired initial status for all bounds. */
								);


	/*
	 *	PROTECTED MEMBER VARIABLES
	 */
	protected:
		Indexlist active;		/**< Index list of active constraints. */
		Indexlist inactive;		/**< Index list of inactive constraints. */
};

END_NAMESPACE_QPOASES

#include <qpOASES/Constraints.ipp>

#endif	/* QPOASES_CONSTRAINTS_HPP */


/*
 *	end of file
 */
