1430 const double sqrtEps = sqrt(std::numeric_limits<double>::epsilon());
1432 dbg<<
"Start Solve_Hybrid\n";
1443 xdbg<<
"x = "<<
x.transpose()<<std::endl;
1445 xdbg<<
"f = "<<f.transpose()<<std::endl;
1446 double normInfF = f.TMV_normInf();
1448 double Q = 0.5*f.TMV_normSq();
1449 xdbg<<
"Q = "<<Q<<std::endl;
1451 xdbg<<
"J = "<<J<<std::endl;
1454 xdbg<<
"A = "<<A<<std::endl;
1456 xdbg<<
"setToIdent\n";
1457 H.TMV_setToIdentity();
1458 xdbg<<
"After calculate H = "<<H<<std::endl;
1460 DVector g = J.transpose() * f;
1461 xdbg<<
"g = "<<g.transpose()<<std::endl;
1462 double normInfG = g.TMV_normInf();
1465 double mu =
_tau * A.TMV_diag().TMV_normInf();
1466 A.EIGEN_diag() += mu;
1469 bool shouldUseQuasiNewton =
false;
1472 dbg<<
"iter |f|inf Q |g|inf mu delta LM/QN\n";
1474 dbg<<k<<
" "<<normInfF<<
" "<<Q<<
" "<<normInfG<<
" "<< mu<<
" "<<
1475 delta<<
" "<<(shouldUseQuasiNewton?
"QN":
"LM")<<std::endl;
1476 xdbg<<
"k = "<<k<<std::endl;
1477 xdbg<<
"mu = "<<mu<<std::endl;
1478 xdbg<<
"delta = "<<delta<<std::endl;
1479 xdbg<<
"A = "<<A<<std::endl;
1480 xdbg<<
"H = "<<H<<std::endl;
1481 xdbg<<
"method = "<<(shouldUseQuasiNewton ?
"quasinewton\n" :
"LM\n");
1482 bool isBetter =
false;
1483 bool shouldSwitchMethod =
false;
1485 if (shouldUseQuasiNewton) {
1487 h = H.ldlt().solve(-g);
1490 h = A.ldlt().solve(-g);
1493 xdbg<<
"h = "<<h.transpose()<<std::endl;
1494 double normH = h.norm();
1496 if (shouldUseQuasiNewton && normH > delta) h *= delta/normH;
1499 xdbg<<
"xnew = "<<xNew.transpose()<<std::endl;
1501 xdbg<<
"fnew = "<<fNew.transpose()<<std::endl;
1502 double QNew = 0.5*fNew.TMV_normSq();
1503 xdbg<<
"Qnew = "<<QNew<<std::endl;
1506 xdbg<<
"Jnew = "<<JNew<<std::endl;
1507 if (shouldUseQuasiNewton || QNew < Q) {
1508 gNew = JNew.transpose() * fNew;
1509 xdbg<<
"gnew = "<<gNew.transpose()<<std::endl;
1511 double normInfGNew = gNew.TMV_normInf();
1513 if (shouldUseQuasiNewton) {
1514 xdbg<<
"quasinewton\n";
1517 (QNew <= (1.+sqrtEps)*Q && normInfGNew < normInfG);
1518 xdbg<<
"better = "<<isBetter<<std::endl;
1519 shouldSwitchMethod = (normInfGNew >= normInfG);
1520 xdbg<<
"switchmethod = "<<shouldSwitchMethod<<std::endl;
1522 double rho = (Q-QNew) / (-(h.transpose()*g)(0,0)-0.5*(J*h).
TMV_normSq());
1524 delta = std::max(delta,3.*normH);
1525 }
else if (rho < 0.25) {
1528 if (delta < min_delta) {
1529 dbg<<
"delta became too small ("<<
1530 delta<<
" < "<<min_delta<<
")\n";
1538 if (delta < min_delta) {
1539 dbg<<
"delta became too small ("<<
1540 delta<<
" < "<<min_delta<<
")\n";
1553 double rho = (Q-QNew) / (-0.5*(h.transpose()*g)(0,0));
1554 mu *= std::max(1./3.,1.-std::pow(2.*rho-1.,3)); nu = 2.;
1555 xdbg<<
"check1: "<<normInfGNew<<
" <? "<<0.02*QNew<<std::endl;
1556 xdbg<<
"check2: "<<Q-QNew<<
" <? "<<0.02*QNew<<std::endl;
1557 if (std::min(normInfGNew,Q-QNew) < 0.02 * QNew) {
1559 if (count == 3) shouldSwitchMethod =
true;
1564 A = JNew.transpose() * JNew;
1565 A.EIGEN_diag() += mu;
1568 A.EIGEN_diag() += mu*(nu-1.); mu *= nu; nu *= 2.;
1571 shouldSwitchMethod = (nu >= 32.);
1573 xdbg<<
"better = "<<isBetter<<std::endl;
1574 xdbg<<
"switchmethod = "<<shouldSwitchMethod<<std::endl;
1575 xdbg<<
"count = "<<count<<std::endl;
1578 y = JNew.transpose()*(JNew*h) + (JNew-J).transpose()*fNew;
1579 double hy = (h.transpose()*
y)(0,0);
1580 xdbg<<
"hy = "<<hy<<std::endl;
1583 xdbg<<
"v = "<<v.transpose()<<std::endl;
1584 xdbg<<
"y = "<<
y.transpose()<<std::endl;
1585 double hv = (h.transpose()*v)(0,0);
1586 xdbg<<
"hv = "<<hv<<std::endl;
1587 H -= (1./hv) * (v * v.transpose());
1588 xdbg<<
"H -> "<<H<<std::endl;
1589 H += (1./hy) * (
y *
y.transpose());
1590 xdbg<<
"H -> "<<H<<std::endl;
1594 xdbg<<
"better"<<std::endl;
1595 x = xNew; f = fNew; Q = QNew; J = JNew; g = gNew;
1596 normInfF = f.TMV_normInf(); normInfG = normInfGNew;
1600 if (shouldSwitchMethod) {
1601 if (shouldUseQuasiNewton) {
1602 xdbg<<
"switch to LM\n";
1603 A = J.transpose() * J;
1605 A.EIGEN_diag() += mu;
1606 shouldUseQuasiNewton =
false;
1609 xdbg<<
"switch to quasinewton\n";
1611 shouldUseQuasiNewton =
true;
1615 dbg<<
"Maximum iterations exceeded in Hybrid method\n";
virtual void calculateF(const DVector &x, DVector &f) const =0
virtual void calculateJ(const DVector &x, const DVector &f, DMatrix &j) const
std::auto_ptr< DMatrix > _pJ