void L2Sphere::DiffRetraction(Variable *x, Vector *etax, Variable *y, Vector *xix, Vector *result, bool IsEtaXiSameDir) const { if (IsEtaXiSameDir) { VectorTransport(x, etax, y, xix, result); if (IsEtaXiSameDir && (HasHHR || UpdBetaAlone)) { const double *etaxTV = etax->ObtainReadData(); const double *xixTV = xix->ObtainReadData(); double EtatoXi = sqrt(Metric(x, etax, etax) / Metric(x, xix, xix)); SharedSpace *beta = new SharedSpace(1, 3); double *betav = beta->ObtainWriteEntireData(); betav[0] = sqrt(Metric(x, etax, etax) / Metric(x, result, result)) / EtatoXi; betav[1] = Metric(x, etax, etax); betav[2] = Metric(x, result, result) * EtatoXi * EtatoXi; etax->AddToTempData("beta", beta); if (HasHHR) { Vector *TReta = result->ConstructEmpty(); result->CopyTo(TReta); ScaleTimesVector(x, betav[0] * EtatoXi, TReta, TReta); SharedSpace *SharedTReta = new SharedSpace(TReta); etax->AddToTempData("betaTReta", SharedTReta); } } return; } std::cout << "Warning: The differentiated retraction has not been implemented!" << std::endl; xix->CopyTo(result); };
void L2Sphere::Retraction(Variable *x, Vector *etax, Variable *result) const {// exponential mapping double norm = sqrt(Metric(x, etax, etax)); if (norm < std::numeric_limits<double>::epsilon()) ScaleTimesVector(x, cos(norm), x, result); else VectorLinearCombination(x, cos(norm), x, sin(norm) / norm, etax, result); };
void L2Sphere::ObtainEtaxFlat(Variable *x, Vector *etax, Vector *etaxflat) const { etax->CopyTo(etaxflat); double *etaxflatTV = etaxflat->ObtainWritePartialData(); double intv = 1.0 / (n - 1); ScaleTimesVector(x, intv, etaxflat, etaxflat); etaxflatTV[0] /= 2; etaxflatTV[n - 1] /= 2; };
void ProductManifold::DiffRetraction(Variable *x, Vector *etax, Variable *y, Vector *xix, Vector *result, bool IsEtaXiSameDir) const { ProdVariable *prodx = dynamic_cast<ProdVariable *> (x); ProdVector *prodetax = dynamic_cast<ProdVector *> (etax); ProdVariable *prody = dynamic_cast<ProdVariable *> (y); ProdVector *prodxix = dynamic_cast<ProdVector *> (xix); ProdVector *prodresult = dynamic_cast<ProdVector *> (result); if (xix == result) { ProdVector *prodresultTemp = prodresult->ConstructEmpty(); prodresultTemp->NewMemoryOnWrite(); for (integer i = 0; i < numofmani; i++) { for (integer j = powsinterval[i]; j < powsinterval[i + 1]; j++) { manifolds[i]->DiffRetraction(prodx->GetElement(j), prodetax->GetElement(j), prody->GetElement(j), prodxix->GetElement(j), prodresultTemp->GetElement(j), IsEtaXiSameDir); } } prodresultTemp->CopyTo(prodresult); delete prodresultTemp; } else { prodresult->NewMemoryOnWrite(); for (integer i = 0; i < numofmani; i++) { for (integer j = powsinterval[i]; j < powsinterval[i + 1]; j++) { manifolds[i]->DiffRetraction(prodx->GetElement(j), prodetax->GetElement(j), prody->GetElement(j), prodxix->GetElement(j), prodresult->GetElement(j), IsEtaXiSameDir); } } } #ifdef CHECKMEMORY prodresult->CheckMemory(); #endif if (IsEtaXiSameDir) { const double *etaxTV = etax->ObtainReadData(); const double *xixTV = xix->ObtainReadData(); double EtatoXi = sqrt(Metric(x, etax, etax) / Metric(x, xix, xix)); SharedSpace *beta = new SharedSpace(1, 1); double *betav = beta->ObtainWriteEntireData(); betav[0] = sqrt(Metric(x, etax, etax) / Metric(x, result, result)) / EtatoXi; etax->AddToTempData("beta", beta); Vector *TReta = result->ConstructEmpty(); result->CopyTo(TReta); ScaleTimesVector(x, betav[0] * EtatoXi, TReta, TReta); SharedSpace *SharedTReta = new SharedSpace(TReta); etax->AddToTempData("betaTReta", SharedTReta); } };
void L2Sphere::InverseVectorTransport(Variable *x, Vector *etax, Variable *y, Vector *xiy, Vector *result) const { if (!etax->TempDataExist("xdydn2")) { Vector *xdy = x->ConstructEmpty(); SharedSpace *Sharedxdy = new SharedSpace(xdy); VectorAddVector(x, x, y, xdy); ScaleTimesVector(x, 1.0 / Metric(x, xdy, xdy), xdy, xdy); etax->AddToTempData("xdydn2", Sharedxdy); } const SharedSpace *Sharedxdydn2 = etax->ObtainReadTempData("xdydn2"); Vector *xdydn2 = Sharedxdydn2->GetSharedElement(); scalarVectorAddVector(x, -2.0 * Metric(x, xiy, x), xdydn2, xiy, result); };
void L2Sphere::TranH(Variable *x, Vector *etax, Variable *y, LinearOPE *Hx, integer start, integer end, LinearOPE *result) const { if (!etax->TempDataExist("xdydn2")) { Vector *xdy = x->ConstructEmpty(); SharedSpace *Sharedxdy = new SharedSpace(xdy); VectorAddVector(x, x, y, xdy); ScaleTimesVector(x, 1.0 / Metric(x, xdy, xdy), xdy, xdy); etax->AddToTempData("xdydn2", Sharedxdy); } integer ell = Hx->Getsize()[0]; integer length = etax->Getlength(); const double *M = Hx->ObtainReadData(); double *Hty = new double[ell]; Variable *yflat = y->ConstructEmpty(); y->CopyTo(yflat); double *yflatptr = yflat->ObtainWritePartialData(); yflatptr[0] /= (2 * (n - 1)); yflatptr[n - 1] /= (2 * (n - 1)); for (integer i = 1; i < n - 1; i++) { yflatptr[i] /= (n - 1); } char *transt = const_cast<char *> ("t"); double one = 1, zero = 0; integer inc = 1, N = ell; dgemv_(transt, &length, &N, &one, const_cast<double *> (M + start), &N, yflatptr, &inc, &zero, Hty, &inc); double scalar = -2.0; Hx->CopyTo(result); const SharedSpace *Sharedxdydn2 = etax->ObtainReadTempData("xdydn2"); Vector *xdydn2 = Sharedxdydn2->GetSharedElement(); const double *xdydn2TV = xdydn2->ObtainReadData(); double *resultL = result->ObtainWritePartialData(); dger_(&length, &N, &scalar, const_cast<double *> (xdydn2TV), &inc, Hty, &inc, resultL + start, &N); delete[] Hty; delete yflat; };
void Stiefel::DiffqfRetraction(Variable *x, Vector *etax, Variable *y, Vector *xix, Vector *result, bool IsEtaXiSameDir) const { Vector *extempx = EMPTYEXTR->ConstructEmpty(); const double *extempxTV; if (IsIntrApproach) { ObtainExtr(x, xix, extempx); extempxTV = extempx->ObtainReadData(); } else { xix->CopyTo(extempx); extempxTV = extempx->ObtainWritePartialData(); } const double *yM = y->ObtainReadData(); double *resultTV = result->ObtainWriteEntireData(); const SharedSpace *HHR = y->ObtainReadTempData("HHR"); const double *ptrHHR = HHR->ObtainReadData(); double *YtVRinv = new double[p * p]; integer inc = 1, N = n, P = p; char *left = const_cast<char *> ("r"), *up = const_cast<char *> ("u"), *transn = const_cast<char *> ("n"), *transt = const_cast<char *> ("t"), *nonunit = const_cast<char *> ("n"); double one = 1, zero = 0; dtrsm_(left, up, transn, nonunit, &N, &P, &one, const_cast<double *> (ptrHHR), &N, const_cast<double *> (extempxTV), &N); double sign; for (integer i = 0; i < P; i++) { sign = (ptrHHR[i + i * N] >= 0) ? 1 : -1; dscal_(&N, &sign, const_cast<double *> (extempxTV + i * N), &inc); } dgemm_(transt, transn, &P, &P, &N, &one, const_cast<double *> (yM), &N, const_cast<double *> (extempxTV), &N, &zero, YtVRinv, &P); for (integer i = 0; i < p; i++) { YtVRinv[i + p * i] = -YtVRinv[i + p * i]; for (integer j = i + 1; j < p; j++) { YtVRinv[i + p * j] = -YtVRinv[j + p * i] - YtVRinv[i + p * j]; YtVRinv[j + p * i] = 0; } } dgemm_(transn, transn, &N, &P, &P, &one, const_cast<double *> (yM), &N, YtVRinv, &P, &one, const_cast<double *> (extempxTV), &N); if (IsIntrApproach) { ObtainIntr(y, extempx, result); } else { extempx->CopyTo(result); } delete[] YtVRinv; delete extempx; if (IsEtaXiSameDir && (HasHHR || UpdBetaAlone)) { const double *etaxTV = etax->ObtainReadData(); const double *xixTV = xix->ObtainReadData(); double EtatoXi = sqrt(Metric(x, etax, etax) / Metric(x, xix, xix)); SharedSpace *beta = new SharedSpace(1, 3); double *betav = beta->ObtainWriteEntireData(); betav[0] = sqrt(Metric(x, etax, etax) / Metric(x, result, result)) / EtatoXi; betav[1] = Metric(x, etax, etax); betav[2] = Metric(x, result, result) * EtatoXi * EtatoXi; etax->AddToTempData("beta", beta); if (HasHHR) { Vector *TReta = result->ConstructEmpty(); result->CopyTo(TReta); ScaleTimesVector(x, betav[0] * EtatoXi, TReta, TReta); SharedSpace *SharedTReta = new SharedSpace(TReta); etax->AddToTempData("betaTReta", SharedTReta); } } };