//////////////////////////////////////////////////////////////////////
//
//	Constraints.cpp: implementation of the CostFunction class.
//
//	Written By: Matthias Wacker
//
//////////////////////////////////////////////////////////////////////

#include "optimization/Constraints.h"

using namespace opt;
Constraints::Constraints():		m_numOfParameters(0),
								m_numOfConstraints(0),
								m_hasAnalyticGradient(false),
								m_hasAnalyticHessian(false)
{

}

/*
	constructor
*/
Constraints::Constraints(unsigned int numOfParameters, unsigned int numOfConstraints) : 
								m_numOfParameters(numOfParameters),
								m_numOfConstraints(numOfConstraints),
								m_hasAnalyticGradient(false),
								m_hasAnalyticHessian(false)
{
	m_weights = matrix_type(numOfConstraints,1);
	for(int i=0; i < static_cast<int>(numOfConstraints); ++i)
	{
		m_weights[i][0] = 1;
	}

}

/*
	copy constructor							
*/
Constraints::Constraints(const Constraints &con)
{
	m_numOfParameters = con.m_numOfParameters;
	m_numOfConstraints = con.m_numOfConstraints;
	m_hasAnalyticGradient = con.m_hasAnalyticGradient;
	m_hasAnalyticHessian = con.m_hasAnalyticHessian;
	m_weights = con.m_weights;
}


/*
	destructor
*/
Constraints::~Constraints()
{
}



/*
	return the AnalyticGradient
*/
const matrix_type Constraints::getAnalyticGradient(const matrix_type &x)
{
	matrix_type tmp(m_numOfParameters, m_numOfConstraints);
	
	return tmp;
}

/*
	return the AnalyticGradient
*/
const matrix_type Constraints::getAnalyticHessian(const matrix_type &x)
{
	matrix_type tmp(m_numOfParameters, m_numOfConstraints * m_numOfParameters);
	
	return tmp;
}

bool Constraints::setWeightVector(const matrix_type weights)
{
	/*
		dimensions have to match:
	*/
	if(static_cast<unsigned int >(weights.rows()) != m_numOfConstraints || weights.cols() != 1)
	{
		return false;
	}

	/*
		weights have to be nonnegative
	*/
	for(unsigned int i= 0; i < m_numOfConstraints; i++)
	{
		if(weights[i][0] < 0)
		{
			return false;
		}
	}
	
	/*
		everything is fine so far, copy weights and return true
	*/
	m_weights = weights;

	return true;

}

matrix_type Constraints::evaluateSub(double lambda)
{
	return evaluate(m_x_0 + m_h_0 * lambda);
}


bool Constraints::setX0(const matrix_type &x0)
{
	if(x0.rows() == static_cast<int>(m_numOfParameters) && x0.cols() == 1)
	{
		m_x_0 = x0;
		return true;
	}
	else
		return false;
}

bool Constraints::setH0(const matrix_type &H0)
{
	if(H0.rows() == static_cast<int>(m_numOfParameters) && H0.cols() == 1)
	{
		m_h_0 = H0;
		return true;
	}
	else
		return false;
}