# ifndef CPPAD_LU_INVERT_INCLUDED # define CPPAD_LU_INVERT_INCLUDED /* -------------------------------------------------------------------------- CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-06 Bradley M. Bell CppAD is distributed under multiple licenses. This distribution is under the terms of the Common Public License Version 1.0. A copy of this license is included in the COPYING file of this distribution. Please visit http://www.coin-or.org/CppAD/ for information on other licenses. -------------------------------------------------------------------------- */ /* $begin LuInvert$$ $escape #$$ $spell cppad.hpp Lu Cpp jp ip const namespace typename etmp $$ $index LuInvert$$ $index linear, invert Lu equation$$ $index equation, Lu invert$$ $section Invert an LU Factored Equation$$ $pre $$ $head Syntax$$ $code# include $$ $pre $$ $syntax%LuInvert(%ip%, %jp%, %LU%, %X%)%$$ $head Description$$ Solves the matrix equation $syntax%%A% * %X% = %B%$$ using an LU factorization computed by $xref/LuFactor/$$. $head Include$$ The file $code cppad/lu_invert.hpp$$ is included by $code cppad/cppad.hpp$$ but it can also be included separately with out the rest of the $code CppAD$$ routines. $head Matrix Storage$$ All matrices are stored in row major order. To be specific, if $latex Y$$ is a vector that contains a $latex p$$ by $latex q$$ matrix, the size of $latex Y$$ must be equal to $latex p * q $$ and for $latex i = 0 , \ldots , p-1$$, $latex j = 0 , \ldots , q-1$$, $latex \[ Y_{i,j} = Y[ i * q + j ] \] $$ $head ip$$ The argument $italic ip$$ has prototype $syntax% const %SizeVector% &%ip% %$$ (see description for $italic SizeVector$$ in $xref/LuFactor/SizeVector/LuFactor/$$ specifications). The size of $italic ip$$ is referred to as $italic n$$ in the specifications below. The elements of $italic ip$$ determine the order of the rows in the permuted matrix. $head jp$$ The argument $italic jp$$ has prototype $syntax% const %SizeVector% &%jp% %$$ (see description for $italic SizeVector$$ in $xref/LuFactor/SizeVector/LuFactor/$$ specifications). The size of $italic jp$$ must be equal to $italic n$$. The elements of $italic jp$$ determine the order of the columns in the permuted matrix. $head LU$$ The argument $italic LU$$ has the prototype $syntax% const %FloatVector% &%LU% %$$ and the size of $italic LU$$ must equal $latex n * n$$ (see description for $italic FloatVector$$ in $xref/LuFactor/FloatVector/LuFactor/$$ specifications). $subhead L$$ We define the lower triangular matrix $italic L$$ in terms of $italic LU$$. The matrix $italic L$$ is zero above the diagonal and the rest of the elements are defined by $syntax% %L%(%i%, %j%) = %LU%[ %ip%[%i%] * %n% + %jp%[%j%] ] %$$ for $latex i = 0 , \ldots , n-1$$ and $latex j = 0 , \ldots , i$$. $subhead U$$ We define the upper triangular matrix $italic U$$ in terms of $italic LU$$. The matrix $italic U$$ is zero below the diagonal, one on the diagonal, and the rest of the elements are defined by $syntax% %U%(%i%, %j%) = %LU%[ %ip%[%i%] * %n% + %jp%[%j%] ] %$$ for $latex i = 0 , \ldots , n-2$$ and $latex j = i+1 , \ldots , n-1$$. $subhead P$$ We define the permuted matrix $italic P$$ in terms of the matrix $italic L$$ and the matrix $italic U$$ by $syntax%%P% = %L% * %U%$$. $subhead A$$ The matrix $italic A$$, which defines the linear equations that we are solving, is given by $syntax% %P%(%i%, %j%) = %A%[ %ip%[%i%] * %n% + %jp%[%j%] ] %$$ (Hence $italic LU$$ contains a permuted factorization of the matrix $italic A$$.) $head X$$ The argument $italic X$$ has prototype $syntax% %FloatVector% &%X% %$$ (see description for $italic FloatVector$$ in $xref/LuFactor/FloatVector/LuFactor/$$ specifications). The matrix $italic X$$ must have the same number of rows as the matrix $italic A$$. The input value of $italic X$$ is the matrix $italic B$$ and the output value solves the matrix equation $syntax%%A% * %X% = %B%$$. $children% example/lu_invert.cpp% omh/lu_invert_hpp.omh %$$ $head Example$$ The file $xref/lu_solve.hpp/$$ is a good example usage of $code LuFactor$$ with $code LuInvert$$. The file $xref/LuInvert.cpp/$$ contains an example and test of using $code LuInvert$$ by itself. It returns true if it succeeds and false otherwise. $head Source$$ The file $cref/lu_invert.hpp/$$ contains the current source code that implements these specifications. $end -------------------------------------------------------------------------- */ // BEGIN PROGRAM # include # include # include namespace CppAD { // BEGIN CppAD namespace // LuInvert template void LuInvert( const SizeVector &ip, const SizeVector &jp, const FloatVector &LU, FloatVector &B ) { size_t k; // column index in X size_t p; // index along diagonal in LU size_t i; // row index in LU and X typedef typename FloatVector::value_type Float; // check numeric type specifications CheckNumericType(); // check simple vector class specifications CheckSimpleVector(); CheckSimpleVector(); Float etmp; size_t n = ip.size(); CPPAD_ASSERT_KNOWN( jp.size() == n, "Error in LuInvert: jp must have size equal to n * n" ); CPPAD_ASSERT_KNOWN( LU.size() == n * n, "Error in LuInvert: Lu must have size equal to n * m" ); size_t m = B.size() / n; CPPAD_ASSERT_KNOWN( B.size() == n * m, "Error in LuSolve: B must have size equal to a multiple of n" ); // temporary storage for reordered solution FloatVector x(n); // loop over equations for(k = 0; k < m; k++) { // invert the equation c = L * b for(p = 0; p < n; p++) { // solve for c[p] etmp = B[ ip[p] * m + k ] / LU[ ip[p] * n + jp[p] ]; B[ ip[p] * m + k ] = etmp; // subtract off effect on other variables for(i = p+1; i < n; i++) B[ ip[i] * m + k ] -= etmp * LU[ ip[i] * n + jp[p] ]; } // invert the equation x = U * c p = n; while( p > 0 ) { --p; etmp = B[ ip[p] * m + k ]; x[ jp[p] ] = etmp; for(i = 0; i < p; i++ ) B[ ip[i] * m + k ] -= etmp * LU[ ip[i] * n + jp[p] ]; } // copy reordered solution into B for(i = 0; i < n; i++) B[i * m + k] = x[i]; } return; } } // END CppAD namespace // END PROGRAM # endif