MathLib.cpp
Go to the documentation of this file.
00001 #include "MathLib.h"
00002 
00003 MathLib::MathLib(void)
00004 {
00005 }
00006 
00007 MathLib::~MathLib(void)
00008 {
00009 }
00010 using namespace momdp;
00011 namespace momdp
00012 {
00013 
00014         void copy(DenseVector& result, const SparseVector& x)
00015         {
00016                 result.resize( x.size() );
00017                 FOREACH(SparseVector_Entry, xi,  x.data) 
00018                 {
00019                         result.data[xi->index] = xi->value;
00020                 }
00021         }
00022 
00023 
00024         void copy(SparseVector& result, const DenseVector& x)
00025         {
00026                 int num_filled;
00027                 int i;
00028                 vector<SparseVector_Entry>::iterator  ri;
00029 
00030 
00031                 // count non-zeros
00032                 num_filled = 0;
00033                 FOREACH(double, xi,  x.data) {
00034                         if (fabs(*xi) > SPARSE_EPS) num_filled++;
00035                 }
00036                 //std::cout << "convert: num_filled=" << num_filled << std::endl;
00037 
00038                 // resize result vector
00039                 result.resize( x.size() );
00040                 result.data.resize(num_filled);
00041 
00042                 // copy non-zeros to result
00043                 i = 0;
00044                 ri = result.data.begin();
00045                 int rCount = 0;
00046                 FOREACH(double, xi,  x.data) {
00047                         if (fabs(*xi) > SPARSE_EPS) {
00048                                 assert(rCount <= num_filled);
00049                                 ri->index = i;
00050                                 ri->value = *xi;
00051                                 ri++;
00052                                 rCount++;
00053                         }
00054                         i++;
00055                 }
00056         }
00057 
00058         void copy(SparseMatrix& result, kmatrix& A)
00059         {
00060                 A.canonicalize();
00061                 result.resize( A.size1(), A.size2() );
00062                 FOREACH(kmatrix_entry, entry,  A.data) {
00063                         if (fabs(entry->value) > SPARSE_EPS) {
00064                                 result.push_back( entry->r, entry->c, entry->value );
00065                         }
00066                 }
00067                 result.canonicalize();
00068         }
00069 
00070         // result = A(:,c)
00071         void copy_from_column(SparseVector& result, const SparseMatrix& A,
00072                 unsigned int c)
00073         {
00074                 assert( 0 <= c && c < A.size2() );
00075 
00076                 vector<SparseVector_Entry>::const_iterator  Ai;
00077 
00078                 vector<SparseVector_Entry>::iterator  ri;
00079 
00080 
00081                 SparseCol col = A.col(c);
00082 
00083                 result.resize( A.size1() );
00084                 result.data.resize( col.end() - col.begin() );
00085                 for (Ai = col.begin(), ri=result.data.begin(); Ai != col.end(); Ai++, ri++) {
00086                         (*ri) = (*Ai);
00087                 }
00088         }
00089 
00090         // result = A(:,c)
00091         void copy_from_column(DenseVector& result, const SparseMatrix& A,
00092                 unsigned int c)
00093         {
00094                 assert( 0 <= c && c < A.size2() );
00095                 vector<SparseVector_Entry>::const_iterator  Ai, col_end;
00096 
00097 
00098                 result.resize( A.size1() );
00099 
00100                 SparseCol col = A.col(c);
00101                 for (Ai = col.begin(); Ai != col.end(); Ai++) {
00102                         result(Ai->index) = Ai->value;
00103                 }
00104         }
00105 
00106         // A(r,c) = v
00107         void kmatrix_set_entry(kmatrix& A, unsigned int r, unsigned int c,
00108                 double v)
00109         {
00110                 A.push_back( r, c, v );
00111         }
00112 
00113         // A = A'
00114         void kmatrix_transpose_in_place(kmatrix& A)
00115         {
00116                 std::swap(A.size1_, A.size2_);
00117                 FOREACH_NOCONST(kmatrix_entry, Ai,  A.data) {
00118                         std::swap( Ai->r, Ai->c );
00119                 }
00120                 A.canonicalize();
00121         }
00122 
00123         // result = A * x
00124         void mult(DenseVector& result, const SparseMatrix& A, const SparseVector& x)
00125         {
00126             A.mult(x, result);
00127         }
00128 
00129         void mult(DenseVector& result, const SparseMatrix& A, const DenseVector& x)
00130         {
00131             A.mult(x, result);
00132         }
00133 
00134         // result = A * x
00135         void mult(SparseVector& result, const SparseMatrix& A, const SparseVector& x)
00136         {
00137                 DenseVector tmp;
00138 
00139                 mult( tmp, A, x );
00140                 copy( result, tmp );
00141         }
00142 
00143         // result = x * A
00144         void mult(DenseVector& result, const DenseVector& x, const SparseMatrix& A)
00145         {
00146             A.leftMult(x, result);
00147         }
00148 
00149         // result = x * A
00150 
00151         void mult(DenseVector& result, const SparseVector& x, const SparseMatrix& A)
00152         {
00153             A.leftMult(x, result);
00154         }
00155 
00156         // result = x * A
00157         void mult(SparseVector& result, const SharedPointer<SparseVector> x, const SharedPointer<SparseMatrix>  A)
00158         {
00159                 mult(result, *x, *A);
00160         }
00161         void mult(SparseVector& result, const SharedPointer<SparseVector> x, const SparseMatrix& A)
00162         {
00163                 mult(result, *x, A);
00164         }
00165         void mult(SparseVector& result, const SparseVector& x, const SharedPointer<SparseMatrix>  A)
00166         {
00167                 mult(result, x, *A);
00168         }
00169         void mult(SparseVector& result, const SparseVector& x, const SparseMatrix& A)
00170         {
00171                 DenseVector tmp;
00172                 mult(tmp,x,A);
00173                 copy(result,tmp);
00174         }
00175 
00176         // result = x .* y [for all i, result(i) = x(i) * y(i)]
00177         void emult(DenseVector& result, const DenseVector& x, const DenseVector& y)
00178         {
00179                 assert( x.size() == y.size() );
00180                 result.resize( x.size() );
00181                 FOR (i, result.size()) {
00182                         result(i) = x(i) * y(i);
00183                 }
00184         }
00185 
00186         // result = x .* y [for all i, result(i) = x(i) * y(i)]
00187         template <class T, class U> void emult_cc_internal(SparseVector& result, T xbegin, T xend,  U ybegin, U yend)
00188         {
00189                 U yi = ybegin;
00190                 for (T xi = xbegin; xi != xend; xi++) {
00191                         while (1) {
00192                                 if (yi == yend) return;
00193                                 if (yi->index >= xi->index) {
00194                                         if (yi->index == xi->index) {
00195                                                 result.push_back( xi->index, xi->value * yi->value);
00196                                         }
00197                                         break;
00198                                 }
00199                                 yi++;
00200                         }
00201                 }
00202         }
00203 
00204         // result = x .* y [for all i, result(i) = x(i) * y(i)]
00205         void emult(SparseVector& result, const SparseVector& x, const SparseVector& y) {
00206                 assert( x.size() == y.size() );
00207                 result.resize( x.size() );
00208 
00209                 emult_cc_internal( result, x.data.begin(), x.data.end(),
00210                         y.data.begin(), y.data.end() );
00211 
00212                 //result.finalize();
00213         }
00214 
00215         // result = A(:,c) .* x
00216         void emult_column(SparseVector& result, const SparseMatrix& A, unsigned int c, const SparseVector& x)
00217         {
00218                 assert( A.size1() == x.size() );
00219                 assert( 0 <= c && c < A.size2() );
00220                 result.resize( x.size() );
00221 
00222                 SparseCol col = A.col(c);
00223 
00224                 emult_cc_internal( result,
00225                         col.begin(), col.end(),
00226                         x.data.begin(), x.data.end() );
00227 
00228                 //result.finalize();
00229         }
00230 
00231         // result = x .* y [for all i, result(i) = x(i) * y(i)]
00232         template <class T> void emult_dc_internal(DenseVector& result, const DenseVector& x, T ybegin, T yend)
00233         {
00234                 int yind;
00235                 for (T yi = ybegin; yi != yend; yi++) {
00236                         yind = yi->index;
00237                         result(yind) = x(yind) * yi->value;
00238                 }
00239         }
00240 
00241         // result = x .* y
00242         void emult(DenseVector& result, const DenseVector& x, const SparseVector& y)
00243         {
00244                 assert( x.size() == y.size() );
00245                 result.resize( x.size() );
00246                 emult_dc_internal( result, x, y.data.begin(), y.data.end() );
00247         }
00248 
00249         // result = A(:,c) .* x
00250         void emult_column(DenseVector& result, const SparseMatrix& A, unsigned int c, const DenseVector& x)
00251         {
00252                 assert( A.size1() == x.size() );
00253                 assert( 0 <= c && c < A.size2() );
00254                 result.resize( x.size() );
00255                 SparseCol col = A.col(c);
00256                 emult_dc_internal( result, x, col.begin(), col.end());
00257         }
00258 
00259         // return x' * y
00260         double inner_prod(const DenseVector& x, const SparseVector& y)
00261         {
00262                 assert( x.size() == y.size() );
00263                 double sum = 0.0;
00264                 FOREACH(SparseVector_Entry, yi,  y.data) 
00265                 {
00266                         sum += x(yi->index) * yi->value;
00267                 }
00268                 return sum;
00269         }
00270         // return x' * y
00271         double inner_prod(const SparseVector& x, const SparseVector& y)
00272         {
00273                 if(x.size()!= y.size())
00274                         printf("x size is : %d, y size is %d\n", (int)x.size(), (int)y.size());
00275                 assert( x.size() == y.size() );
00276                 double result;
00277 
00278                 //check whether binary search is useful
00279                 if(x.data.size()>=y.data.size() && (quickLog2(x.data.size())*y.data.size())< (x.data.size())){
00280                         //                printf("x size:%d, y size:%d\n", (int)x.data.size(), (int)y.data.size());
00281                         result = inner_prod_binary(x, y);
00282                 }
00283                 else if(y.data.size()>x.data.size() && (quickLog2(y.data.size())*x.data.size())<(y.data.size())){
00284                         //                printf("x size:%d, y size:%d\n", (int)x.data.size(), (int)y.data.size());
00285                         result = inner_prod_binary(y, x);
00286                 }
00287                 else{
00288                         result = inner_prod_SparseVector_internal( x.data.begin(), x.data.end(),
00289                                 y.data.begin(), y.data.end() );
00290                 }
00291                 return result;
00292         }
00293         //quick log making use of shifts
00294         int quickLog2(int n){
00295                 int r = 0;
00296                 while(n!= 0){
00297                         n = n >> 1;
00298                         r++;
00299                 }
00300                 return r;
00301         }
00302 
00303         //Function: binarySearch
00304         //Functionality:
00305         //      to find the position of entry in x which has index value as 'key'
00306         //Parameter:
00307         //      key:    the index value to be found
00308         //Returns:
00309         //      the position of entry, if it is found
00310         //      -1, else
00311         int binarySearch(const SparseVector &x, int lowerbound, int key)
00312         {
00313                 int position;
00314                 //         int lowerbound = 0;
00315                 int upperbound = x.data.size()-1;
00316                 // calculate the first search position.
00317                 position = ( lowerbound + upperbound)>>1;
00318 
00319                 /*              if (position < 0 || position >= (int)x.data.size())
00320                 return -1;*/
00321                 // unnecessary condition, commented out by Yanzhu
00322 
00323                 while(((int)((x.data.at(position).index))!= key) && (lowerbound <= upperbound))
00324                 {
00325                         if (((int)(x.data.at(position).index)) > key)               // if the value in the array[position]..
00326                         {                                                       // is greater than the number for ��?                               upperbound = position - 1;    // which we are searching, change ..
00327                         }                                                       // upperbound to the position��?                    else                                                 // minus one.
00328                         {                                                        // Else, change lowerbound to ..
00329                                 lowerbound = position + 1;     // position plus one.
00330                         }
00331                         position = (lowerbound + upperbound)>>1;
00332                         if (position < 0 || position >= (int)x.data.size())
00333                                 break;
00334 
00335                 }
00336 
00337                 /*              if (lowerbound <= upperbound){
00338                 return position;
00339                 }
00340                 return -1;*/
00341                 // unnecessary checking, commented out by Yanzhu
00342                 return position;
00343 
00344         }
00345 
00346         //added!! to improve efficiency of inner product
00347         //rn 11/30/2006
00348         // result = x .* y [for all i, result(i) = x(i) * y(i)]
00349         double inner_prod_binary(const SparseVector& x, const SparseVector& y)
00350         {
00351                 double sum = 0.0;
00352                 int xi_position;
00353                 SparseVector_Entry xi;
00354                 vector<SparseVector_Entry>::const_iterator  yi;
00355 
00356                 xi_position = 0;
00357                 for (yi = y.data.begin(); yi!=y.data.end() && xi_position<(int)x.data.size(); yi++)
00358                 {
00359                         xi = x.data.at(xi_position);
00360                         if (xi.index == yi->index){
00361                                 sum+= xi.value*yi->value;
00362                         }
00363                         else{
00364                                 //find data in x where index = yi_index
00365                                 xi_position = binarySearch(x, xi_position, yi->index);
00366 
00367                                 if(xi_position> -1){
00368                                         xi = x.data.at(xi_position);//@
00369                                         //                        printf("result of binary search: xi_index:%d, yi_index:%d\n", xi.index, yi->index);
00370                                         sum += xi.value * yi->value;
00371                                 }
00372                         }
00373                         xi_position++;
00374                 }
00375 
00376                 return sum;
00377         }
00378         //end added
00379 
00380         // return A(:,c)' * x
00381         double inner_prod_column(const SparseMatrix& A, unsigned int c, const SparseVector& x)
00382         {
00383                 assert( A.size1() == x.size() );
00384                 assert( 0 <= c && c < A.size2() );
00385                 SparseCol col = A.col(c);
00386                 return inner_prod_SparseVector_internal( col.begin(), col.end(), x.data.begin(), x.data.end() );
00387         }
00388 
00389         // return true if for all i: x(i) >= y(i) - eps
00390         bool dominates(const DenseVector& x, const DenseVector& y, double eps)
00391         {
00392                 FOR (i, x.size()) {
00393                         if (x(i) < y(i) - eps) return false;
00394                 }
00395                 return true;
00396         }
00397 
00398         // return true if for all i: x(i) >= y(i) - eps
00399         bool dominates(const SparseVector& x, const SparseVector& y, double eps)
00400         {
00401                 vector<SparseVector_Entry>::const_iterator  xi, xend;
00402 
00403                 vector<SparseVector_Entry>::const_iterator  yi, yend;
00404 
00405                 unsigned int xind, yind;
00406                 bool xdone = false, ydone = false;
00407 
00408                 assert( x.size() == y.size() );
00409 
00410 #define CHECK_X() \
00411         if (xi == xend) { \
00412         xdone = true; \
00413         goto main_loop_done; \
00414         } else { \
00415         xind = xi->index; \
00416         }
00417 
00418 #define CHECK_Y() \
00419         if (yi == yend) { \
00420         ydone = true; \
00421         goto main_loop_done; \
00422         } else { \
00423         yind = yi->index; \
00424         }
00425 
00426                 xi = x.data.begin();
00427                 yi = y.data.begin();
00428                 xend = x.data.end();
00429                 yend = y.data.end();
00430 
00431                 CHECK_X();
00432                 CHECK_Y();
00433 
00434                 while (1) {
00435                         if (xind < yind) {
00436                                 // x(xind) == xi->value, y(xind) == 0
00437                                 if (xi->value < -eps) return false;
00438                                 xi++;
00439                                 CHECK_X();
00440                         } else if (xind == yind) {
00441                                 // x(xind) == xi->value, y(xind) == yi->value
00442                                 if (xi->value < yi->value - eps) return false;
00443                                 xi++;
00444                                 yi++;
00445                                 CHECK_X();
00446                                 CHECK_Y();
00447                         } else {
00448                                 // x(yind) == 0, y(yind) == yi->value
00449                                 if (0 < yi->value - eps) return false;
00450                                 yi++;
00451                                 CHECK_Y();
00452                         }
00453                 }
00454 
00455 main_loop_done:
00456                 if (!xdone) {
00457                         for (; xi != xend; xi++) {
00458                                 if (xi->value < -eps) return false;
00459                         }
00460                 } else if (!ydone) {
00461                         for (; yi != yend; yi++) {
00462                                 if (0 < yi->value - eps) return false;
00463                         }
00464                 }
00465 
00466                 return true;
00467         }
00468 
00469 
00470         /**********************************************************************
00471         * KMATRIX FUNCTIONS
00472         **********************************************************************/
00473 
00474         double kmatrix::operator()(unsigned int r, unsigned int c) const
00475         {
00476                 assert( 0 <= r < size1() );
00477                 assert( 0 <= c < size2() );
00478                 // NOTE: also assumes the kmatrix has been canonicalized
00479 
00480                 FOREACH(kmatrix_entry, di,  data) {
00481                         if (di->r == r && di->c == c) {
00482                                 return di->value;
00483                         }
00484                 }
00485                 return 0.0;
00486         }
00487 
00488         void kmatrix::clear(void)
00489         {
00490                 resize(0,0,0);
00491         }
00492 
00493         void kmatrix::resize(unsigned int _size1, unsigned int _size2, double value)
00494         {
00495                 assert( 0 == value );
00496                 size1_ = _size1;
00497                 size2_ = _size2;
00498                 data.clear();
00499         }
00500 
00501         void kmatrix::push_back(unsigned int r, unsigned int c, double value)
00502         {
00503                 data.push_back( kmatrix_entry(r,c,value) );
00504         }
00505 
00506         struct ColumnMajorCompare {
00507                 bool operator()(const kmatrix_entry& lhs, const kmatrix_entry& rhs) {
00508                         return (lhs.c < rhs.c) || ((lhs.c == rhs.c) && (lhs.r < rhs.r));
00509                 }
00510         };
00511 
00512         bool rc_equal(const kmatrix_entry& lhs, const kmatrix_entry& rhs)
00513         {
00514                 return (lhs.r == rhs.r) && (lhs.c == rhs.c);
00515         }
00516 
00517         void kmatrix::canonicalize(void)
00518         {
00519                 std::vector< kmatrix_entry > d;
00520 
00521                 // sort in column-major order
00522                 std::stable_sort( data.begin(), data.end(), ColumnMajorCompare() );
00523 
00524                 // ensure there is at most one entry with each (r,c) coordinate.
00525                 // among all the entries with the same (r,c), keep the last one.
00526                 // note that this operation does *not* get rid of near-zero entries.
00527                 FOR ( i, data.size() ) {
00528                         if (!d.empty() && rc_equal( d.back(), data[i] )) {
00529                                 d.back() = data[i];
00530                         } else {
00531                                 d.push_back( data[i] );
00532                         }
00533                 }
00534                 data.swap( d );
00535         }
00536 
00537         void kmatrix::read(std::istream& in)
00538         {
00539                 int rows, cols;
00540                 int num_entries;
00541                 int r, c;
00542                 double value;
00543 
00544                 in >> rows >> cols;
00545                 resize( rows, cols );
00546 
00547                 in >> num_entries;
00548                 FOR (i, num_entries) {
00549                         in >> r >> c >> value;
00550                         push_back( r, c, value );
00551                 }
00552         }
00553 
00554         // Index of maximum element of a vector
00555         int argmax_elt(const DenseVector& v) 
00556         {
00557                 assert(v.size() > 0);
00558                 double maxval = v(0);
00559                 int max_ind = 0;
00560                 for (unsigned int i=1; i < v.size(); i++) {
00561                         if (v(i) > maxval) {
00562                                 max_ind = i;
00563                                 maxval = v(i);
00564                         }
00565                 }
00566                 return max_ind;
00567         }
00568 
00569         int argmax_elt(const SparseVector& v) 
00570         {
00571                 assert(v.size() > 0);
00572                 double maxval = v(0);
00573                 int max_ind = 0;
00574                 // find the largest non-zero entry
00575                 FOR_CV(v) 
00576                 {
00577                         double val = CV_VAL(v);
00578                         if (val > maxval) 
00579                         {
00580 
00581                                 max_ind = CV_INDEX(v);
00582                                 maxval = val;
00583                         }
00584                 }
00585                 if (maxval >= 0 || v.filled() == v.size()) 
00586                 {
00587                         // a non-zero entry is maximal
00588                         return max_ind;
00589                 }
00590                 else 
00591                 {
00592                         // all non-zero entries are negative; return
00593                         // the index of a zero entry.
00594                         int ind, last_ind = -1;
00595                         FOR_CV(v) 
00596                         {
00597                                 ind = CV_INDEX(v);
00598                                 if (ind - last_ind > 1) 
00599                                 {
00600                                         return ind-1;
00601                                 }
00602                                 last_ind = ind;
00603                         }
00604                         return ind+1;
00605                 }
00606         }
00607 
00608         void max_assign(DenseVector& result, const DenseVector& x)
00609         {
00610                 assert( result.size() == x.size() );
00611 
00612                 vector<double>::const_iterator  xi = x.data.begin();
00613 
00614                 double xval;
00615 
00616                 FOREACH_NOCONST(double, ri,  result.data) {
00617                         xval = *xi;
00618                         if (xval > (*ri)) (*ri) = xval;
00619                         xi++;
00620                 }
00621         }
00622 }
00623 
00624 


appl
Author(s): petercai
autogenerated on Tue Jan 7 2014 11:02:29