Sketcher: basic graph based system partitioning

This commit is contained in:
logari81 2012-04-14 12:10:32 +02:00
parent 1684585733
commit 126b25e690
4 changed files with 93 additions and 77 deletions

View File

@ -1563,13 +1563,14 @@ bool Sketch::updateGeometry()
// solving ========================================================== // solving ==========================================================
int Sketch::solve() int Sketch::solve(void)
{ {
Base::TimeInfo start_time; Base::TimeInfo start_time;
if (!isInitMove) { // make sure we are in single subsystem mode if (!isInitMove) { // make sure we are in single subsystem mode
GCSsys.clearByTag(-1); GCSsys.clearByTag(-1);
GCSsys.clearByTag(-2); GCSsys.clearByTag(-2);
isFine = true;
} }
int ret; int ret;
@ -1580,15 +1581,15 @@ int Sketch::solve()
case 0: // solving with the default DogLeg solver case 0: // solving with the default DogLeg solver
// (or with SQP if we are in moving mode) // (or with SQP if we are in moving mode)
solvername = isInitMove ? "SQP" : "DogLeg"; solvername = isInitMove ? "SQP" : "DogLeg";
ret = GCSsys.solve(true, GCS::DogLeg); ret = GCSsys.solve(isFine, GCS::DogLeg);
break; break;
case 1: // solving with the LevenbergMarquardt solver case 1: // solving with the LevenbergMarquardt solver
solvername = "LevenbergMarquardt"; solvername = "LevenbergMarquardt";
ret = GCSsys.solve(true, GCS::LevenbergMarquardt); ret = GCSsys.solve(isFine, GCS::LevenbergMarquardt);
break; break;
case 2: // solving with the BFGS solver case 2: // solving with the BFGS solver
solvername = "BFGS"; solvername = "BFGS";
ret = GCSsys.solve(true, GCS::BFGS); ret = GCSsys.solve(isFine, GCS::BFGS);
break; break;
case 3: // last resort: augment the system with a second subsystem and use the SQP solver case 3: // last resort: augment the system with a second subsystem and use the SQP solver
solvername = "SQP(augmented system)"; solvername = "SQP(augmented system)";
@ -1601,7 +1602,7 @@ int Sketch::solve()
GCSsys.addConstraintEqual(*it, &InitParameters[i], -2); GCSsys.addConstraintEqual(*it, &InitParameters[i], -2);
} }
GCSsys.initSolution(Parameters); GCSsys.initSolution(Parameters);
ret = GCSsys.solve(true); ret = GCSsys.solve(isFine);
break; break;
} }
@ -1647,8 +1648,10 @@ int Sketch::solve()
return ret; return ret;
} }
int Sketch::initMove(int geoId, PointPos pos) int Sketch::initMove(int geoId, PointPos pos, bool fine)
{ {
isFine = fine;
geoId = checkGeoId(geoId); geoId = checkGeoId(geoId);
GCSsys.clearByTag(-1); GCSsys.clearByTag(-1);

View File

@ -94,7 +94,7 @@ public:
/** initializes a point (or curve) drag by setting the current /** initializes a point (or curve) drag by setting the current
* sketch status as a reference * sketch status as a reference
*/ */
int initMove(int geoId, PointPos pos); int initMove(int geoId, PointPos pos, bool fine=true);
/** move this point (or curve) to a new location and solve. /** move this point (or curve) to a new location and solve.
* This will introduce some additional weak constraints expressing * This will introduce some additional weak constraints expressing
@ -212,6 +212,7 @@ protected:
std::vector<GCS::Circle> Circles; std::vector<GCS::Circle> Circles;
bool isInitMove; bool isInitMove;
bool isFine;
private: private:
/// retrieves the index of a point /// retrieves the index of a point

View File

@ -27,9 +27,14 @@
#include "qp_eq.h" #include "qp_eq.h"
#include <Eigen/QR> #include <Eigen/QR>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/connected_components.hpp>
namespace GCS namespace GCS
{ {
typedef boost::adjacency_list <boost::vecS, boost::vecS, boost::undirectedS> Graph;
/////////////////////////////////////// ///////////////////////////////////////
// Solver // Solver
/////////////////////////////////////// ///////////////////////////////////////
@ -38,9 +43,7 @@ namespace GCS
System::System() System::System()
: clist(0), : clist(0),
c2p(), p2c(), c2p(), p2c(),
subsys0(0), subsyslist(0),
subsys1(0),
subsys2(0),
reference(), reference(),
init(false) init(false)
{ {
@ -48,9 +51,7 @@ System::System()
System::System(std::vector<Constraint *> clist_) System::System(std::vector<Constraint *> clist_)
: c2p(), p2c(), : c2p(), p2c(),
subsys0(0), subsyslist(0),
subsys1(0),
subsys2(0),
reference(), reference(),
init(false) init(false)
{ {
@ -553,6 +554,28 @@ void System::initSolution(VEC_pD &params)
// - Organizes the rest of constraints into two subsystems for // - Organizes the rest of constraints into two subsystems for
// tag ids >=0 and < 0 respectively and applies the // tag ids >=0 and < 0 respectively and applies the
// system reduction specified in the previous step // system reduction specified in the previous step
MAP_pD_I params_index;
for (int i=0; i < int(params.size()); ++i)
params_index[params[i]] = i;
Graph g;
for (int i=0; i < int(params.size() + clist.size()); i++)
boost::add_vertex(g);
int cvtid = int(params.size());
for (std::vector<Constraint *>::const_iterator constr=clist.begin();
constr != clist.end(); ++constr, cvtid++) {
VEC_pD &cparams = c2p[*constr];
for (VEC_pD::const_iterator param=cparams.begin();
param != cparams.end(); ++param) {
MAP_pD_I::const_iterator it = params_index.find(*param);
if (it != params_index.end())
boost::add_edge(cvtid, it->second, g);
}
}
VEC_I components(boost::num_vertices(g));
int components_size = boost::connected_components(g, &components[0]);
clearReference(); clearReference();
for (VEC_pD::const_iterator param=params.begin(); for (VEC_pD::const_iterator param=params.begin();
@ -564,9 +587,6 @@ void System::initSolution(VEC_pD &params)
reductionmap.clear(); reductionmap.clear();
{ {
VEC_pD reduced_params=params; VEC_pD reduced_params=params;
MAP_pD_I params_index;
for (int i=0; i < int(params.size()); ++i)
params_index[params[i]] = i;
for (std::vector<Constraint *>::const_iterator constr=clist.begin(); for (std::vector<Constraint *>::const_iterator constr=clist.begin();
constr != clist.end(); ++constr) { constr != clist.end(); ++constr) {
@ -589,27 +609,39 @@ void System::initSolution(VEC_pD &params)
reductionmap[params[i]] = reduced_params[i]; reductionmap[params[i]] = reduced_params[i];
} }
int i=0; std::vector< std::vector<Constraint *> > clists0(components_size),
std::vector<Constraint *> clist0, clist1, clist2; clists1(components_size),
clists2(components_size);
int i = int(params.size());
for (std::vector<Constraint *>::const_iterator constr=clist.begin(); for (std::vector<Constraint *>::const_iterator constr=clist.begin();
constr != clist.end(); ++constr, i++) { constr != clist.end(); ++constr, i++) {
if (eliminated.count(*constr) == 0) { if (eliminated.count(*constr) == 0) {
int id = components[i];
if ((*constr)->getTag() >= 0) if ((*constr)->getTag() >= 0)
clist0.push_back(*constr); clists0[id].push_back(*constr);
else if ((*constr)->getTag() == -1) // move constraints else if ((*constr)->getTag() == -1) // move constraints
clist1.push_back(*constr); clists1[id].push_back(*constr);
else // distance from reference constraints else // distance from reference constraints
clist2.push_back(*constr); clists2[id].push_back(*constr);
} }
} }
std::vector< std::vector<double *> > plists(components_size);
for (int i=0; i < int(params.size()); ++i) {
int id = components[i];
plists[id].push_back(params[i]);
}
clearSubSystems(); clearSubSystems();
if (clist0.size() > 0) for (int cid=0; cid < components_size; cid++) {
subsys0 = new SubSystem(clist0, params, reductionmap); subsyslist.push_back(std::vector<SubSystem *>(0));
if (clist1.size() > 0) if (clists0[cid].size() > 0)
subsys1 = new SubSystem(clist1, params, reductionmap); subsyslist[cid].push_back(new SubSystem(clists0[cid], plists[cid], reductionmap));
if (clist2.size() > 0) if (clists1[cid].size() > 0)
subsys2 = new SubSystem(clist2, params, reductionmap); subsyslist[cid].push_back(new SubSystem(clists1[cid], plists[cid], reductionmap));
if (clists2[cid].size() > 0)
subsyslist[cid].push_back(new SubSystem(clists2[cid], plists[cid], reductionmap));
}
init = true; init = true;
} }
@ -634,31 +666,26 @@ int System::solve(VEC_pD &params, bool isFine, Algorithm alg)
int System::solve(bool isFine, Algorithm alg) int System::solve(bool isFine, Algorithm alg)
{ {
if (subsys0) { bool isReset = false;
resetToReference(); // return success by default in order to permit coincidence constraints to be applied
if (subsys2) { // even if no other system has to be solved
int ret = solve(subsys0, subsys2, isFine); int res = Success;
if (subsys1) // give subsys1 higher priority than subsys2 for (int cid=0; cid < int(subsyslist.size()); cid++) {
// in this case subsys2 acts like a preconditioner if (subsyslist[cid].size() > 0 && !isReset) {
return solve(subsys0, subsys1, isFine); resetToReference();
else isReset = true;
return ret;
} }
else if (subsys1) if (subsyslist[cid].size() == 1)
return solve(subsys0, subsys1, isFine); res = std::max(res, solve(subsyslist[cid][0], isFine, alg));
else else if (subsyslist[cid].size() == 2)
return solve(subsys0, isFine, alg); res = std::max(res, solve(subsyslist[cid][0], subsyslist[cid][1], isFine));
else if (subsyslist[cid].size() > 2)
// subsystem 1 has higher priority than subsystems 2,3,...
// these subsystems act like a preconditioner
for (int i=subsyslist[cid].size()-1; i > 0; i--)
res = std::max(res, solve(subsyslist[cid][0], subsyslist[cid][i], isFine));
} }
else if (subsys1) { return res;
resetToReference();
if (subsys2)
return solve(subsys1, subsys2, isFine);
else
return solve(subsys1, isFine, alg);
}
else
// return success in order to permit coincidence constraints to be applied
return Success;
} }
int System::solve(SubSystem *subsys, bool isFine, Algorithm alg) int System::solve(SubSystem *subsys, bool isFine, Algorithm alg)
@ -1193,25 +1220,11 @@ int System::solve(SubSystem *subsysA, SubSystem *subsysB, bool isFine)
} }
void System::getSubSystems(std::vector<SubSystem *> &subsysvec)
{
subsysvec.clear();
if (subsys0)
subsysvec.push_back(subsys0);
if (subsys1)
subsysvec.push_back(subsys1);
if (subsys2)
subsysvec.push_back(subsys2);
}
void System::applySolution() void System::applySolution()
{ {
if (subsys2) for (int cid=0; cid < int(subsyslist.size()); cid++)
subsys2->applySolution(); for (int i=subsyslist[cid].size()-1; i >= 0; i--)
if (subsys1) subsyslist[cid][i]->applySolution();
subsys1->applySolution();
if (subsys0)
subsys0->applySolution();
for (MAP_pD_pD::const_iterator it=reductionmap.begin(); for (MAP_pD_pD::const_iterator it=reductionmap.begin();
it != reductionmap.end(); ++it) it != reductionmap.end(); ++it)
@ -1303,12 +1316,9 @@ int System::diagnose(VEC_pD &params, VEC_I &conflicting)
void System::clearSubSystems() void System::clearSubSystems()
{ {
init = false; init = false;
std::vector<SubSystem *> subsystems; for (int i=0; i < int(subsyslist.size()); i++)
getSubSystems(subsystems); free(subsyslist[i]);
free(subsystems); subsyslist.clear();
subsys0 = NULL;
subsys1 = NULL;
subsys2 = NULL;
} }
double lineSearch(SubSystem *subsys, Eigen::VectorXd &xdir) double lineSearch(SubSystem *subsys, Eigen::VectorXd &xdir)

View File

@ -54,9 +54,12 @@ namespace GCS
std::map<Constraint *,VEC_pD > c2p; // constraint to parameter adjacency list std::map<Constraint *,VEC_pD > c2p; // constraint to parameter adjacency list
std::map<double *,std::vector<Constraint *> > p2c; // parameter to constraint adjacency list std::map<double *,std::vector<Constraint *> > p2c; // parameter to constraint adjacency list
SubSystem *subsys0; // has the highest priority, always used as the primary subsystem // each row of subsyslist contains 3 subsystems.
SubSystem *subsys1; // normally used as secondary subsystem, it is considered primary only if subsys0 is missing // the first one has the highest priority, always used as the primary subsystem
SubSystem *subsys2; // has the lowest priority, always used as secondary system // the second one is normally used as secondary subsystem, it is considered primary
// only if the first one is missing
// the rhird one has the lowest priority, always used as secondary system
std::vector< std::vector<SubSystem *> > subsyslist;
void clearSubSystems(); void clearSubSystems();
MAP_pD_D reference; MAP_pD_D reference;
@ -152,7 +155,6 @@ namespace GCS
int solve(SubSystem *subsys, bool isFine=true, Algorithm alg=DogLeg); int solve(SubSystem *subsys, bool isFine=true, Algorithm alg=DogLeg);
int solve(SubSystem *subsysA, SubSystem *subsysB, bool isFine=true); int solve(SubSystem *subsysA, SubSystem *subsysB, bool isFine=true);
void getSubSystems(std::vector<SubSystem *> &subsysvec);
void applySolution(); void applySolution();
void undoSolution(); void undoSolution();