File indexing completed on 2025-07-11 08:31:36
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029 #include "../../../../Eigen/src/Core/util/NonMPL2.h"
0030
0031 #ifndef EIGEN_CONSTRAINEDCG_H
0032 #define EIGEN_CONSTRAINEDCG_H
0033
0034 #include "../../../../Eigen/Core"
0035
0036 namespace Eigen {
0037
0038 namespace internal {
0039
0040
0041
0042
0043
0044
0045
0046 template <typename CMatrix, typename CINVMatrix>
0047 void pseudo_inverse(const CMatrix &C, CINVMatrix &CINV)
0048 {
0049
0050 typedef typename CMatrix::Scalar Scalar;
0051 typedef typename CMatrix::Index Index;
0052
0053 typedef Matrix<Scalar,Dynamic,1> TmpVec;
0054
0055 Index rows = C.rows(), cols = C.cols();
0056
0057 TmpVec d(rows), e(rows), l(cols), p(rows), q(rows), r(rows);
0058 Scalar rho, rho_1, alpha;
0059 d.setZero();
0060
0061 typedef Triplet<double> T;
0062 std::vector<T> tripletList;
0063
0064 for (Index i = 0; i < rows; ++i)
0065 {
0066 d[i] = 1.0;
0067 rho = 1.0;
0068 e.setZero();
0069 r = d;
0070 p = d;
0071
0072 while (rho >= 1e-38)
0073 {
0074
0075 l = C.transpose() * p;
0076 q = C * l;
0077 alpha = rho / p.dot(q);
0078 e += alpha * p;
0079 r += -alpha * q;
0080 rho_1 = rho;
0081 rho = r.dot(r);
0082 p = (rho/rho_1) * p + r;
0083 }
0084
0085 l = C.transpose() * e;
0086
0087 for (Index j=0; j<l.size(); ++j)
0088 if (l[j]<1e-15)
0089 tripletList.push_back(T(i,j,l(j)));
0090
0091
0092 d[i] = 0.0;
0093 }
0094 CINV.setFromTriplets(tripletList.begin(), tripletList.end());
0095 }
0096
0097
0098
0099
0100
0101
0102
0103
0104 template<typename TMatrix, typename CMatrix,
0105 typename VectorX, typename VectorB, typename VectorF>
0106 void constrained_cg(const TMatrix& A, const CMatrix& C, VectorX& x,
0107 const VectorB& b, const VectorF& f, IterationController &iter)
0108 {
0109 using std::sqrt;
0110 typedef typename TMatrix::Scalar Scalar;
0111 typedef typename TMatrix::Index Index;
0112 typedef Matrix<Scalar,Dynamic,1> TmpVec;
0113
0114 Scalar rho = 1.0, rho_1, lambda, gamma;
0115 Index xSize = x.size();
0116 TmpVec p(xSize), q(xSize), q2(xSize),
0117 r(xSize), old_z(xSize), z(xSize),
0118 memox(xSize);
0119 std::vector<bool> satured(C.rows());
0120 p.setZero();
0121 iter.setRhsNorm(sqrt(b.dot(b)));
0122 if (iter.rhsNorm() == 0.0) iter.setRhsNorm(1.0);
0123
0124 SparseMatrix<Scalar,RowMajor> CINV(C.rows(), C.cols());
0125 pseudo_inverse(C, CINV);
0126
0127 while(true)
0128 {
0129
0130 old_z = z;
0131 memox = x;
0132 r = b;
0133 r += A * -x;
0134 z = r;
0135 bool transition = false;
0136 for (Index i = 0; i < C.rows(); ++i)
0137 {
0138 Scalar al = C.row(i).dot(x) - f.coeff(i);
0139 if (al >= -1.0E-15)
0140 {
0141 if (!satured[i])
0142 {
0143 satured[i] = true;
0144 transition = true;
0145 }
0146 Scalar bb = CINV.row(i).dot(z);
0147 if (bb > 0.0)
0148
0149 for (typename CMatrix::InnerIterator it(C,i); it; ++it)
0150 z.coeffRef(it.index()) -= bb*it.value();
0151 }
0152 else
0153 satured[i] = false;
0154 }
0155
0156
0157 rho_1 = rho;
0158 rho = r.dot(z);
0159
0160 if (iter.finished(rho)) break;
0161 if (transition || iter.first()) gamma = 0.0;
0162 else gamma = (std::max)(0.0, (rho - old_z.dot(z)) / rho_1);
0163 p = z + gamma*p;
0164
0165 ++iter;
0166
0167 q = A * p;
0168 lambda = rho / q.dot(p);
0169 for (Index i = 0; i < C.rows(); ++i)
0170 {
0171 if (!satured[i])
0172 {
0173 Scalar bb = C.row(i).dot(p) - f[i];
0174 if (bb > 0.0)
0175 lambda = (std::min)(lambda, (f.coeff(i)-C.row(i).dot(x)) / bb);
0176 }
0177 }
0178 x += lambda * p;
0179 memox -= x;
0180 }
0181 }
0182
0183 }
0184
0185 }
0186
0187 #endif