solve_VPSC.cpp revision aaacc83e3fab3c943e5d3b59646109b6b92c08dd
/**
* \brief Solve an instance of the "Variable Placement with Separation
* Constraints" problem.
*
* Authors:
* Tim Dwyer <tgdwyer@gmail.com>
*
* Copyright (C) 2005 Authors
*
* Released under GNU LGPL. Read the file 'COPYING' for more information.
*/
#include <cassert>
#include "constraint.h"
#include "block.h"
#include "blocks.h"
#include "solve_VPSC.h"
#include <math.h>
#include <sstream>
#ifdef RECTANGLE_OVERLAP_LOGGING
#include <fstream>
#endif
#include <map>
using namespace std;
namespace vpsc {
static const double ZERO_UPPERBOUND=-0.0000001;
(*i)->active=false;
}
}
Solver::Solver(const unsigned n, Variable* const vs[], const unsigned m, Constraint *cs[]) : m(m), cs(cs), n(n), vs(vs) {
#ifdef RECTANGLE_OVERLAP_LOGGING
printBlocks();
//assert(!constraintGraphIsCyclic(n,vs));
#endif
}
delete bs;
}
// useful in debugging
void Solver::printBlocks() {
#ifdef RECTANGLE_OVERLAP_LOGGING
Block *b=*i;
f<<" "<<*b<<endl;
}
for(unsigned i=0;i<m;i++) {
}
#endif
}
/**
* Produces a feasible - though not necessarily optimal - solution by
* examining blocks in the partial order defined by the directed acyclic
* graph of constraints. For each block (when processing left to right) we
* maintain the invariant that all constraints to the left of the block
* (incoming constraints) are satisfied. This is done by repeatedly merging
* blocks into bigger blocks across violated constraints (most violated
* first) fixing the position of variables inside blocks relative to one
* another so that constraints internal to the block are satisfied.
*/
Variable *v=*i;
}
}
for(unsigned i=0;i<m;i++) {
#ifdef RECTANGLE_OVERLAP_LOGGING
#endif
//assert(cs[i]->slack()>-0.0000001);
throw "Unsatisfied constraint";
}
}
delete vs;
}
bool solved=false;
// Solve shouldn't loop indefinately
// ... but just to make sure we limit the number of iterations
unsigned maxtries=100;
solved=true;
maxtries--;
Block *b=*i;
b->setUpInConstraints();
b->setUpOutConstraints();
}
Block *b=*i;
Constraint *c=b->findMinLM();
#ifdef RECTANGLE_OVERLAP_LOGGING
f<<"Split on constraint: "<<*c<<endl;
#endif
// Split on c
// split alters the block set so we have to restart
solved=false;
break;
}
}
}
for(unsigned i=0;i<m;i++) {
throw "Unsatisfied constraint";
}
}
}
/**
* Calculate the optimal solution. After using satisfy() to produce a
* feasible solution, refine() examines each block to see if further
* refinement is possible by splitting the block. This is done repeatedly
* until no further improvement is possible.
*/
satisfy();
refine();
}
#ifdef RECTANGLE_OVERLAP_LOGGING
f<<"solve_inc()..."<<endl;
#endif
do {
satisfy();
splitBlocks();
#ifdef RECTANGLE_OVERLAP_LOGGING
#endif
}
/**
* incremental version of satisfy that allows refinement after blocks are
* moved.
*
* - move blocks to new positions
* - repeatedly merge across most violated constraint until no more
* violated constraints exist
*
* Note: there is a special case to handle when the most violated constraint
* is between two variables in the same block. Then, we must split the block
* over an active constraint between the two variables. We choose the
* constraint with the most negative lagrangian multiplier.
*/
#ifdef RECTANGLE_OVERLAP_LOGGING
f<<"satisfy_inc()..."<<endl;
#endif
splitBlocks();
long splitCtr = 0;
Constraint* v = NULL;
} else {
// cycle found, relax the violated, cyclic constraint
continue;
}
if(splitCtr++>10000) {
throw "Cycle Error!";
}
// constraint is within block, need to split first
}
}
#ifdef RECTANGLE_OVERLAP_LOGGING
f<<" finished merges."<<endl;
#endif
for(unsigned i=0;i<m;i++) {
v=cs[i];
if(v->slack() < ZERO_UPPERBOUND) {
s<<"Unsatisfied constraint: "<<*v;
#ifdef RECTANGLE_OVERLAP_LOGGING
#endif
}
}
#ifdef RECTANGLE_OVERLAP_LOGGING
f<<" finished cleanup."<<endl;
printBlocks();
#endif
}
void IncSolver::moveBlocks() {
#ifdef RECTANGLE_OVERLAP_LOGGING
f<<"moveBlocks()..."<<endl;
#endif
Block *b = *i;
b->wposn = b->desiredWeightedPosition();
}
#ifdef RECTANGLE_OVERLAP_LOGGING
f<<" moved blocks."<<endl;
#endif
}
void IncSolver::splitBlocks() {
#ifdef RECTANGLE_OVERLAP_LOGGING
#endif
moveBlocks();
splitCnt=0;
// Split each block if necessary on min LM
Block* b = *i;
Constraint* v=b->findMinLM();
#ifdef RECTANGLE_OVERLAP_LOGGING
#endif
splitCnt++;
b->split(l,r,v);
b->deleted=true;
#ifdef RECTANGLE_OVERLAP_LOGGING
#endif
}
}
#ifdef RECTANGLE_OVERLAP_LOGGING
f<<" finished splits."<<endl;
#endif
}
/**
* Scan constraint list for the most violated constraint, or the first equality
* constraint
*/
Constraint* v=NULL;
#ifdef RECTANGLE_OVERLAP_LOGGING
f<<"Looking for most violated..."<<endl;
#endif
Constraint *c=*i;
v=c;
deletePoint=i;
if(c->equality) break;
}
}
// Because the constraint list is not order dependent we just
// move the last element over the deletePoint and resize
// downwards. There is always at least 1 element in the
// vector because of search.
}
#ifdef RECTANGLE_OVERLAP_LOGGING
f<<" most violated is: "<<*v<<endl;
#endif
return v;
}
struct node {
};
// useful in debugging - cycles would be BAD
for(unsigned i=0;i<n;i++) {
}
for(unsigned i=0;i<n;i++) {
}
}
}
u=*i;
break;
}
}
//cycle found!
return true;
} else {
node *v=*j;
}
delete u;
}
}
delete graph[i];
}
return false;
}
// useful in debugging - cycles would be BAD
bool Solver::blockGraphIsCyclic() {
Block *b=*i;
bmap[b]=u;
}
Block *b=*i;
b->setUpInConstraints();
Constraint *c=b->findMinInConstraint();
while(c!=NULL) {
b->deleteMinInConstraint();
c=b->findMinInConstraint();
}
b->setUpOutConstraints();
c=b->findMinOutConstraint();
while(c!=NULL) {
b->deleteMinOutConstraint();
c=b->findMinOutConstraint();
}
}
u=*i;
break;
}
}
//cycle found!
return true;
} else {
node *v=*j;
}
delete u;
}
}
delete graph[i];
}
return false;
}
}