xerus
a general purpose tensor library
cg.cpp
Go to the documentation of this file.
1 // Xerus - A General Purpose Tensor Library
2 // Copyright (C) 2014-2017 Benjamin Huber and Sebastian Wolf.
3 //
4 // Xerus is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as published
6 // by the Free Software Foundation, either version 3 of the License,
7 // or (at your option) any later version.
8 //
9 // Xerus is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
13 //
14 // You should have received a copy of the GNU Affero General Public License
15 // along with Xerus. If not, see <http://www.gnu.org/licenses/>.
16 //
17 // For further information on Xerus visit https://libXerus.org
18 // or contact us at contact@libXerus.org.
19 
25 #include <xerus/algorithms/cg.h>
26 #include <xerus/algorithms/als.h>
28 #include <xerus/basic.h>
29 #include <xerus/index.h>
31 #include <xerus/tensorNetwork.h>
32 
35 
36 namespace xerus {
37 
38  value_t GeometricCGVariant::solve(const TTOperator *_Ap, TTTensor &_x, const TTTensor &_b, size_t _numSteps, value_t _convergenceEpsilon, PerformanceData &_perfData) const {
39  const TTOperator &_A = *_Ap;
40  static const Index i,j;
41  size_t stepCount=0;
42  TTTensor residual;
43  TTTangentVector gradient;
44  value_t gradientNorm = 1.0;
45  value_t lastResidual=1e100;
46  value_t currResidual=1e100;
47  value_t normB = frob_norm(_b);
48 
49  if (_Ap != nullptr) {
50  _perfData << "Conjugated Gradients for ||A*x - b||^2, x.dimensions: " << _x.dimensions << '\n'
51  << "A.ranks: " << _A.ranks() << '\n';
53  _perfData << " with symmetric positive definite Operator A\n";
54  }
55  } else {
56  _perfData << "Conjugated Gradients for ||x - b||^2, x.dimensions: " << _x.dimensions << '\n';
57  }
58  _perfData << "x.ranks: " << _x.ranks() << '\n'
59  << "b.ranks: " << _b.ranks() << '\n'
60  << "maximum number of steps: " << _numSteps << '\n'
61  << "convergence epsilon: " << _convergenceEpsilon << '\n';
62  _perfData.start();
63 
64  auto calculateResidual = [&]()->value_t {
65  if (_Ap != nullptr) {
66  residual(i&0) = _b(i&0) - _A(i/2,j/2)*_x(j&0);
67  } else {
68  residual = _b - _x;
69  }
70  return frob_norm(residual);//normB;
71  };
72  auto updateGradient = [&]() {
73  if (assumeSymmetricPositiveDefiniteOperator || (_Ap == nullptr)) {
74  gradient = TTTangentVector(_x, residual);
75  } else {
76  TTTensor grad;
77  grad(i&0) = (*_Ap)(j/2,i/2) * residual(j&0); // grad = A^T * (b - Ax)
78  gradient = TTTangentVector(_x, grad);
79  }
80  gradientNorm = gradient.frob_norm();
81  };
82 
83  currResidual = calculateResidual();
84  _perfData.add(stepCount, currResidual, _x);
85 
86  updateGradient();
87  TTTangentVector direction = gradient;
88  value_t alpha = 1;
89  while ((_numSteps == 0 || stepCount < _numSteps)
90  && currResidual/normB > _convergenceEpsilon
91  && std::abs(lastResidual-currResidual)/normB > _convergenceEpsilon
92  && std::abs(1-currResidual/lastResidual)/normB > _convergenceEpsilon)
93  {
94  stepCount += 1;
95  size_t stepFlags = 0;
96 
97  // check the derivative along the current direction
98  value_t derivative = gradient.scalar_product(direction) / direction.frob_norm();
99 
100  // if movement in the given direction would increase the residual rather than decrease it, perform one steepest descent step instead
101  if (derivative <= 0) {
102  direction = gradient;
103  derivative = gradient.frob_norm();
104  alpha = 1;
105  stepFlags |= 1;
106  }
107 
108  line_search(_x, alpha, direction, derivative, currResidual, retraction, calculateResidual, 0.8);
109 
110  _perfData.add(stepCount, currResidual, _x, stepFlags);
111 
112 // direction(i&0) = residual(i&0) + beta * direction(i&0);
113  TTTangentVector oldDirection(direction);
114  vectorTransport(_x, oldDirection);
115  value_t oldGradNorm = gradientNorm;
116  updateGradient();
117 
118  double beta = gradientNorm / oldGradNorm ;// Fletcher-Reeves update
119  direction = gradient;
120  direction += oldDirection * beta;
121  }
122 
123  return currResidual;
124  }
125 
127 } // namespace xerus
bool assumeSymmetricPositiveDefiniteOperator
calculates the gradient as b-Ax instead of A^T(b-Ax)
Definition: cg.h:48
Header file for the Index class.
Header file for the IndexedTensorMoveable class.
Header file for the steepest descent algorithms.
Header file defining lists of indexed tensors.
Header file for the classes defining factorisations of Tensors.
class to compactly represent tangent vectors of the manifold of constant TT-rank
Definition: retractions.h:33
Specialized TensorNetwork class used to represent TTTensor and TToperators.
The main namespace of xerus.
Definition: basic.h:37
Header file for the ALS algorithm and its variants.
void ProjectiveVectorTransport(const TTTensor &_newBase, TTTangentVector &_tangentVector)
simple vector transport by projecting onto the new tangent plane
double solve(const TTOperator *_Ap, TTTensor &_x, const TTTensor &_b, size_t _numSteps, value_t _convergenceEpsilon, PerformanceData &_perfData=NoPerfData) const
Definition: cg.cpp:38
Storage class for the performance data collected during an algorithm (typically iteration count...
TTRetractionI retraction
the retraction type I to project from point + tangent vector to a new point on the manifold ...
Definition: cg.h:50
value_t frob_norm() const
Wrapper class for all geometric (ie. Riemannian) CG variants.
Definition: cg.h:41
std::vector< size_t > ranks() const
Gets the ranks of the TTNetwork.
Definition: ttNetwork.cpp:717
void SubmanifoldRetractionI(TTTensor &_U, const TTTangentVector &_change)
retraction that performs componentwise addition of and where is the i-th component of the riemanni...
TTVectorTransport vectorTransport
the vector transport from old tangent space to new one
Definition: cg.h:51
static XERUS_force_inline value_t frob_norm(const Tensor &_tensor)
Calculates the frobenius norm of the given tensor.
Definition: tensor.h:931
Header file for shorthand notations that are xerus specific but used throughout the library...
double value_t
The type of values to be used by xerus.
Definition: basic.h:43
Class used to represent indices that can be used to write tensor calculations in index notation...
Definition: index.h:43
void line_search(TTTensor &_x, value_t &_alpha, const TTTangentVector &_direction, value_t _derivative, value_t &_residual, std::function< void(TTTensor &, const TTTangentVector &)> _retraction, std::function< value_t()> _calculate_residual, value_t _changeInAlpha=0.5)
const GeometricCGVariant GeometricCG
default variant of the steepest descent algorithm using the lapack solver
value_t scalar_product(const TTTangentVector &_other) const
Header file for the TensorNetwork class.
void add(const size_t _itrCount, const value_t _residual, const TensorNetwork::RankTuple _ranks=TensorNetwork::RankTuple(), const size_t _flags=0)
Header file for the CG algorithm.
std::vector< size_t > dimensions
Dimensions of the external indices, i.e. the dimensions of the tensor represented by the network...