00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <iostream>
00023 #include <algorithm>
00024 #include <cfloat>
00025
00026 #include "GCS.h"
00027 #include "qp_eq.h"
00028 #include <Eigen/QR>
00029
00030 namespace GCS
00031 {
00032
00034
00036
00037
00038 System::System()
00039 : clist(0),
00040 c2p(), p2c(),
00041 subsys0(0),
00042 subsys1(0),
00043 subsys2(0),
00044 reference(),
00045 init(false)
00046 {
00047 }
00048
00049 System::System(std::vector<Constraint *> clist_)
00050 : c2p(), p2c(),
00051 subsys0(0),
00052 subsys1(0),
00053 subsys2(0),
00054 reference(),
00055 init(false)
00056 {
00057
00058 for (std::vector<Constraint *>::iterator constr=clist_.begin();
00059 constr != clist_.end(); ++constr) {
00060 Constraint *newconstr;
00061 switch ((*constr)->getTypeId()) {
00062 case Equal: {
00063 ConstraintEqual *oldconstr = static_cast<ConstraintEqual *>(*constr);
00064 newconstr = new ConstraintEqual(*oldconstr);
00065 break;
00066 }
00067 case Difference: {
00068 ConstraintDifference *oldconstr = static_cast<ConstraintDifference *>(*constr);
00069 newconstr = new ConstraintDifference(*oldconstr);
00070 break;
00071 }
00072 case P2PDistance: {
00073 ConstraintP2PDistance *oldconstr = static_cast<ConstraintP2PDistance *>(*constr);
00074 newconstr = new ConstraintP2PDistance(*oldconstr);
00075 break;
00076 }
00077 case P2PAngle: {
00078 ConstraintP2PAngle *oldconstr = static_cast<ConstraintP2PAngle *>(*constr);
00079 newconstr = new ConstraintP2PAngle(*oldconstr);
00080 break;
00081 }
00082 case P2LDistance: {
00083 ConstraintP2LDistance *oldconstr = static_cast<ConstraintP2LDistance *>(*constr);
00084 newconstr = new ConstraintP2LDistance(*oldconstr);
00085 break;
00086 }
00087 case PointOnLine: {
00088 ConstraintPointOnLine *oldconstr = static_cast<ConstraintPointOnLine *>(*constr);
00089 newconstr = new ConstraintPointOnLine(*oldconstr);
00090 break;
00091 }
00092 case Parallel: {
00093 ConstraintParallel *oldconstr = static_cast<ConstraintParallel *>(*constr);
00094 newconstr = new ConstraintParallel(*oldconstr);
00095 break;
00096 }
00097 case Perpendicular: {
00098 ConstraintPerpendicular *oldconstr = static_cast<ConstraintPerpendicular *>(*constr);
00099 newconstr = new ConstraintPerpendicular(*oldconstr);
00100 break;
00101 }
00102 case L2LAngle: {
00103 ConstraintL2LAngle *oldconstr = static_cast<ConstraintL2LAngle *>(*constr);
00104 newconstr = new ConstraintL2LAngle(*oldconstr);
00105 break;
00106 }
00107 case MidpointOnLine: {
00108 ConstraintMidpointOnLine *oldconstr = static_cast<ConstraintMidpointOnLine *>(*constr);
00109 newconstr = new ConstraintMidpointOnLine(*oldconstr);
00110 break;
00111 }
00112 case None:
00113 break;
00114 }
00115 if (newconstr)
00116 addConstraint(newconstr);
00117 }
00118 }
00119
00120 System::~System()
00121 {
00122 clear();
00123 }
00124
00125 void System::clear()
00126 {
00127 clearReference();
00128 clearSubSystems();
00129 free(clist);
00130 c2p.clear();
00131 p2c.clear();
00132 }
00133
00134 void System::clearByTag(int tagId)
00135 {
00136 std::vector<Constraint *> constrvec;
00137 for (std::vector<Constraint *>::const_iterator
00138 constr=clist.begin(); constr != clist.end(); ++constr) {
00139 if ((*constr)->getTag() == tagId)
00140 constrvec.push_back(*constr);
00141 }
00142 for (std::vector<Constraint *>::const_iterator
00143 constr=constrvec.begin(); constr != constrvec.end(); ++constr) {
00144 removeConstraint(*constr);
00145 }
00146 }
00147
00148 int System::addConstraint(Constraint *constr)
00149 {
00150 clearReference();
00151
00152 clist.push_back(constr);
00153 VEC_pD constr_params = constr->params();
00154 for (VEC_pD::const_iterator param=constr_params.begin();
00155 param != constr_params.end(); ++param) {
00156
00157 c2p[constr].push_back(*param);
00158 p2c[*param].push_back(constr);
00159 }
00160 return clist.size()-1;
00161 }
00162
00163 void System::removeConstraint(Constraint *constr)
00164 {
00165 clearReference();
00166 clearSubSystems();
00167
00168 std::vector<Constraint *>::iterator it;
00169 it = std::find(clist.begin(), clist.end(), constr);
00170 clist.erase(it);
00171
00172 VEC_pD constr_params = c2p[constr];
00173 for (VEC_pD::const_iterator param=constr_params.begin();
00174 param != constr_params.end(); ++param) {
00175 std::vector<Constraint *> &constraints = p2c[*param];
00176 it = std::find(constraints.begin(), constraints.end(), constr);
00177 constraints.erase(it);
00178 }
00179 c2p.erase(constr);
00180
00181 std::vector<Constraint *> constrvec;
00182 constrvec.push_back(constr);
00183 free(constrvec);
00184 }
00185
00186
00187
00188 int System::addConstraintEqual(double *param1, double *param2, int tagId)
00189 {
00190 Constraint *constr = new ConstraintEqual(param1, param2);
00191 constr->setTag(tagId);
00192 return addConstraint(constr);
00193 }
00194
00195 int System::addConstraintDifference(double *param1, double *param2,
00196 double *difference, int tagId)
00197 {
00198 Constraint *constr = new ConstraintDifference(param1, param2, difference);
00199 constr->setTag(tagId);
00200 return addConstraint(constr);
00201 }
00202
00203 int System::addConstraintP2PDistance(Point &p1, Point &p2, double *distance, int tagId)
00204 {
00205 Constraint *constr = new ConstraintP2PDistance(p1, p2, distance);
00206 constr->setTag(tagId);
00207 return addConstraint(constr);
00208 }
00209
00210 int System::addConstraintP2PAngle(Point &p1, Point &p2, double *angle,
00211 double incr_angle, int tagId)
00212 {
00213 Constraint *constr = new ConstraintP2PAngle(p1, p2, angle, incr_angle);
00214 constr->setTag(tagId);
00215 return addConstraint(constr);
00216 }
00217
00218 int System::addConstraintP2PAngle(Point &p1, Point &p2, double *angle, int tagId)
00219 {
00220 return addConstraintP2PAngle(p1, p2, angle, 0.);
00221 }
00222
00223 int System::addConstraintP2LDistance(Point &p, Line &l, double *distance, int tagId)
00224 {
00225 Constraint *constr = new ConstraintP2LDistance(p, l, distance);
00226 constr->setTag(tagId);
00227 return addConstraint(constr);
00228 }
00229
00230 int System::addConstraintPointOnLine(Point &p, Line &l, int tagId)
00231 {
00232 Constraint *constr = new ConstraintPointOnLine(p, l);
00233 constr->setTag(tagId);
00234 return addConstraint(constr);
00235 }
00236
00237 int System::addConstraintParallel(Line &l1, Line &l2, int tagId)
00238 {
00239 Constraint *constr = new ConstraintParallel(l1, l2);
00240 constr->setTag(tagId);
00241 return addConstraint(constr);
00242 }
00243
00244 int System::addConstraintPerpendicular(Line &l1, Line &l2, int tagId)
00245 {
00246 Constraint *constr = new ConstraintPerpendicular(l1, l2);
00247 constr->setTag(tagId);
00248 return addConstraint(constr);
00249 }
00250
00251 int System::addConstraintPerpendicular(Point &l1p1, Point &l1p2,
00252 Point &l2p1, Point &l2p2, int tagId)
00253 {
00254 Constraint *constr = new ConstraintPerpendicular(l1p1, l1p2, l2p1, l2p2);
00255 constr->setTag(tagId);
00256 return addConstraint(constr);
00257 }
00258
00259 int System::addConstraintL2LAngle(Line &l1, Line &l2, double *angle, int tagId)
00260 {
00261 Constraint *constr = new ConstraintL2LAngle(l1, l2, angle);
00262 constr->setTag(tagId);
00263 return addConstraint(constr);
00264 }
00265
00266 int System::addConstraintL2LAngle(Point &l1p1, Point &l1p2,
00267 Point &l2p1, Point &l2p2, double *angle, int tagId)
00268 {
00269 Constraint *constr = new ConstraintL2LAngle(l1p1, l1p2, l2p1, l2p2, angle);
00270 constr->setTag(tagId);
00271 return addConstraint(constr);
00272 }
00273
00274 int System::addConstraintMidpointOnLine(Line &l1, Line &l2, int tagId)
00275 {
00276 Constraint *constr = new ConstraintMidpointOnLine(l1, l2);
00277 constr->setTag(tagId);
00278 return addConstraint(constr);
00279 }
00280
00281 int System::addConstraintMidpointOnLine(Point &l1p1, Point &l1p2,
00282 Point &l2p1, Point &l2p2, int tagId)
00283 {
00284 Constraint *constr = new ConstraintMidpointOnLine(l1p1, l1p2, l2p1, l2p2);
00285 constr->setTag(tagId);
00286 return addConstraint(constr);
00287 }
00288
00289
00290
00291 int System::addConstraintP2PCoincident(Point &p1, Point &p2, int tagId)
00292 {
00293 addConstraintEqual(p1.x, p2.x, tagId);
00294 return addConstraintEqual(p1.y, p2.y, tagId);
00295 }
00296
00297 int System::addConstraintHorizontal(Line &l, int tagId)
00298 {
00299 return addConstraintEqual(l.p1.y, l.p2.y, tagId);
00300 }
00301
00302 int System::addConstraintHorizontal(Point &p1, Point &p2, int tagId)
00303 {
00304 return addConstraintEqual(p1.y, p2.y, tagId);
00305 }
00306
00307 int System::addConstraintVertical(Line &l, int tagId)
00308 {
00309 return addConstraintEqual(l.p1.x, l.p2.x, tagId);
00310 }
00311
00312 int System::addConstraintVertical(Point &p1, Point &p2, int tagId)
00313 {
00314 return addConstraintEqual(p1.x, p2.x, tagId);
00315 }
00316
00317 int System::addConstraintCoordinateX(Point &p, double *x, int tagId)
00318 {
00319 return addConstraintEqual(p.x, x, tagId);
00320 }
00321
00322 int System::addConstraintCoordinateY(Point &p, double *y, int tagId)
00323 {
00324 return addConstraintEqual(p.y, y, tagId);
00325 }
00326
00327 int System::addConstraintArcRules(Arc &a, int tagId)
00328 {
00329 addConstraintP2PAngle(a.center, a.start, a.startAngle, tagId);
00330 addConstraintP2PAngle(a.center, a.end, a.endAngle, tagId);
00331 addConstraintP2PDistance(a.center, a.start, a.rad, tagId);
00332 return addConstraintP2PDistance(a.center, a.end, a.rad, tagId);
00333 }
00334
00335 int System::addConstraintPointOnCircle(Point &p, Circle &c, int tagId)
00336 {
00337 return addConstraintP2PDistance(p, c.center, c.rad, tagId);
00338 }
00339
00340 int System::addConstraintPointOnArc(Point &p, Arc &a, int tagId)
00341 {
00342 return addConstraintP2PDistance(p, a.center, a.rad, tagId);
00343 }
00344
00345 int System::addConstraintTangent(Line &l, Circle &c, int tagId)
00346 {
00347 return addConstraintP2LDistance(c.center, l, c.rad, tagId);
00348 }
00349
00350 int System::addConstraintTangent(Line &l, Arc &a, int tagId)
00351 {
00352 return addConstraintP2LDistance(a.center, l, a.rad, tagId);
00353 }
00354
00355 int System::addConstraintTangentLine2Arc(Point &p1, Point &p2, Arc &a, int tagId)
00356 {
00357 addConstraintP2PCoincident(p2, a.start, tagId);
00358 double incr_angle = *(a.startAngle) < *(a.endAngle) ? M_PI/2 : -M_PI/2;
00359 return addConstraintP2PAngle(p1, p2, a.startAngle, incr_angle, tagId);
00360 }
00361
00362 int System::addConstraintTangentArc2Line(Arc &a, Point &p1, Point &p2, int tagId)
00363 {
00364 addConstraintP2PCoincident(p1, a.end, tagId);
00365 double incr_angle = *(a.startAngle) < *(a.endAngle) ? M_PI/2 : -M_PI/2;
00366 return addConstraintP2PAngle(p1, p2, a.endAngle, incr_angle, tagId);
00367 }
00368
00369 int System::addConstraintCircleRadius(Circle &c, double *radius, int tagId)
00370 {
00371 return addConstraintEqual(c.rad, radius, tagId);
00372 }
00373
00374 int System::addConstraintArcRadius(Arc &a, double *radius, int tagId)
00375 {
00376 return addConstraintEqual(a.rad, radius, tagId);
00377 }
00378
00379 int System::addConstraintEqualLength(Line &l1, Line &l2, double *length, int tagId)
00380 {
00381 addConstraintP2PDistance(l1.p1, l1.p2, length, tagId);
00382 return addConstraintP2PDistance(l2.p1, l2.p2, length, tagId);
00383 }
00384
00385 int System::addConstraintEqualRadius(Circle &c1, Circle &c2, int tagId)
00386 {
00387 return addConstraintEqual(c1.rad, c2.rad, tagId);
00388 }
00389
00390 int System::addConstraintEqualRadius(Circle &c1, Arc &a2, int tagId)
00391 {
00392 return addConstraintEqual(c1.rad, a2.rad, tagId);
00393 }
00394
00395 int System::addConstraintEqualRadius(Arc &a1, Arc &a2, int tagId)
00396 {
00397 return addConstraintEqual(a1.rad, a2.rad, tagId);
00398 }
00399
00400 int System::addConstraintP2PSymmetric(Point &p1, Point &p2, Line &l, int tagId)
00401 {
00402 addConstraintPerpendicular(p1, p2, l.p1, l.p2, tagId);
00403 return addConstraintMidpointOnLine(p1, p2, l.p1, l.p2, tagId);
00404 }
00405
00406 void System::rescaleConstraint(int id, double coeff)
00407 {
00408 if (id >= clist.size() || id < 0)
00409 return;
00410 if (clist[id])
00411 clist[id]->rescale(coeff);
00412 }
00413
00414
00415 void System::initSolution(VEC_pD ¶ms)
00416 {
00417
00418
00419
00420
00421
00422
00423
00424 clearReference();
00425 for (VEC_pD::const_iterator param=params.begin();
00426 param != params.end(); ++param)
00427 reference[*param] = **param;
00428
00429
00430 std::set<Constraint *> eliminated;
00431 reductionmap.clear();
00432 {
00433 VEC_pD reduced_params=params;
00434 MAP_pD_I params_index;
00435 for (int i=0; i < int(params.size()); ++i)
00436 params_index[params[i]] = i;
00437
00438 for (std::vector<Constraint *>::const_iterator constr=clist.begin();
00439 constr != clist.end(); ++constr) {
00440 if ((*constr)->getTag() >= 0 && (*constr)->getTypeId() == Equal) {
00441 MAP_pD_I::const_iterator it1,it2;
00442 it1 = params_index.find((*constr)->params()[0]);
00443 it2 = params_index.find((*constr)->params()[1]);
00444 if (it1 != params_index.end() && it2 != params_index.end()) {
00445 eliminated.insert(*constr);
00446 double *p_kept = reduced_params[it1->second];
00447 double *p_replaced = reduced_params[it2->second];
00448 for (int i=0; i < int(params.size()); ++i)
00449 if (reduced_params[i] == p_replaced)
00450 reduced_params[i] = p_kept;
00451 }
00452 }
00453 }
00454 for (int i=0; i < int(params.size()); ++i)
00455 if (params[i] != reduced_params[i])
00456 reductionmap[params[i]] = reduced_params[i];
00457 }
00458
00459 int i=0;
00460 std::vector<Constraint *> clist0, clist1, clist2;
00461 for (std::vector<Constraint *>::const_iterator constr=clist.begin();
00462 constr != clist.end(); ++constr, i++) {
00463 if (eliminated.count(*constr) == 0) {
00464 if ((*constr)->getTag() >= 0)
00465 clist0.push_back(*constr);
00466 else if ((*constr)->getTag() == -1)
00467 clist1.push_back(*constr);
00468 else
00469 clist2.push_back(*constr);
00470 }
00471 }
00472
00473 clearSubSystems();
00474 if (clist0.size() > 0)
00475 subsys0 = new SubSystem(clist0, params, reductionmap);
00476 if (clist1.size() > 0)
00477 subsys1 = new SubSystem(clist1, params, reductionmap);
00478 if (clist2.size() > 0)
00479 subsys2 = new SubSystem(clist2, params, reductionmap);
00480 init = true;
00481 }
00482
00483 void System::clearReference()
00484 {
00485 init = false;
00486 reference.clear();
00487 }
00488
00489 void System::resetToReference()
00490 {
00491 for (MAP_pD_D::const_iterator it=reference.begin();
00492 it != reference.end(); ++it)
00493 *(it->first) = it->second;
00494 }
00495
00496 int System::solve(VEC_pD ¶ms, bool isFine, Algorithm alg)
00497 {
00498 initSolution(params);
00499 return solve(isFine, alg);
00500 }
00501
00502 int System::solve(bool isFine, Algorithm alg)
00503 {
00504 if (subsys0) {
00505 resetToReference();
00506 if (subsys2) {
00507 int ret = solve(subsys0, subsys2, isFine);
00508 if (subsys1)
00509
00510 return solve(subsys0, subsys1, isFine);
00511 else
00512 return ret;
00513 }
00514 else if (subsys1)
00515 return solve(subsys0, subsys1, isFine);
00516 else
00517 return solve(subsys0, isFine, alg);
00518 }
00519 else if (subsys1) {
00520 resetToReference();
00521 if (subsys2)
00522 return solve(subsys1, subsys2, isFine);
00523 else
00524 return solve(subsys1, isFine, alg);
00525 }
00526 else
00527
00528 return Success;
00529 }
00530
00531 int System::solve(SubSystem *subsys, bool isFine, Algorithm alg)
00532 {
00533 if (alg == BFGS)
00534 return solve_BFGS(subsys, isFine);
00535 else if (alg == LevenbergMarquardt)
00536 return solve_LM(subsys);
00537 else if (alg == DogLeg)
00538 return solve_DL(subsys);
00539 }
00540
00541 int System::solve_BFGS(SubSystem *subsys, bool isFine)
00542 {
00543 int xsize = subsys->pSize();
00544 if (xsize == 0)
00545 return Success;
00546
00547 subsys->redirectParams();
00548
00549 Eigen::MatrixXd D = Eigen::MatrixXd::Identity(xsize, xsize);
00550 Eigen::VectorXd x(xsize);
00551 Eigen::VectorXd xdir(xsize);
00552 Eigen::VectorXd grad(xsize);
00553 Eigen::VectorXd h(xsize);
00554 Eigen::VectorXd y(xsize);
00555 Eigen::VectorXd Dy(xsize);
00556
00557
00558 subsys->getParams(x);
00559 subsys->calcGrad(grad);
00560
00561
00562 xdir = -grad;
00563 lineSearch(subsys, xdir);
00564 double err = subsys->error();
00565
00566 h = x;
00567 subsys->getParams(x);
00568 h = x - h;
00569
00570 double convergence = isFine ? XconvergenceFine : XconvergenceRough;
00571 int maxIterNumber = MaxIterations * xsize;
00572 double diverging_lim = 1e6*err + 1e12;
00573
00574 for (int iter=1; iter < maxIterNumber; iter++) {
00575
00576 if (h.norm() <= convergence || err <= smallF)
00577 break;
00578 if (err > diverging_lim || err != err)
00579 break;
00580
00581 y = grad;
00582 subsys->calcGrad(grad);
00583 y = grad - y;
00584
00585 double hty = h.dot(y);
00586
00587 if (hty == 0)
00588 hty = .0000000001;
00589
00590 Dy = D * y;
00591
00592 double ytDy = y.dot(Dy);
00593
00594
00595 D += (1.+ytDy/hty)/hty * h * h.transpose();
00596 D -= 1./hty * (h * Dy.transpose() + Dy * h.transpose());
00597
00598 xdir = -D * grad;
00599 lineSearch(subsys, xdir);
00600 err = subsys->error();
00601
00602 h = x;
00603 subsys->getParams(x);
00604 h = x - h;
00605 }
00606
00607 subsys->revertParams();
00608
00609 if (err <= smallF)
00610 return Success;
00611 if (h.norm() <= convergence)
00612 return Converged;
00613 return Failed;
00614 }
00615
00616 int System::solve_LM(SubSystem* subsys)
00617 {
00618 int xsize = subsys->pSize();
00619 int csize = subsys->cSize();
00620
00621 if (xsize == 0)
00622 return Success;
00623
00624 Eigen::VectorXd e(csize), e_new(csize);
00625 Eigen::MatrixXd J(csize, xsize);
00626 Eigen::MatrixXd A(xsize, xsize);
00627 Eigen::VectorXd x(xsize), h(xsize), x_new(xsize), g(xsize), diag_A(xsize);
00628
00629 subsys->redirectParams();
00630
00631 subsys->getParams(x);
00632 subsys->calcResidual(e);
00633 e*=-1;
00634
00635 int maxIterNumber = MaxIterations * xsize;
00636 double diverging_lim = 1e6*e.squaredNorm() + 1e12;
00637
00638 double eps=1e-10, eps1=1e-80;
00639 double tau=1e-3;
00640 double nu=2, mu=0;
00641 int iter=0, stop=0;
00642 for (iter=0; iter < maxIterNumber && !stop; ++iter) {
00643
00644
00645 double err=e.squaredNorm();
00646 if (err <= eps) {
00647 stop = 1;
00648 break;
00649 }
00650 else if (err > diverging_lim || err != err) {
00651 stop = 6;
00652 break;
00653 }
00654
00655
00656 subsys->calcJacobi(J);;
00657
00658 A = J.transpose()*J;
00659 g = J.transpose()*e;
00660
00661
00662 double g_inf = g.lpNorm<Eigen::Infinity>();
00663 diag_A = A.diagonal();
00664
00665
00666 if (g_inf <= eps1) {
00667 stop = 2;
00668 break;
00669 }
00670
00671
00672 if (iter == 0)
00673 mu = tau * A.diagonal().lpNorm<Eigen::Infinity>();
00674
00675
00676 int k=0;
00677 while (k < 50) {
00678
00679 for (int i=0; i < xsize; ++i)
00680 A(i,i) += mu;
00681
00682
00683 h = A.fullPivLu().solve(g);
00684 double rel_error = (A*h - g).norm() / g.norm();
00685
00686
00687 if (rel_error < 1e-5) {
00688
00689
00690 x_new = x + h;
00691 double h_norm = h.squaredNorm();
00692
00693 if (h_norm <= eps1*eps1*x.norm()) {
00694 stop = 3;
00695 break;
00696 }
00697 else if (h_norm >= (x.norm()+eps1)/(DBL_EPSILON*DBL_EPSILON)) {
00698 stop = 4;
00699 break;
00700 }
00701
00702 subsys->setParams(x_new);
00703 subsys->calcResidual(e_new);
00704 e_new *= -1;
00705
00706 double dF = e.squaredNorm() - e_new.squaredNorm();
00707 double dL = h.dot(mu*h+g);
00708
00709 if (dF>0. && dL>0.) {
00710 double tmp=2*dF/dL-1.;
00711 mu *= std::max(1./3., 1.-tmp*tmp*tmp);
00712 nu=2;
00713
00714
00715 x = x_new;
00716 e = e_new;
00717 break;
00718 }
00719 }
00720
00721
00722
00723
00724 mu*=nu;
00725 nu*=2.0;
00726 for (int i=0; i < xsize; ++i)
00727 A(i,i) = diag_A(i);
00728
00729 k++;
00730 }
00731 if (k > 50) {
00732 stop = 7;
00733 break;
00734 }
00735 }
00736
00737 if (iter >= maxIterNumber)
00738 stop = 5;
00739
00740 subsys->revertParams();
00741
00742 return (stop == 1) ? Success : Failed;
00743 }
00744
00745
00746 int System::solve_DL(SubSystem* subsys)
00747 {
00748 double tolg=1e-80, tolx=1e-80, tolf=1e-10;
00749
00750 int xsize = subsys->pSize();
00751 int csize = subsys->cSize();
00752
00753 Eigen::VectorXd x(xsize), x_new(xsize);
00754 Eigen::VectorXd fx(csize), fx_new(csize);
00755 Eigen::MatrixXd Jx(csize, xsize), Jx_new(csize, xsize);
00756 Eigen::VectorXd g(xsize), h_sd(xsize), h_gn(xsize), h_dl(xsize);
00757
00758 subsys->redirectParams();
00759
00760 double err;
00761 subsys->getParams(x);
00762 subsys->calcResidual(fx, err);
00763 subsys->calcJacobi(Jx);
00764
00765 g = Jx.transpose()*(-fx);
00766
00767
00768 double g_inf = g.lpNorm<Eigen::Infinity>();
00769 double fx_inf = fx.lpNorm<Eigen::Infinity>();
00770
00771 int maxIterNumber = MaxIterations * xsize;
00772 double diverging_lim = 1e6*err + 1e12;
00773
00774 double delta=0.1;
00775 double alpha=0.;
00776 double nu=2.;
00777 int iter=0, stop=0, reduce=0;
00778 while (!stop) {
00779
00780
00781 if (fx_inf <= tolf)
00782 stop = 1;
00783 else if (g_inf <= tolg)
00784 stop = 2;
00785 else if (delta <= tolx*(tolx + x.norm()))
00786 stop = 2;
00787 else if (iter >= maxIterNumber)
00788 stop = 4;
00789 else if (err > diverging_lim || err != err) {
00790 stop = 6;
00791 }
00792 else {
00793
00794 alpha = g.squaredNorm()/(Jx*g).squaredNorm();
00795 h_sd = alpha*g;
00796
00797
00798 h_gn = Jx.fullPivLu().solve(-fx);
00799 double rel_error = (Jx*h_gn + fx).norm() / fx.norm();
00800 if (rel_error > 1e15)
00801 break;
00802
00803
00804 if (h_gn.norm() < delta) {
00805 h_dl = h_gn;
00806 if (h_dl.norm() <= tolx*(tolx + x.norm())) {
00807 stop = 5;
00808 break;
00809 }
00810 }
00811 else if (alpha*g.norm() >= delta) {
00812 h_dl = (delta/(alpha*g.norm()))*h_sd;
00813 }
00814 else {
00815
00816 double beta = 0;
00817 Eigen::VectorXd b = h_gn - h_sd;
00818 double bb = (b.transpose()*b).norm();
00819 double gb = (h_sd.transpose()*b).norm();
00820 double c = (delta + h_sd.norm())*(delta - h_sd.norm());
00821
00822 if (gb > 0)
00823 beta = c / (gb + sqrt(gb * gb + c * bb));
00824 else
00825 beta = (sqrt(gb * gb + c * bb) - gb)/bb;
00826
00827
00828 h_dl = h_sd + beta*b;
00829 }
00830 }
00831
00832
00833 if (stop)
00834 break;
00835
00836
00837 double err_new;
00838 x_new = x + h_dl;
00839 subsys->setParams(x_new);
00840 subsys->calcResidual(fx_new, err_new);
00841 subsys->calcJacobi(Jx_new);
00842
00843
00844 double dL = err - 0.5*(fx + Jx*h_dl).squaredNorm();
00845 double dF = err - err_new;
00846 double rho = dL/dF;
00847
00848 if (dF > 0 && dL > 0) {
00849 x = x_new;
00850 Jx = Jx_new;
00851 fx = fx_new;
00852 err = err_new;
00853
00854 g = Jx.transpose()*(-fx);
00855
00856
00857 g_inf = g.lpNorm<Eigen::Infinity>();
00858 fx_inf = fx.lpNorm<Eigen::Infinity>();
00859 }
00860 else
00861 rho = -1;
00862
00863
00864 if (fabs(rho-1.) < 0.2 && h_dl.norm() > delta/3. && reduce <= 0) {
00865 delta = 3*delta;
00866 nu = 2;
00867 reduce = 0;
00868 }
00869 else if (rho < 0.25) {
00870 delta = delta/nu;
00871 nu = 2*nu;
00872 reduce = 2;
00873 }
00874 else
00875 reduce--;
00876
00877
00878 iter++;
00879 }
00880
00881 subsys->revertParams();
00882
00883 return (stop == 1) ? Success : Failed;
00884 }
00885
00886
00887
00888 int System::solve(SubSystem *subsysA, SubSystem *subsysB, bool isFine)
00889 {
00890 int xsizeA = subsysA->pSize();
00891 int xsizeB = subsysB->pSize();
00892 int csizeA = subsysA->cSize();
00893
00894 VEC_pD plist(xsizeA+xsizeB);
00895 {
00896 VEC_pD plistA, plistB;
00897 subsysA->getParamList(plistA);
00898 subsysB->getParamList(plistB);
00899
00900 std::sort(plistA.begin(),plistA.end());
00901 std::sort(plistB.begin(),plistB.end());
00902
00903 VEC_pD::const_iterator it;
00904 it = std::set_union(plistA.begin(),plistA.end(),
00905 plistB.begin(),plistB.end(),plist.begin());
00906 plist.resize(it-plist.begin());
00907 }
00908 int xsize = plist.size();
00909
00910 Eigen::MatrixXd B = Eigen::MatrixXd::Identity(xsize, xsize);
00911 Eigen::MatrixXd JA(csizeA, xsize);
00912 Eigen::MatrixXd Y,Z;
00913
00914 Eigen::VectorXd resA(csizeA);
00915 Eigen::VectorXd lambda(csizeA), lambda0(csizeA), lambdadir(csizeA);
00916 Eigen::VectorXd x(xsize), x0(xsize), xdir(xsize), xdir1(xsize);
00917 Eigen::VectorXd grad(xsize);
00918 Eigen::VectorXd h(xsize);
00919 Eigen::VectorXd y(xsize);
00920 Eigen::VectorXd Bh(xsize);
00921
00922
00923 subsysA->redirectParams();
00924 subsysB->redirectParams();
00925
00926 subsysB->getParams(plist,x);
00927 subsysA->getParams(plist,x);
00928 subsysB->setParams(plist,x);
00929
00930 subsysB->calcGrad(plist,grad);
00931 subsysA->calcJacobi(plist,JA);
00932 subsysA->calcResidual(resA);
00933
00934 double convergence = isFine ? XconvergenceFine : XconvergenceRough;
00935 int maxIterNumber = MaxIterations * xsize;
00936 double diverging_lim = 1e6*subsysA->error() + 1e12;
00937
00938 double mu = 0;
00939 lambda.setZero();
00940 for (int iter=1; iter < maxIterNumber; iter++) {
00941 int status = qp_eq(B, grad, JA, resA, xdir, Y, Z);
00942 if (status)
00943 break;
00944
00945 x0 = x;
00946 lambda0 = lambda;
00947 lambda = Y.transpose() * (B * xdir + grad);
00948 lambdadir = lambda - lambda0;
00949
00950
00951 {
00952 double eta=0.25;
00953 double tau=0.5;
00954 double rho=0.5;
00955 double alpha=1;
00956 alpha = std::min(alpha, subsysA->maxStep(plist,xdir));
00957
00958
00959
00960
00961
00962
00963 mu = std::max(mu,
00964 (grad.dot(xdir) + std::max(0., 0.5*xdir.dot(B*xdir))) /
00965 ( (1. - rho) * resA.lpNorm<1>() ) );
00966
00967
00968 double f0 = subsysB->error() + mu * resA.lpNorm<1>();
00969
00970
00971 double deriv = grad.dot(xdir) - mu * resA.lpNorm<1>();
00972
00973 x = x0 + alpha * xdir;
00974 subsysA->setParams(plist,x);
00975 subsysB->setParams(plist,x);
00976 subsysA->calcResidual(resA);
00977 double f = subsysB->error() + mu * resA.lpNorm<1>();
00978
00979
00980 bool first = true;
00981 while (f > f0 + eta * alpha * deriv) {
00982 if (first) {
00983
00984
00985 xdir1 = -Y*resA;
00986 x += xdir1;
00987 subsysA->setParams(plist,x);
00988 subsysB->setParams(plist,x);
00989 subsysA->calcResidual(resA);
00990 f = subsysB->error() + mu * resA.lpNorm<1>();
00991 if (f < f0 + eta * alpha * deriv)
00992 break;
00993 }
00994 alpha = tau * alpha;
00995 if (alpha < 1e-8)
00996 alpha = 0.;
00997 x = x0 + alpha * xdir;
00998 subsysA->setParams(plist,x);
00999 subsysB->setParams(plist,x);
01000 subsysA->calcResidual(resA);
01001 f = subsysB->error() + mu * resA.lpNorm<1>();
01002 if (alpha < 1e-8)
01003 break;
01004 }
01005 lambda = lambda0 + alpha * lambdadir;
01006
01007 }
01008 h = x - x0;
01009
01010 y = grad - JA.transpose() * lambda;
01011 {
01012 subsysB->calcGrad(plist,grad);
01013 subsysA->calcJacobi(plist,JA);
01014 subsysA->calcResidual(resA);
01015 }
01016 y = grad - JA.transpose() * lambda - y;
01017
01018 if (iter > 1) {
01019 double yTh = y.dot(h);
01020 if (yTh != 0) {
01021 Bh = B * h;
01022
01023 B += 1./yTh * y * y.transpose();
01024 B -= 1./h.dot(Bh) * (Bh * Bh.transpose());
01025 }
01026 }
01027
01028 double err = subsysA->error();
01029 if (h.norm() <= convergence && err <= smallF)
01030 break;
01031 if (err > diverging_lim || err != err)
01032 break;
01033 }
01034
01035 int ret;
01036 if (subsysA->error() <= smallF)
01037 ret = Success;
01038 else if (h.norm() <= convergence)
01039 ret = Converged;
01040 else
01041 ret = Failed;
01042
01043 subsysA->revertParams();
01044 subsysB->revertParams();
01045 return ret;
01046
01047 }
01048
01049 void System::getSubSystems(std::vector<SubSystem *> &subsysvec)
01050 {
01051 subsysvec.clear();
01052 if (subsys0)
01053 subsysvec.push_back(subsys0);
01054 if (subsys1)
01055 subsysvec.push_back(subsys1);
01056 if (subsys2)
01057 subsysvec.push_back(subsys2);
01058 }
01059
01060 void System::applySolution()
01061 {
01062 if (subsys2)
01063 subsys2->applySolution();
01064 if (subsys1)
01065 subsys1->applySolution();
01066 if (subsys0)
01067 subsys0->applySolution();
01068
01069 for (MAP_pD_pD::const_iterator it=reductionmap.begin();
01070 it != reductionmap.end(); ++it)
01071 *(it->first) = *(it->second);
01072 }
01073
01074 void System::undoSolution()
01075 {
01076 resetToReference();
01077 }
01078
01079 int System::diagnose(VEC_pD ¶ms, VEC_I &conflicting)
01080 {
01081
01082
01083 conflicting.clear();
01084 std::vector<VEC_I> conflictingIndex;
01085 VEC_I tags;
01086 Eigen::MatrixXd J(clist.size(), params.size());
01087 int count=0;
01088 for (std::vector<Constraint *>::iterator constr=clist.begin();
01089 constr != clist.end(); ++constr) {
01090 (*constr)->revertParams();
01091 if ((*constr)->getTag() >= 0) {
01092 count++;
01093 tags.push_back((*constr)->getTag());
01094 for (int j=0; j < int(params.size()); j++)
01095 J(count-1,j) = (*constr)->grad(params[j]);
01096 }
01097 }
01098
01099 if (J.rows() > 0) {
01100 Eigen::FullPivHouseholderQR<Eigen::MatrixXd> qrJT(J.topRows(count).transpose());
01101 Eigen::MatrixXd Q = qrJT.matrixQ ();
01102 int params_num = qrJT.rows();
01103 int constr_num = qrJT.cols();
01104 int rank = qrJT.rank();
01105
01106 Eigen::MatrixXd R;
01107 if (constr_num >= params_num)
01108 R = qrJT.matrixQR().triangularView<Eigen::Upper>();
01109 else
01110 R = qrJT.matrixQR().topRows(constr_num)
01111 .triangularView<Eigen::Upper>();
01112
01113 if (constr_num > rank) {
01114 for (int i=1; i < rank; i++) {
01115
01116 assert(R(i,i) != 0);
01117 for (int row=0; row < i; row++) {
01118 if (R(row,i) != 0) {
01119 double coef=R(row,i)/R(i,i);
01120 R.block(row,i+1,1,constr_num-i-1) -= coef * R.block(i,i+1,1,constr_num-i-1);
01121 R(row,i) = 0;
01122 }
01123 }
01124 }
01125 conflictingIndex.resize(constr_num-rank);
01126 for (int j=rank; j < constr_num; j++) {
01127 for (int row=0; row < rank; row++) {
01128 if (R(row,j) != 0) {
01129 int orig_col = qrJT.colsPermutation().indices()[row];
01130 conflictingIndex[j-rank].push_back(orig_col);
01131 }
01132 }
01133 int orig_col = qrJT.colsPermutation().indices()[j];
01134 conflictingIndex[j-rank].push_back(orig_col);
01135 }
01136
01137 SET_I tags_set;
01138 for (int i=0; i < conflictingIndex.size(); i++) {
01139 for (int j=0; j < conflictingIndex[i].size(); j++) {
01140 tags_set.insert(tags[conflictingIndex[i][j]]);
01141 }
01142 }
01143 tags_set.erase(0);
01144 conflicting.resize(tags_set.size());
01145 std::copy(tags_set.begin(), tags_set.end(), conflicting.begin());
01146
01147 if (params_num == rank)
01148 return params_num - constr_num;
01149 }
01150
01151 return params_num - rank;
01152 }
01153 return params.size();
01154 }
01155
01156 void System::clearSubSystems()
01157 {
01158 init = false;
01159 std::vector<SubSystem *> subsystems;
01160 getSubSystems(subsystems);
01161 free(subsystems);
01162 subsys0 = NULL;
01163 subsys1 = NULL;
01164 subsys2 = NULL;
01165 }
01166
01167 double lineSearch(SubSystem *subsys, Eigen::VectorXd &xdir)
01168 {
01169 double f1,f2,f3,alpha1,alpha2,alpha3,alphaStar;
01170
01171 double alphaMax = subsys->maxStep(xdir);
01172
01173 Eigen::VectorXd x0, x;
01174
01175
01176 subsys->getParams(x0);
01177
01178
01179 alpha1 = 0.;
01180 f1 = subsys->error();
01181
01182
01183 alpha2 = 1.;
01184 x = x0 + alpha2 * xdir;
01185 subsys->setParams(x);
01186 f2 = subsys->error();
01187
01188
01189 alpha3 = alpha2*2;
01190 x = x0 + alpha3 * xdir;
01191 subsys->setParams(x);
01192 f3 = subsys->error();
01193
01194
01195
01196 while (f2 > f1 || f2 > f3) {
01197 if (f2 > f1) {
01198
01199
01200 alpha3 = alpha2;
01201 f3 = f2;
01202 alpha2 = alpha2 / 2;
01203 x = x0 + alpha2 * xdir;
01204 subsys->setParams(x);
01205 f2 = subsys->error();
01206 }
01207 else if (f2 > f3) {
01208 if (alpha3 >= alphaMax)
01209 break;
01210
01211
01212 alpha2 = alpha3;
01213 f2 = f3;
01214 alpha3 = alpha3 * 2;
01215 x = x0 + alpha3 * xdir;
01216 subsys->setParams(x);
01217 f3 = subsys->error();
01218 }
01219 }
01220
01221 alphaStar = alpha2 + ((alpha2-alpha1)*(f1-f3))/(3*(f1-2*f2+f3));
01222
01223
01224 if (alphaStar >= alpha3 || alphaStar <= alpha1)
01225 alphaStar = alpha2;
01226
01227 if (alphaStar > alphaMax)
01228 alphaStar = alphaMax;
01229
01230 if (alphaStar != alphaStar)
01231 alphaStar = 0.;
01232
01233
01234 x = x0 + alphaStar * xdir;
01235 subsys->setParams(x);
01236
01237 return alphaStar;
01238 }
01239
01240
01241 void free(VEC_pD &doublevec)
01242 {
01243 for (VEC_pD::iterator it = doublevec.begin();
01244 it != doublevec.end(); ++it)
01245 if (*it) delete *it;
01246 doublevec.clear();
01247 }
01248
01249 void free(std::vector<Constraint *> &constrvec)
01250 {
01251 for (std::vector<Constraint *>::iterator constr=constrvec.begin();
01252 constr != constrvec.end(); ++constr) {
01253 if (*constr) {
01254 switch ((*constr)->getTypeId()) {
01255 case Equal:
01256 delete static_cast<ConstraintEqual *>(*constr);
01257 break;
01258 case Difference:
01259 delete static_cast<ConstraintDifference *>(*constr);
01260 break;
01261 case P2PDistance:
01262 delete static_cast<ConstraintP2PDistance *>(*constr);
01263 break;
01264 case P2PAngle:
01265 delete static_cast<ConstraintP2PAngle *>(*constr);
01266 break;
01267 case P2LDistance:
01268 delete static_cast<ConstraintP2LDistance *>(*constr);
01269 break;
01270 case PointOnLine:
01271 delete static_cast<ConstraintPointOnLine *>(*constr);
01272 break;
01273 case Parallel:
01274 delete static_cast<ConstraintParallel *>(*constr);
01275 break;
01276 case Perpendicular:
01277 delete static_cast<ConstraintPerpendicular *>(*constr);
01278 break;
01279 case L2LAngle:
01280 delete static_cast<ConstraintL2LAngle *>(*constr);
01281 break;
01282 case MidpointOnLine:
01283 delete static_cast<ConstraintMidpointOnLine *>(*constr);
01284 break;
01285 case None:
01286 default:
01287 delete *constr;
01288 }
01289 }
01290 }
01291 constrvec.clear();
01292 }
01293
01294 void free(std::vector<SubSystem *> &subsysvec)
01295 {
01296 for (std::vector<SubSystem *>::iterator it=subsysvec.begin();
01297 it != subsysvec.end(); ++it)
01298 if (*it) delete *it;
01299 }
01300
01301
01302 }