Example #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);
}
Example #3
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;
	}
}
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;

}