Esempio n. 1
0
    bool LpSolve::solve() {
        set_add_rowmode(lp, TRUE);
        for (size_t c = 0; c < moduleIndexMap.size(); ++c) {
            colno[c] = c + 1;
            set_binary(lp, c + 1, TRUE);
        }
        for (auto &equation : equations) {
            memset(row, 0, moduleIndexMap.size() * sizeof(*row));
            for (auto const &module : equation->getModules()) {
                row[moduleIndexMap.at(module->toString())] = 1;
            }
            add_constraintex(lp, moduleIndexMap.size(), row, colno, equation->getIsEqualityConstraint() ? EQ : LE, 1);
        }
        set_add_rowmode(lp, FALSE);
        memset(row, 0, moduleIndexMap.size() * sizeof(*row));
        set_obj_fnex(lp, moduleIndexMap.size(), row, colno);

        if (::solve(lp) != OPTIMAL) {
            return false;
        }
        get_variables(lp, row);
        for (size_t j = 0; j < moduleIndexMap.size(); j++)
            printf("%s: %f\n", get_col_name(lp, j + 1), row[j]);
        return true;
    }
// TODO there's a seriouxx need for refactoring here !
Solution LpsolveAdaptator::getAdmissibleSolution(LinearProblem * lp) {
	lprec *lprec;
	int nbCol = lp->getVariables().size();
	lprec = make_lp(0, nbCol);

	if (lprec == NULL) {
		// TODO raise an exception
	}

	/* set variables name to ease debugging */
	for (int i = 0; i < (int)lp->getVariables().size(); ++i) {
		Variable * var = (lp->getVariables())[i];
		set_col_name(lprec, i+1, var->getNameToChar());
		if (var->isBinary()) {
			set_binary(lprec, i+1, TRUE);
		}
	}

	/* to build the model faster when adding constraints one at a time */
	set_add_rowmode(lprec, TRUE);

	for (int i = 0; i < (int)(lp->getConstraints().size()); ++i) {
		// FIXME there's a bug here but I can't find it
		Constraint c = (Constraint)(lp->getConstraints()[i]);
		TermList terms = c.getTerms();
		int col[terms.size()];
		REAL row[terms.size()];
		int j = 0;
		for (TermList::const_iterator it = terms.begin(); it != terms.end();
				++it, ++j) {
			// TODO check if this is fixed
			col[j] = ((Term)*it).getVariable().getPosition();
			row[j] = ((Term)*it).getCoeff();
		}
		// WARNING the Consraint uses the same operator values than in lp_lib.h
		if (!add_constraintex(lprec, j, row, col, c.getOperator(), c.getBound())) {
			// TODO raise an exception
		}
	}

	/* the objective function requires rowmode to be off */
	set_add_rowmode(lprec, FALSE);

	return getSolution(lprec);
}
Esempio n. 3
0
bool CLPLpsolve::solve(
					  std::tstring logfile /*= ""*/,
					  std::tstring problemFile /*= ""*/,
					  std::tstring solutionFile /*= ""*/,
					  ESimplexSolverType initialSolverType /*= NoSimplexT*/,
					  ESimplexSolverType reSolverType /*= NoSimplexT*/,
					  bool doLpPresolveInInitialSolve /*= true*/,
					  bool doLpPresolveInReSolve /*= true*/,
					  int scaling /*= 1*/,
					  double timeLimit /*= -1*/,
					  int numberOfThread /* = 0*/,
					  int nCPX_PARAM_BARCOLNZ /*=-1*/,
					  int nCPX_PARAM_BARITLIM /*=-1*/,
					  int nCPX_PARAM_BARALG /*=1*/,
					  int nCPX_PARAM_BARSTATALG /*=1*/,
					  int nCPX_PARAM_DEPIND /*=1*/,
					  int nCPX_PARAM_BARORDER /*=1*/,
					  bool writeStatistics /*= false */
					  )
{
	if(problemFile != "")
	{
		writeProblem(problemFile.c_str(), NULL);
	}

	set_add_rowmode(m_env, FALSE);
	//m_status = m_solver->solveProblem(m_env);
	
#if 1
	switch(reSolverType) {
	case PrimalSimplexT:
		set_simplextype(m_env, SIMPLEX_PRIMAL_PRIMAL);
		break;

	case DualSimplexT:
		set_simplextype(m_env, SIMPLEX_DUAL_DUAL);
		break;

	default: //SIMPLEX_DUAL_PRIMAL
		set_simplextype(m_env, SIMPLEX_DEFAULT);
		break;
	}
#endif

	m_status = ::solve(m_env);
	//m_status = solve_LP(m_env, NULL);

	m_status = getStatus();
	


	if (solutionFile != "") {
		writeSolution(solutionFile.c_str());
	}

	return true;
}
/*
	Solve the LP subproblem by calling lp_solve API 
*/
int LLW_solve_lp(double **gradient, const struct TrainingCache *cache, const struct Model *model)
{
	long i,k,l,ind_pattern,y_i;
	const long Q = model->Q;
	const double Qd = (double)Q;
	const long chunk_size = cache->chunk_size;
	const double *C = model->C;
	
	const int nRows = Q-1; 
	const int nCols = chunk_size * Q;

	double *obj = (double*)malloc(sizeof(double) * (1+nCols));
	double *row = (double*)malloc(sizeof(double) * (1+nCols));
	double *rhs = (double*)malloc(sizeof(double) * Q);
	long **lp_sol_table = matrix_l(nCols, 2);
	long **lp_sol_table_inv = matrix_l(chunk_size, Q);
	double *sol = (double*)malloc(sizeof(double) * (1+nRows+nCols));
	double epsel;
		
	// Make LP
	lprec *lp = make_lp(0, nCols);
	set_add_rowmode(lp, TRUE);

	// Make objective function
	int col = 1;
	for(i=1; i<=chunk_size; i++)
	  {
	  ind_pattern = cache->table_chunk[i];
	  for(k=1; k<=Q; k++)
	      {
	      	obj[col] = gradient[ind_pattern][k];
		lp_sol_table[col][1] = i;	// keep a table of correspondance between
		lp_sol_table[col][2] = k;	// LPSOLVE vector of variables and lp_sol matrix
		lp_sol_table_inv[i][k] = col++; // lp_sol[i][k] = the 'lp_solve_table_inv[i][k]'-th variable for LPSOLVE
	      }
	  }
	set_obj_fn(lp, obj);


/*	// Make RHS of constraints
	// -- complete computation --
	for(k=1; k<Q; k++)
	  {
	  rhs[k] = 0.0;
	  for(i=1; i<=nb_data; i++)
	    if(cache->in_chunk[i] == 0)
	      {
	      for(l=1; l<=Q; l++)
		 rhs[k] += model->alpha[i][l];
	      rhs[k] -= Qd * model->alpha[i][k];
		
	      }
	  }
*/	  

	// Make RHS of constraints
	// -- updates to cache->rhs are made in compute_new_alpha()
	//    to keep track of rhs
	//    we only need to remove the contribution of the examples in the chunk
	for(k=1; k<Q; k++)
	  {
	  rhs[k] = cache->lp_rhs[k];
	  for(i=1; i<=chunk_size; i++)
	      {
	      ind_pattern = cache->table_chunk[i];
	      for(l=1; l<=Q; l++)
		 rhs[k] -= model->alpha[ind_pattern][l];
	      rhs[k] += Qd * model->alpha[ind_pattern][k];		
	      }
	  }
	
	
	// Make constraints
	for(k=1; k<Q; k++)
	  {
	  for(col = 1;col <=nCols; col++)
	     row[col] = 0.0;

	  for(i=1; i<=chunk_size; i++)
	    {
	    ind_pattern = cache->table_chunk[i];
	    y_i = model->y[ind_pattern];

            for(l=1; l<=Q; l++)
              if(l != y_i)
        	{
        	row[lp_sol_table_inv[i][l]] = -1.0;
        	if(l == k)
        	     row[lp_sol_table_inv[i][l]] += Qd;
		}
	    }

	  add_constraint(lp, row, EQ, rhs[k]);
	  }

	// Upper bound constraints: alpha <= Cy_i
	for(col=1;col<=nCols;col++)
		set_upbo(lp, col, C[model->y[cache->table_chunk[lp_sol_table[col][1]]]]);

	/*
	for(i=1; i<=chunk_size; i++) {
	  for(k=1; k<=Q; k++)
	    if(k != model->y[cache->table_chunk[i]]) {
	    	col = (int)lp_sol_table_inv[i][k];
		set_upbo(lp, col, C);
	    }
	}
	*/
	
	// End of LP making
	set_add_rowmode(lp, FALSE);	
	//print_lp(lp);
	
	// Solve LP
	int jump = false;
	set_outputfile(lp,"");

	if(solve(lp)) {
		printf("Problem with the LP... \n");
		jump = true;
	}
	else {
		// Recover solution in the matrix lp_sol
		get_primal_solution(lp, sol);	// sol: template for lp_solve solution format
						// 	sol=[obj, constraints, variables] 

		epsel = get_epsel(lp);	// tolerance in lp_solve
		
		// Put solution into lp_sol
		for(col=1; col<= nCols; col++) {

			// Check feasibility of the col-th variable
			if((sol[nRows+col] < -epsel) || (sol[nRows+col] > C[model->y[cache->table_chunk[lp_sol_table[col][1]]]] + epsel)) {
				jump = true;
				break;
			}
			// Round off tolerance
			if(fabs(sol[nRows+col]) < epsel) 
				sol[nRows+col] = 0.0;
				
			else if(fabs(sol[nRows+col] - C[model->y[cache->table_chunk[lp_sol_table[col][1]]]]) < epsel)
				sol[nRows+col] = C[model->y[cache->table_chunk[lp_sol_table[col][1]]]];
				
			// Set the value in lp_sol matrix
			cache->lp_sol[lp_sol_table[col][1]][lp_sol_table[col][2]] = sol[nRows+col];
		}
		
	}

	delete_lp(lp);

	free(obj);
	free(row);
	free(rhs);
	free(lp_sol_table[1]);free(lp_sol_table);
	free(lp_sol_table_inv[1]);free(lp_sol_table_inv);
	free(sol);

	return jump;	
}
Esempio n. 5
0
int StateConstraints::fireVectorSize(const PetriNet& net,
									 const MarkVal* m0,
									 const VarVal*) const{
	assert(nPlaces == net.numberOfPlaces());
	assert(nVars == net.numberOfVariables());

	// Create linary problem
	lprec* lp;
	lp = make_lp(0, net.numberOfTransitions());	// One variable for each entry in the firing vector
	assert(lp);
	if(!lp) return false;

	// Set verbosity
	set_verbose(lp, IMPORTANT);

	// Set transition names (not strictly needed)
	for(size_t i = 0; i < net.numberOfTransitions(); i++)
		set_col_name(lp, i+1, const_cast<char*>(net.transitionNames()[i].c_str()));

	// Start adding rows
	set_add_rowmode(lp, TRUE);

	REAL row[net.numberOfTransitions() + 1];
	for(size_t p = 0; p < nPlaces; p++){
		// Set row zero
		memset(row, 0, sizeof(REAL) * net.numberOfTransitions() + 1);
		for(size_t t = 0; t < net.numberOfTransitions(); t++){
			int d = net.outArc(t, p) - net.inArc(p, t);
			row[1+t] = d;
		}

		if(pcs[p].min == pcs[p].max &&
		   pcs[p].max != CONSTRAINT_INFTY){
			double target = pcs[p].min - m0[p];
			add_constraint(lp, row, EQ,  target);
		}else{
			// There's always a min, even zero is interesting
			double target = pcs[p].min - m0[p];
			add_constraint(lp, row, GE,  target);
			if(pcs[p].max != CONSTRAINT_INFTY){
				double target = pcs[p].max - m0[p];
				add_constraint(lp, row, LE,  target);
			}
		}
	}

	// Finished adding rows
	set_add_rowmode(lp, FALSE);

	// Create objective
	memset(row, 0, sizeof(REAL) * net.numberOfTransitions() + 1);
	for(size_t t = 0; t < net.numberOfTransitions(); t++)
		row[1+t] = 1;	// The sum the components in the firing vector

	// Set objective
	set_obj_fn(lp, row);

	// Minimize the objective
	set_minim(lp);

	// Set variables as integer variables
	for(size_t i = 0; i < net.numberOfTransitions(); i++)
		set_int(lp, 1+i, TRUE);

	// Attempt to solve the problem
	int result = solve(lp);

	// Limit on traps to test
	size_t traplimit = nPlaces * OVER_APPROX_TRAP_FACTOR;
	// Try to add a minimal trap constraint
	while((result == OPTIMAL) && traplimit-- < 0){
		memset(row, 0, sizeof(REAL) * net.numberOfTransitions() + 1);
		// Get the firing vector
		get_variables(lp, row);
		// Compute the resulting marking
		MarkVal rMark[net.numberOfPlaces()];
		for(size_t p = 0; p < nPlaces; p++){
			rMark[p] = m0[p];
			for(size_t t = 0; t < net.numberOfTransitions(); t++)
				rMark[p] += (net.outArc(t, p) - net.inArc(p, t)) * (int)row[t];
		}

		// Find an M-trap
		BitField trap(minimalTrap(net, m0, rMark));

		//Break if there's no trap
		if(trap.none()) break;

		// Compute the new equation
		for(size_t t = 0; t < net.numberOfTransitions(); t++){
			row[1+t] = 0;
			for(size_t p = 0; p < nPlaces; p++)
				if(trap.test(p))
					row[1+t] += net.outArc(t, p) - net.inArc(p, t);
		}

		// Add a new row with target as greater than equal to 1
		set_add_rowmode(lp, TRUE);
		add_constraint(lp, row, GE,  1);
		set_add_rowmode(lp, FALSE);

		// Attempt to solve the again
		result = solve(lp);
	}

	int retval = 0;

	if(result != INFEASIBLE){
		get_variables(lp, row);
		for(size_t t = 0; t < net.numberOfTransitions(); t++)
			retval += (int)row[t];
	}

	// Delete the linear problem
	delete_lp(lp);
	lp = NULL;

	// Return true, if it was infeasible
	return retval;
}
Esempio n. 6
0
//Execute function
int LPSolveClass::Execute()
{
	/*
	std::cout << "---------------------------------\n";
	std::cout << "objective function\n";
	for (unsigned int i = 0; i < coefficients.size(); i++)
		std::cout << coefficients[i] << "\t";
	std::cout << "\nConstant Value = " << obj_const << std::endl;

	std::cout << "---------------------------------\n";
	std::cout << "Equality Constraints\n";	
	for (unsigned int i = 0; i < A_equ.size(); i++){
		//std::cout << "Row index = " << i << "\t\t";
		for (unsigned int j = 0; j < A_equ[i].size(); j++)
			std::cout << A_equ[i][j] << "\t";
		std::cout << "\n";
	}
	std::cout << "b\n";
	for (unsigned int i = 0; i < b_equ.size(); i++)
		std::cout << b_equ[i] << "\t";
	std::cout << "\n";


	std::cout << "---------------------------------\n";
	std::cout << "InEquality Constraints\n";	
	for (unsigned int i = 0; i < A_inequ.size(); i++){
		//std::cout << "Row index = " << i << "\t\t";
		for (unsigned int j = 0; j < A_inequ[i].size(); j++)
			std::cout << A_inequ[i][j] << "\t";
		std::cout << "\n";
	}
	std::cout << "b\n";
	for (unsigned int i = 0; i < b_inequ.size(); i++)
		std::cout << b_inequ[i] << "\t";
	std::cout << "\n";
	*/

	lprec *lp;
	int Ncol = coefficients.size(), *colno = NULL, j, ret = 0;
	REAL *row = NULL;
	
	/* We will build the model row by row
     So we start with creating a model with 0 rows and n columns */

	lp = make_lp(0, Ncol);
	if (lp == NULL)
		ret = 1;/* couldn't construct a new model... */
		
	if (ret == 0){
		//let us name our variables
		std::string s = "x";
		for (int i = 0; i < Ncol; i++){
			std::stringstream out;
			out << i;
			s = s + out.str();
			char *cpy = new char[s.size()+1] ;
			strcpy(cpy, s.c_str());			
			set_col_name(lp, i+1, cpy);
		}

		/* create space large enough for one row */
		colno = (int *) malloc(Ncol * sizeof(*colno));
    	row = (REAL *) malloc(Ncol * sizeof(*row));
		if ((colno == NULL) || (row == NULL))
      		ret = 2;
	}

	set_add_rowmode(lp, TRUE);
	//add the equation constraints
	if (ret == 0){
		/* makes building the model faster if it is done rows by row */
		if (A_equ.size() > 0){
			for (unsigned int i = 0; i < A_equ.size(); i++){//loop over the rows of equality constraints
				for (unsigned int j = 0; j < A_equ[i].size(); j++){//loop over the columns of equality constraints
					colno[j] = j+1;//add the j-th column to lpsolve
					row[j] = A_equ[i][j];
				}
				/* add the row to lpsolve */
				if(!add_constraintex(lp, A_equ[i].size(), row, colno, EQ, b_equ[i]))
					ret = 2;
			}
		}
	}
	
	//add the inequality constraints
	if (ret == 0){
		/* makes building the model faster if it is done rows by row */
		if (A_inequ.size() > 0){
			for (unsigned int i = 0; i < A_inequ.size(); i++){//loop over the rows of inequality constraints
				for (unsigned int j = 0; j < A_inequ[i].size(); j++){//loop over the columns of inequality constraints
					colno[j] = j+1;//add the j-th column to lpsolve
					row[j] = A_inequ[i][j];
				}
				/* add the row to lpsolve */
				if(!add_constraintex(lp, A_inequ[i].size(), row, colno, LE, b_inequ[i]))
					ret = 3;
			}
		}
	}

	//add the const constraint	
	if (ret == 0){
		if (b_const.size()>0){
			for (unsigned int i = 0; i < b_const.size(); i++){
				if (b_const[i] > 0){
					for (unsigned int j = 0; j < b_const.size(); j++){
						if (i == j){
							colno[j] = j+1;//add the j-th column to lpsolve
							row[j] = 1.0;						
						}				
						else{
							colno[j] = j+1;//add the j-th column to lpsolve
							row[j] = 0.0;
						}
					}
					if(!add_constraintex(lp, b_const.size(), row, colno, EQ, b_const[i]))
						ret = 4;		
				}
			}
		}
	}

	//set the variables to be integer
	if (ret == 0){
		for (int i = 0; i < Ncol; i++)
			set_int(lp, i+1, TRUE);
	}
	
	/* rowmode should be turned off again when done building the model */
	set_add_rowmode(lp, FALSE);	
	//add the objective function
	if (ret == 0){
		//set the objective function
		for (unsigned int i = 0; i < coefficients.size(); i++){
			colno[i] = i+1;
			row[i] = coefficients[i];
		}
		//set the objective in lpsolve
		if(!set_obj_fnex(lp, coefficients.size(), row, colno))
      		ret = 4;
	}

	//set the objective to minimize
	if (ret == 0){
		set_minim(lp);

		/* just out of curioucity, now show the model in lp format on screen */
    	/* this only works if this is a console application. If not, use write_lp and a filename */
    	write_LP(lp, stdout);

		/* I only want to see important messages on screen while solving */
    	set_verbose(lp, IMPORTANT);

    	/* Now let lpsolve calculate a solution */
    	ret = solve(lp);
    	if(ret == OPTIMAL)
      		ret = 0;
    	else
      		ret = 5;
	}

	//get some results
	if (ret == 0){
		/* a solution is calculated, now lets get some results */

    	/* objective value */
    	std::cout << "Objective value: " << get_objective(lp) << std::endl;

		/* variable values */
    	get_variables(lp, row);

		/* variable values */
		variables.resize(Ncol);
		for(j = 0; j < Ncol; j++)
			variables[j] = row[j];

		/* we are done now */
	}
	else{
		std::cout << "The optimal value can't be solved for linear programming, please check the constraints!!\n";
		exit(1);

	}
		
	
	std::cout << "print the result\t # of line segments is \n";
	for (int i = 0; i < Ncol; i++)
		std::cout << "index = " << i << "\t# = " << variables[i] << std::endl;

	/* free allocated memory */
  	if(row != NULL)
    	free(row);
  	if(colno != NULL)
    	free(colno);

	/* clean up such that all used memory by lpsolve is freed */
	if (lp != NULL)
		delete_lp(lp);

	return ret;
}
Esempio n. 7
0
vector<PathPoint *> LPPath :: findPath(vertex *curr) {
	lprec *lp;
	
	int numDropoff = 0;
	int numDropped = 0;
	int numPickup = 0;
	
	//find pairs for each dropoff point
	for(int i = 0; i < points.size(); i++) {
		if(points[i]->type == 1) {
			bool foundPair = false;
			
			for(int j = 0; j < points.size(); j++) {
				if(j != i && points[j]->pairIndex == points[i]->pairIndex) {
					pairIndex[i] = j;
					foundPair = true;
					break;
				}
			}
			
			//sometimes, there's an error and the pair cannot be found
			//in that case, print out some debugging information
			if(!foundPair) {
				cout << i << ":" << points[i]->pairIndex << "  ";
				for(int j = 0; j < points.size(); j++) {
					cout << points[j]->type << ":" << points[j]->pairIndex << " ";
				}
				cout << endl;
			}
		}
	}
	
	//occasionally we encounter a model that takes hours or days to solve
	//we set a timeout on the solve function, and then advance to the next iteration
	//as the iteration increases, we introduce more randomness into the model
	// (this is done via the getNonZero function)
	for(int iteration = 0; ; iteration += 10) {
		//calculate cost matrix
		for(int i = 0; i < points.size(); i++) {
			PathPoint *ipoint = points[i];
		
			if(ipoint->type == 0) numPickup++;
			else if(ipoint->type == 1) numDropoff++;
			else if(ipoint->type == 2) numDropped++;
			
			//from this point to itself
			costMatrix[i + 1][i] = getNonZero(0, iteration);
			
			//from this point to every other point
			for(int j = 0; j < points.size(); j++) {
				if(i != j)
					costMatrix[i + 1][j] = getNonZero(length(ipoint, points[j]), iteration);
			}
			
			//from the current location to this point
			costMatrix[0][i] = getNonZero(taxiPath->shortestPath(curr, ipoint->vert), iteration);
		}

	
		//calculate m matrix
		//first, we have to find earliest and latest
		
		//the current location must occur at time zero
		latest[0] = 0;
	
		for(int i = 0; i < points.size(); i++) {
			if(points[i]->type == 0 || points[i]->type == 2) {
				//this is a pickup or stand-alone dropoff point
				//the earliest time occurs when we go directly
				// from the current location to here
				//the latest time is set by the pickup constraint
				
				earliest[i] = costMatrix[0][i];
				latest[i + 1] = points[i]->remaining;
			} else if(points[i]->type == 1) {
				//this is a dropoff point
				//the earliest time occurs when we go directly
				// to the pickup point, then here
				//the latest time occurs when we get to the pickup
				// point the latest, and then here the latest
				// (stretch both pickup and service constraints)
				earliest[i] = costMatrix[0][pairIndex[i]] + costMatrix[pairIndex[i] + 1][i];
				latest[i + 1] = points[pairIndex[i]]->remaining + points[i]->remaining;
			}
		}
		
		//calculate m
		double test;
		for(int i = 0; i < points.size() + 1; i++) {
			for(int j = 0; j < points.size(); j++) {
				test = latest[i] + costMatrix[i][j] - earliest[j];
				if(test > 0) m[i][j] = test;
				else m[i][j] = 0;
			}
		}
		
		//find the number of binary columns
		//each x_ij determines whether or not the taxi will move
		// from i to j
		//in the comments below these movements will be referred
		// to as route segments (_from_ i _to_ j)
		int ncol = (points.size() + 1) * points.size();
		
		//find the total number of columns
		//besides the binary ones, there are ones for the time
		// at which the taxi will reach a point (B_i)
		int ncol_total = ncol + points.size() + 1;
		
		//create the lp instance
		lp = make_lp(0, ncol_total);
		
		//colno and row are used to define the constraints, and
		// later row will store the result from lpsolve
		//colno identifies the variable (column), and row identifies
		// the constants (multiplied by the variable); then, a
		// separate value determines the number of variables
		// that will be read (since we are using a sparse matrix -
		// otherwise we wouldn't need colno)
		//note**: column numbers are labeled starting from 1, not 0
		int *colno = new int[ncol_total];
		REAL *row = new REAL[ncol_total];
		
		//since we're going to be adding constraints equation
		// by equation, we set add row mode to make it faster
		set_add_rowmode(lp, TRUE);
		
		//disable most output from lpsolve
		set_verbose(lp, CRITICAL);
		
		//set timeout of three seconds so we don't spend forever on this model
		set_timeout(lp, 3);
		
		//set up the binary constraints
		for(int i = 0; i < ncol; i++) {
			set_binary(lp, i + 1, TRUE);
		}
		
		//constraints 1 to 3
		//these have one constraint per point
		for(int i = 0; i < points.size(); i++) {
			//1. the total number of route segments to here will
			// be equal to one
			for(int j = 0; j < points.size() + 1; j++) {
				colno[j] = j * points.size() + i + 1;
				row[j] = 1;
			}
			
			add_constraintex(lp, points.size() + 1, row, colno, EQ, 1);
			
			//2. there will be no route segment from here to itself
			colno[0] = (i + 1) * points.size() + i + 1;
			row[0] = 1;
			add_constraintex(lp, 1, row, colno, EQ, 0);
			
			//3. the total number of route segments from here will
			// be less than or equal to one (since the last point in
			// the route will be zero)
			for(int j = 0; j < points.size(); j++) {
				colno[j] = (i + 1) * points.size() + j + 1;
				row[j] = 1;
			}
			
			add_constraintex(lp, points.size(), row, colno, LE, 1);
		}
		
		//4. there will be exactly one route segment from the
		// current location
		for(int i = 0; i < points.size(); i++) {
			colno[i] = i + 1;
			row[i] = 1;
		}
	
		add_constraintex(lp, points.size(), row, colno, EQ, 1);
	
		//5. the relative time that the taxi reaches the current
		// location is zero
		colno[0] = ncol + 1;
		row[0] = 1;
		add_constraintex(lp, 1, row, colno, EQ, 0);
	
		//6. defined for each route segment (i, j)
		//if the segment (i, j) exists, then the time B_j
		// the taxi reaches j will be greater than
		//    B_i + time(i, j)
		// (time is interchangeable with distance)
		//in other words,
		//    B_j >= ( B_i + time(i, j) ) * x_ij
		//
		//**but that's non-linear (since B_i * x_ij)
		//to achieve the if statement, we subtract a large
		// number M from the right and M * x_ij on the left
		//the equation becomes:
		//    B_j - B_i - M*x_ij >= time(i, j) - M
		//
		//m_ij that we found earlier is suitable for M, since
		// if x_ij = 0 the equation reduces to
		//    B_j - B_i >= time(i, j) - M
		// >> M >= B_i + time(i, j) - B_j
		// we used the maximum possible value for B_i (latest[i])
		//  and the minimim for B_j (earliest[j]), so everything
		//  is good :)
		for(int i = 0; i < points.size() + 1; i++) {
			for(int j = 0; j < points.size(); j++) {
				colno[0] = ncol + 1 + i;
				colno[1] = ncol + 1 + j + 1; //make sure to add an extra 1 because we're not including current location
				colno[2] = i * points.size() + j + 1;
			
				double constant = costMatrix[i][j] - m[i][j];
			
				//only use positive constants or it seems to explode
				if(constant >= 0) {
					row[0] = -1;
					row[1] = 1;
					row[2] = -m[i][j];
		
					add_constraintex(lp, 3, row, colno, GE, constant);
				} else {
					row[0] = 1;
					row[1] = -1;
					row[2] = m[i][j];
		
					add_constraintex(lp, 3, row, colno, LE, -constant);
				}
			}
		}
	
		//constraints 7, 8, and 9
		for(int i = 0; i < points.size(); i++) {
			if(points[i]->type == 1) {
				//dropoff point
				
				//make sure to add an extra 1 because we're not including current location
				colno[0] = ncol + 1 + i + 1;
				colno[1] = ncol + 1 + pairIndex[i] + 1;
			
				row[0] = 1;
				row[1] = -1;
			
				//constraints on L_i (= B_i - B_pickup[i])
				
				//7. L_i >= time(pickup[i], i)
				add_constraintex(lp, 2, row, colno, GE, costMatrix[pairIndex[i] + 1][i]);
				
				//8. L_i <= remaining service constraint
				add_constraintex(lp, 2, row, colno, LE, points[i]->remaining);
			} else if(points[i]->type == 0 || points[i]->type == 2) {
				//pickup or stand-alone dropoff point
				colno[0] = ncol + 1 + i + 1;
				row[0] = 1;
				
				//9. B_i <= remaining pickup constraint
				add_constraintex(lp, 1, row, colno, LE, points[i]->remaining);
			}
		}
	
		//10. this used to enforce that all varibles be
		// non-negative, but it seems to be working now
		// (lpsolve makes variables non-negative unless
		// explicitly stated in a constraint)
		for(int i = ncol; i < ncol_total; i++) {
			colno[0] = i + 1;
			row[0] = 1;
			//add_constraintex(lp, 1, row, colno, GE, 0);
		}
		
		//disable rowmode because we're done building model
		set_add_rowmode(lp, FALSE);
		
		//objective function: minimize sum( time(i, j) * x_ij )
		//we maximize the negative though
		// (we could change to set_minim(lp), but it's the same thing)
		for(int i = 0; i < points.size() + 1; i++) {
			for(int j = 0; j < points.size(); j++) {
				colno[i * points.size() + j] = i * points.size() + j + 1;;
				row[i * points.size() + j] = -costMatrix[i][j];
			}
		}
	
		set_obj_fnex(lp, ncol, row, colno);
		set_maxim(lp); //maximize the objective function
		
		struct timeval solveStartTime;
		struct timeval solveEndTime;
		gettimeofday(&solveStartTime, NULL);
		
		int ret = solve(lp);
		
		gettimeofday(&solveEndTime, NULL);
		long tS = solveStartTime.tv_sec*1000000 + (solveStartTime.tv_usec);
		long tE = solveEndTime.tv_sec*1000000 + (solveEndTime.tv_usec);
		long solveTime = tE - tS;
		
		if(iteration == 0 && ret != TIMEOUT) {
			lpTotalTime += solveTime;
			if(solveTime > lpMaxTime) lpMaxTime = solveTime;
			lpNum++;
			
			cout << "lptimestatus: " << lpTotalTime / lpNum << " " << lpMaxTime << " " << lpNum << " " << solveTime << endl;
		}
		
		//if we didn't get the optimal solution, don't continue
		if(ret != OPTIMAL) {
			delete colno;
			delete row;
			delete_lp(lp);
			bestList.clear();
			
			if(ret == TIMEOUT) {
				//if we timed out, then we need to try again
				cout << "timed out on iteration " << iteration << ", advancing..." << endl;
				continue;
			} else {
				return bestList;
			}
		}
	
		get_variables(lp, row); //store variables in our row array
	
		//extract the ordering of the points from the x_ij in the row
		//at the same time, we calculate the route's distance
		
		int previous = 0;
		minTour = 0;
		
		for(int i = 0; i < points.size(); i++) {
			for(int j = 0; j < points.size(); j++) {
				if(row[previous * points.size() + j] == 1) {
					minTour += costMatrix[previous][j];
				
					bestList.push_back(points[j]);
					previous = j + 1;
					break;
				}
			}
		}

		delete colno;
		delete row;
		delete_lp(lp);
		
		//sometimes errors occur, probably because M was
		// too large and double-precision isn't accurate
		// enough
		//in these cases, since they're rare enough, we
		// assume that the model was infeasible
		if(bestList.size() != points.size()) {
			bestList.clear();
			minTour = numeric_limits<double>::max();
			return bestList;
		}
	
		return bestList;
	}
}
Esempio n. 8
0
void CLPLpsolve::setFunction(CLPFunction* function)
{
	m_status = 0;

	m_lpFunction = function;
	const int nVars = function->getNumCoefficients();

	// Creates an empty problem with getNumCoefficients variables
	m_env = make_lp(0, nVars);

	if(m_env == NULL)
	{	
		m_status = 1;
	}

	//if(!set_add_rowmode(m_env, FALSE))
	//{
	//	m_status = 1;
	//}
	
	//Allowing memory for rows
	//int * colno = new int[nVars];
    REAL * row= new REAL[nVars + 1];

	//set variables names
	for (int i = 0; i < nVars; ++i)
	{
		int lpIndex = i + 1;
		row[lpIndex] = function->getCoefficients().at(i);
		//colno[i] = lpIndex;

		

		//Determines the type
		switch(function->getIntegers().at(i)) {
			case 'C' :
				m_status = set_unbounded(m_env, lpIndex);
				break;

			case 'B' :
				m_status = set_binary(m_env, lpIndex, TRUE);
				break;

			case 'I' :
				m_status = set_int(m_env, lpIndex, TRUE);
				break;

			case 'S' :
				m_status = set_semicont(m_env, lpIndex, TRUE);
				break;

			default:
				assert(false);
				break;
		}
		
		//Sets upper bound and lower bound
		set_upbo(m_env, lpIndex, function->getUpperBounds().at(i));
		set_lowbo(m_env, lpIndex, function->getLowerBounds().at(i));
		set_col_name(m_env, lpIndex, const_cast<char*>(function->getVarNames().at(i).c_str()));

	}

	//set_obj_fnex(m_env, nVars, row, colno); 
	set_obj_fn(m_env, row);

	// Set the type of the problem (Min or Max)
	switch (function->getType()) {
	case lpMinFunction:
		set_minim(m_env);
		break;

	case lpMaxFunction:
		set_maxim(m_env);
		break;
	}

	if(!set_add_rowmode(m_env, TRUE))
	{
		m_status = 1;
	}
	
	delete [] row;

}
Esempio n. 9
0
double solve_constraints(int this_task)
{
	lprec *lp;
	int numVar = 0, *var = NULL, ret = 0, i, j, k, var_count;
	double *coeff = NULL, lhs,rhs, obj;
	char col_name[10];

	/* Creating a model */
	for(i = 1;i < this_task; i++)
		numVar+=i;	
	lp = make_lp(0, numVar);
	if(lp == NULL)
		ret = 1; /* Couldn't construct a new model */
		
	if(ret == 0) {
		var_count = 1;
		for(i = 1 ; i < this_task; i++){
			for(j = i+1 ; j <= this_task; j++)
			{
				sprintf(col_name, "%dNNP%d_%d", this_task, i, j);
				set_col_name(lp, var_count, col_name);
				var_count++;			
			}
		}
		/* create space large enough for one row(i.e. equation) */
		var = (int *) malloc(numVar * sizeof(*var));
		coeff = (double *) malloc(numVar * sizeof(*coeff));
		if((var == NULL) || (coeff == NULL))
			ret = 2;
	}	
	
	/* add the equations to lpsolve */
	if(ret == 0) {
		set_add_rowmode(lp, TRUE);
		/* --------------------adding EQN-D-------------------- */
		for(j = 2;j <= this_task;j++){
			var_count = 0;
			for(i = 1; i < j; i++){
				sprintf(col_name,"%dNNP%d_%d",this_task, i, j);
				var[var_count] = get_nameindex(lp, col_name, FALSE);
				coeff[var_count] = 1;
				var_count++;
			}

			lhs= 0;
			for(i = 1; i < j; i++)
				lhs+= nnp_min[i][j];
			lhs*= floor(R[this_task]/task[j].p);			
			
			rhs = 0;
			for(i = 1; i < j; i++)
				rhs += nnp_max[i][j];
			rhs *= ceil(R[this_task]/task[j].p);
			
			if(!add_constraintex(lp, var_count, coeff, var, GE, lhs))
				ret = 3;
			if(!add_constraintex(lp, var_count, coeff, var, LE, rhs))
				ret = 3;			
		}
	}
	
	if(ret == 0) {	
		/* --------------------adding EQN-E-------------------- */
		for(k = 2;k <= this_task;k++)
		{			
			var_count = 0;
			for(j = 2; j <= k; j++){
				for(i = 1; i < j; i++){
					sprintf(col_name,"%dNNP%d_%d",this_task, i, j);
					var[var_count] = get_nameindex(lp, col_name, FALSE);
					coeff[var_count] = 1;
					var_count++;
				}
			}
			
			rhs = 0;
			for(i = 1; i < k; i++)
				rhs += ceil(R[this_task]/task[i].p);
			if(!add_constraintex(lp, var_count, coeff, var, LE,rhs))
				ret = 3;
		}
	}
	
	if(ret == 0) {
		/* ------------------adding EQN-G & H------------------ */
		for(j = 2; j <= this_task ; j++){
			for(i = 1; i < j; i++){
				lhs= floor(R[this_task]/task[j].p) * nnp_min[i][j];
				sprintf(col_name,"%dNNP%d_%d",this_task, i, j);
				var[0] = get_nameindex(lp, col_name, FALSE);
				coeff[0] = 1;
				if(!add_constraintex(lp, 1, coeff, var, GE, lhs))
					ret = 3;
				
				rhs = min(ceil(R[this_task]/task[i].p), ceil(R[this_task]/task[j].p) * ceil(R[j]/task[i].p), ceil(R[this_task]/task[j].p) * nnp_max[i][j]);
				if(!add_constraintex(lp, 1, coeff, var, LE,rhs))
					ret = 3;
			}
		}
	}
	
	if(ret == 0) {
 		/* --------------------adding EQN-I-------------------- */
		for(i = 1; i < this_task; i++){
			var_count = 0;
			for(j = i+1; j <= this_task; j++){
				sprintf(col_name,"%dNNP%d_%d",this_task, i, j);
				var[var_count] = get_nameindex(lp, col_name, FALSE);
				coeff[var_count] = 1;
				var_count++;				
			}
			rhs = ceil(R[this_task]/task[i].p);
			if(!add_constraintex(lp, var_count, coeff, var, LE,rhs))
				ret = 3;
		}
	}
		
	set_add_rowmode(lp, FALSE);
	if(ret == 0) {
		/* -----------------set the objective----------------- */
		var_count = 0;
		for(i = 1 ; i < this_task; i++){
			for(j = i+1 ; j<= this_task; j++){
				sprintf(col_name,"%dNNP%d_%d",this_task, i, j);
				var[var_count] = get_nameindex(lp, col_name, FALSE);
				coeff[var_count] = get_f(this_task, i, j);
				var_count++;
			}			
		}
		if(!set_obj_fnex(lp, var_count, coeff, var))
			ret = 4;
		set_maxim(lp);
		write_LP(lp, stdout);
		set_verbose(lp, IMPORTANT);
		ret = solve(lp);
		if(ret == OPTIMAL)
			ret = 0;
		else
			ret = 5;
	}
	if(ret == 0) {
		obj = get_objective(lp);
		/* Displaying calculated values */		
		/* variable values */
		printf("\nVariable values:\n");
		get_variables(lp, coeff);
		printf("\n");
		for(j = 0; j < numVar; j++)
			printf("%s: %f\n", get_col_name(lp, j + 1), coeff[j]);		
		/* objective value */
		printf("\nObjective value: %f\n\n", obj);
	}
	printf("LP ERROR = %d\n\n", ret);
	
	/* free allocated memory */
	if(coeff != NULL)
		free(coeff);
	if(var != NULL)
		free(var);
	if(lp != NULL) 		
		delete_lp(lp);
	
	return ret == 0 ? obj : 0;
}
Esempio n. 10
0
    int  calculate (IN  int nCols /* variables in the model */,
                    IN  int nRows,
                    IN  double** rows,
                    IN  double*  rights,
                    IN  double*  objectives,
                    OUT int* answer,
                    IN  int verbose)
    {
      lprec *lp;
      int result = 0;

      char *str = NULL;
      int *colno = NULL;
      double *row = NULL;

      /*  We will build the model row by row
       *  So we start with creating a model
       *  with 0 rows and 2 columns
       */
      if ( !(lp = make_lp (0, nCols)) )
      { 
        /* couldn't construct a new model... */
        result = 1;
        goto RESULT;
      }

      if ( !(str = (char*) malloc ((log10 (nCols) + 10) * sizeof (*str))) )
      {
        result = 2;
        goto RESULT;
      }

      /*  let us name our variables. Not required, 
       *  but can be useful for debugging
       */
      for ( int i = 1; i <= nCols; ++i )
      {       
        str[0] = 't';
        _itoa (i, str + 1, 10);

        set_col_name (lp, i, str);
        // set_int (lp, i, TRUE);
      }

      /* create space large enough for one row */
      colno = (int   *) malloc (nCols * sizeof (*colno));
      row   = (double*) malloc (nCols * sizeof (*row));

      if ( (colno == NULL) || (row == NULL) )
      {
        result = 2;
        goto RESULT;
      }

      for ( int j = 0; j < nCols; ++j )
      { colno[j] = j + 1; /* (j + 1) column */ }

      /* makes building the model faster if it is done rows by row */
      set_add_rowmode (lp, TRUE);
      
      for ( int i = 0; i < nRows; ++i )
      {
        // /* construct j row */
        // for ( int j = 0; j < nCols; ++j )
        // { row[j] = ??? ; }

        /* (210 * t2 + 156 * t3 == 0.0178) */
        /* (230 * t2 + 160 * t3 == 0.0176) */

        /* add the row to lp_solve */
        if ( !add_constraintex (lp, nCols, rows[i], colno, EQ, rights[i]) )
        {
          result = 3;
          goto RESULT;
        }
      }

      /* rowmode should be turned off again when done building the model */
      set_add_rowmode (lp, FALSE); 

      // /* set the objective function  */
      // for ( int j = 0; j < nCols; ++j )
      // { row[j] = objectives[j]; }

      /* (t1 + t2 + t3 + t4) */

      /* set the objective in lp_solve */
      if ( !set_obj_fnex (lp, nCols, objectives, colno) )
      {
        result = 4;
        goto RESULT;
      }
      
      /* set the object direction to maximize */
      set_minim (lp);

      if ( verbose )
      {
        /* just out of curioucity, now show the model in lp format on screen */
        /* this only works if this is a console application. If not, use write_lp and a filename */
        write_LP (lp, stdout);
        /* write_lp(lp, "model.lp"); */
      }
      
      /* I only want to see important messages on screen while solving */
      set_verbose (lp, IMPORTANT);
      
      /* Now let lpsolve calculate a solution */
      result = solve (lp);
      if ( result == OPTIMAL )
      { result = 0; }
      else
      {
        result = 5;
        goto RESULT;
      }

      /*  a solution is calculated,
       *  now lets get some results
       */
      if ( verbose )
      {
        /* objective value */
        printf ("Objective value: %f\n", get_objective (lp));
      }

      /* variable values */
      get_variables (lp, row);
      for ( int j = 0; j < nCols; j++ )
      {
        if ( verbose )
          printf ("%s: %f\n", get_col_name (lp, j + 1), row[j]);
        
        answer[j] = row[j];
      }
      /* we are done now */

RESULT:;
      /* free allocated memory */
      if ( str != NULL )free (str);
      if ( row != NULL ) free (row);
      if ( colno != NULL ) free (colno);

      if ( lp != NULL )
      {
        /* clean up such that all used memory by lpsolve is freed */
        delete_lp (lp);
      }

      return result;
    }
Esempio n. 11
0
void LoadBalancing::lp_create_model() {
	int Ncol=3*num_using_nodes_+(num_using_nodes_-1)*(num_quantiles_+2);
	int i,j;
	int *colno=(int*)malloc((Ncol+1)*sizeof(int));
	REAL *row=(REAL*)malloc((Ncol+1)*sizeof(REAL));
	int *sosvars=(int*)malloc((num_quantiles_+2)*sizeof(int));
	int ret;

	lp = make_lp(0,Ncol);
	if(lp == NULL) {
		fprintf(stderr, "Unable to create new LP model\n");
//		return(-1);
	}
	resize_lp(lp, 6*num_using_nodes_-3, Ncol);

	//Set objective function
	set_obj(lp,num_using_nodes_+1,1);

	//Add constraints:
	set_add_rowmode(lp, TRUE);

	// D*x + E*ip - t <= -G
	for(i=0;i<num_using_nodes_;i++){
		for(j=0;j<num_using_nodes_;j++){
			colno[j]=POS_Xi(j);
			row[j]=lp_D[i*num_using_nodes_+j];
		}
		colno[j]=POS_IPi(i); //ip(i);
		row[j]=Mopt_*lp_E[i];
		colno[j+1]=POS_T;
		row[j+1]=-1;// -t
		add_constraintex(lp,j+2,row,colno,LE,-lp_G[i]);
	}

	//Increasing constraints, considering the overlap, (x[n]-x[n+1]<=-2*overlap_)
	for(i=0;i<num_using_nodes_-2;i++){
		colno[0]=POS_Xi(i);
		row[0]=1;
		colno[1]=POS_Xi(i+1);
		row[1]=-1;
		add_constraintex(lp,2,row,colno,LE,-2*overlap_);
	}
	colno[0]=POS_Xi(i);
	row[0]=1;
	colno[1]=POS_Xi(i+1);
	row[1]=-1;
	add_constraintex(lp,2,row,colno,LE,-overlap_);


	//And the last cut must be 1: (x[num_using_nodes_]=1)
	colno[0]=POS_Xi(num_using_nodes_-1);
	row[0]=1;
	add_constraintex(lp,1,row,colno,EQ,1);

	//And now we define the number of interest points for each cut (ip1, ip2,...)
	// ip1=f1
	// ip2=f2-f1
	// ip3=f3-f2
	// ipN=1-f3

	//ip1:
	colno[0]=POS_IPi(0); //ip1
	row[0]=-1;
	colno[1]=POS_Fi(0); //f1
	row[1]=1;
	add_constraintex(lp,2,row,colno,EQ,0);

	//ip2 to ip(N-1):
	for(i=1;i<num_using_nodes_-1;i++){
		colno[0]=POS_IPi(i); //ip(i)
		row[0]=-1;
		colno[1]=POS_Fi(i); //f(i)
		row[1]=1;
		colno[2]=POS_Fi(i-1); //f(i-1)
		row[2]=-1;
		add_constraintex(lp,3,row,colno,EQ,0);
	}

	//ipN:
	colno[0]=POS_IPi(num_using_nodes_-1); //ipN
	row[0]=1;
	colno[1]=POS_Fi(num_using_nodes_-2); //f(N-1)
	row[1]=1;
	add_constraintex(lp,2,row,colno,EQ,1);


	//SOS variables:
	// d10+d11+d12+d13+...=1
	for(i=0;i<num_using_nodes_-1;i++){
		for(j=0;j<num_quantiles_+2;j++){
			colno[j]=POS_Dij(i,j);
			row[j]=1;
			sosvars[j]=POS_Dij(i,j);
		}
		char sosName[] = "SOS"; //Gives a warning otherwise...
		add_SOS(lp, sosName, 2, 1, num_quantiles_+2, sosvars, NULL);
		add_constraintex(lp,num_quantiles_+2,row,colno,EQ,1);
	}

	//So now we define the piecewise functions f (number of interest points left of x)
	for(i=0;i<num_using_nodes_-1;i++){
		colno[0]=POS_Fi(i); //fi
		row[0]=-1;
		for(j=0;j<num_quantiles_;j++){
			colno[j+1]=POS_Dij(i,j+1);
			row[j+1]=(j+1.0)/num_quantiles_;
		}
		colno[j+1]=POS_Dij(i,j+1);
		row[j+1]=1;
		add_constraintex(lp,num_quantiles_+2,row,colno,EQ,0);
	}

	// Now x1=q1*d11 + q2*d12 + ...
	for(i=0;i<num_using_nodes_-1;i++){
		colno[0]=POS_Xi(i);
		row[0]=-1;
		for(j=0;j<num_quantiles_;j++){
			colno[j+1]=POS_Dij(i,j+1);
			row[j+1]=(float)IPx_quantile_aprox_.at(j)/width_;
		}
		colno[j+1]=POS_Dij(i,j+1);
		row[j+1]=1;
		add_constraintex(lp,num_quantiles_+2,row,colno,EQ,0);
	}

	set_add_rowmode(lp, FALSE);

	free(colno);
	free(row);
	free(sosvars);
	is_lpmodel_created_=true;
}
Esempio n. 12
0
int demo()
{
    lprec *lp;
    int Ncol, *colno = NULL, j, ret = 0;
    REAL *row = NULL;

    /* We will build the model row by row
       So we start with creating a model with 0 rows and 2 columns */
    Ncol = 2; /* there are two variables in the model */
    lp = make_lp(0, Ncol);
    if(lp == NULL)
        ret = 1; /* couldn't construct a new model... */

    if(ret == 0) {
        /* let us name our variables. Not required, but can be useful for debugging */
        set_col_name(lp, 1, "x");
        set_col_name(lp, 2, "y");

        /* create space large enough for one row */
        colno = (int *) malloc(Ncol * sizeof(*colno));
        row = (REAL *) malloc(Ncol * sizeof(*row));
        if((colno == NULL) || (row == NULL))
            ret = 2;
    }

    if(ret == 0) {
        set_add_rowmode(lp, TRUE);  /* makes building the model faster if it is done rows by row */

        /* construct first row (120 x + 210 y <= 15000) */
        j = 0;

        colno[j] = 1; /* first column */
        row[j++] = 120;

        colno[j] = 2; /* second column */
        row[j++] = 210;

        /* add the row to lpsolve */
        if(!add_constraintex(lp, j, row, colno, LE, 15000))
            ret = 3;
    }

    if(ret == 0) {
        /* construct second row (110 x + 30 y <= 4000) */
        j = 0;

        colno[j] = 1; /* first column */
        row[j++] = 110;

        colno[j] = 2; /* second column */
        row[j++] = 30;

        /* add the row to lpsolve */
        if(!add_constraintex(lp, j, row, colno, LE, 4000))
            ret = 3;
    }

    if(ret == 0) {
        /* construct third row (x + y <= 75) */
        j = 0;

        colno[j] = 1; /* first column */
        row[j++] = 1;

        colno[j] = 2; /* second column */
        row[j++] = 1;

        /* add the row to lpsolve */
        if(!add_constraintex(lp, j, row, colno, LE, 75))
            ret = 3;
    }

    if(ret == 0) {
        set_add_rowmode(lp, FALSE); /* rowmode should be turned off again when done building the model */

        /* set the objective function (143 x + 60 y) */
        j = 0;

        colno[j] = 1; /* first column */
        row[j++] = 143;

        colno[j] = 2; /* second column */
        row[j++] = 60;

        /* set the objective in lpsolve */
        if(!set_obj_fnex(lp, j, row, colno))
            ret = 4;
    }

    if(ret == 0) {
        /* set the object direction to maximize */
        set_maxim(lp);

        /* just out of curioucity, now show the model in lp format on screen */
        /* this only works if this is a console application. If not, use write_lp and a filename */
        write_LP(lp, stdout);
        /* write_lp(lp, "model.lp"); */

        /* I only want to see important messages on screen while solving */
        set_verbose(lp, IMPORTANT);

        /* Now let lpsolve calculate a solution */
        ret = solve(lp);
        if(ret == OPTIMAL)
            ret = 0;
        else
            ret = 5;
    }

    if(ret == 0) {
        /* a solution is calculated, now lets get some results */

        /* objective value */
        printf("Objective value: %f\n", get_objective(lp));

        /* variable values */
        get_variables(lp, row);
        for(j = 0; j < Ncol; j++)
            printf("%s: %f\n", get_col_name(lp, j + 1), row[j]);

        /* we are done now */
    }

    /* free allocated memory */
    if(row != NULL)
        free(row);
    if(colno != NULL)
        free(colno);

    if(lp != NULL) {
        /* clean up such that all used memory by lpsolve is freed */
        delete_lp(lp);
    }

    return(ret);
}