1 #ifndef PRIMALSOLVER_H_
2 #define PRIMALSOLVER_H_
4 #if (defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) || defined(__WINDOWS__) || defined(MINGW)) && !defined(CYGWIN)
21 #ifdef TRWS_DEBUG_OUTPUT
28 #ifdef TRWS_DEBUG_OUTPUT
29 using OUT::operator <<;
51 typedef std::list<listElement>
List1D;
53 template<
class Parent,
class typeT>
62 return (this->Parent::operator *()._pbufElement)-_pbuffer0;
66 size_t x()
const{
return (*this->Parent::operator *()._pbufElement->_rowIterator)._coordinate;}
67 size_t y()
const{
return (*this->Parent::operator *()._pbufElement->_colIterator)._coordinate;}
73 return iterator_template(this->Parent::operator *()._pbufElement->_colIterator,_pbuffer0);
75 return iterator_template(this->Parent::operator *()._pbufElement->_rowIterator,_pbuffer0);
85 typedef iterator_template<typename List1D::iterator,T>
iterator;
86 typedef iterator_template<typename List1D::const_iterator,const T>
const_iterator;
92 bufferElement(
const T& val,
typename List1D::iterator rowIterator,
typename List1D::iterator colIterator)
123 typedef std::vector<bufferElement>
Buffer;
139 bool push(
size_t x,
size_t y,
const T& val);
148 bool insert(
size_t x,
size_t y,
const T& val);
149 void erase(iterator it);
158 size_t rowSize(
size_t y)
const{
return _rowLists[y].size();};
159 size_t xsize()
const{
return _colLists.size();}
160 size_t colSize(
size_t x)
const{
return _colLists[x].size();};
161 size_t ysize()
const{
return _rowLists.size();}
162 size_t nnz()
const{
return _buffer.size();}
177 template<
class BinaryTable1D>
181 template<
class BinaryTable2D>
184 template<
class BinaryTable2D>
187 T&
buffer(
size_t index){
return _buffer[index]._value;}
188 const T&
buffer(
size_t index)
const{
return _buffer[index]._value;}
190 std::pair<bool,T>
getValue(
size_t x,
size_t y)
const;
192 #ifdef TRWS_DEBUG_OUTPUT
193 void PrintTestData(std::ostream& fout)
const;
196 bool _insert(
size_t x,
size_t y,
const T& val,
size_t position);
198 static T NaN(){
return std::numeric_limits<T>::max();}
201 size_t _insertPosition;
202 size_t _pushPosition;
210 _insertPosition(nnz-1),
226 _rowLists.assign(ysize,
List1D());
227 _colLists.assign(xsize,
List1D());
228 _buffer.assign(nnz,
bufferElement(NaN(),
typename List1D::iterator(),
typename List1D::iterator()));
229 _insertPosition=nnz-1;
239 _rowLists=lst._rowLists;
240 typename List1DSeq::iterator itbeg=_rowLists.begin(), itend=_rowLists.end();
241 for (;itbeg!=itend;++itbeg)
243 typename List1D::iterator beg=(*itbeg).begin(),end=(*itbeg).end();
244 for (;beg!=end;++beg)
246 size_t offset=(*beg)._pbufElement-&(lst._buffer[0]);
247 (*beg)._pbufElement= &_buffer[offset];
248 (*beg)._pbufElement->_rowIterator=beg;
252 _colLists=lst._colLists;
253 itbeg=_colLists.begin(), itend=_colLists.end();
254 for (;itbeg!=itend;++itbeg)
256 typename List1D::iterator beg=(*itbeg).begin(),end=(*itbeg).end();
257 for (;beg!=end;++beg)
259 size_t offset=(*beg)._pbufElement-&(lst._buffer[0]);
260 (*beg)._pbufElement= &_buffer[offset];
261 (*beg)._pbufElement->_colIterator=beg;
266 _insertPosition=lst._insertPosition;
267 _pushPosition=lst._pushPosition;
284 if (_insert(x,y,val,_insertPosition))
286 _insertPosition=_buffer.size();
296 if (_insert(x,y,val,_pushPosition))
300 if (_pushPosition == (_buffer.size()-1))
329 bool List2D<T>::_insert(
size_t x,
size_t y,
const T& val,
size_t position)
331 assert(x<_colLists.size());
332 assert(y< _rowLists.size());
334 if (position >= _buffer.size())
337 bufferElement& buf=_buffer[position];
340 List1D& rowList=_rowLists[y];
341 List1D& colList=_colLists[x];
343 typename List1D::iterator insertPosition=std::find_if(rowList.begin(),rowList.end(),coordMore<listElement>(x));
344 buf._rowIterator=rowList.insert(insertPosition,listElement(x,&buf));
345 insertPosition=std::find_if(colList.begin(),colList.end(),coordMore<listElement>(y));
346 buf._colIterator=colList.insert(insertPosition,listElement(y,&buf));
354 _insertPosition=it.
index();
355 size_t x=it.
x(), y=it.
y();
356 _rowLists[y].erase(_buffer[_insertPosition]._rowIterator);
357 _colLists[x].erase(_buffer[_insertPosition]._colIterator);
358 _buffer[_insertPosition]._value=NaN();
364 while (!_rowLists[y].empty())
365 erase(
iterator(_rowLists[y].begin(),&_buffer[0]));
371 while (!_colLists[x].empty())
372 erase(
iterator(_colLists[x].begin(),&_buffer[0]));
378 for (
size_t x=0;x<_rowLists.size();++x)
381 for (
size_t y=0;y<_colLists.size();++y)
385 _insertPosition=_buffer.size()-1;
389 template<
class BinaryTable1D>
393 for (
size_t i=0; i<_colLists.size();++i)
395 typename List1D::const_iterator beg=_colLists[i].begin(), end=_colLists[i].end();
396 for (;beg!=end;++beg)
397 sum+=(*beg)._pbufElement->_value * bin[xsize()*((*beg)._coordinate)+i];
403 template<
class BinaryTable2D>
406 T floatTypeEps=std::numeric_limits<T>::epsilon();
410 pprecision_=pprecision;
412 pprecision_=&precision_;
417 for (
size_t i=0; i<xsize();++i)
420 for (;beg!=end;++beg)
422 sum+=(*beg) * bin(beg.
x(),beg.
y());
423 *pprecision_+=floatTypeEps*fabs(sum);
432 typename List1D::const_iterator beg=_colLists[x].begin(), end=_colLists[x].end();
433 for (;beg!=end;++beg)
434 if ((*beg)._coordinate==y)
435 return std::make_pair(
true,(*beg)._pbufElement->_value);
437 return std::make_pair(
false,(T)0);
440 #ifdef TRWS_DEBUG_OUTPUT
444 fout <<
"_nnz=" <<_buffer.size()<<std::endl;
445 fout <<
"_insertPosition=" << _insertPosition<<std::endl;
446 fout <<
"_pushPosition=" << _pushPosition<<std::endl;
447 fout <<
"xsize="<<_colLists.size()<<std::endl;
448 fout <<
"ysize="<<_rowLists.size()<<std::endl;
450 std::vector<T> printBuffer(_buffer.size(),NaN());
452 fout <<
"row Lists: "<<std::endl;
453 for (
size_t i=0; i< _rowLists.size();++i)
455 fout <<
"y="<<i<<
": ";
456 typename List1D::const_iterator beg=_rowLists[i].begin(), end=_rowLists[i].end();
457 for (;beg!=end;++beg)
459 fout <<
"("<<(*beg)._coordinate<<
","<<(*beg)._pbufElement->_value<<
")";
460 printBuffer[(*beg)._pbufElement-&_buffer[0]]=(*beg)._pbufElement->_value;
465 fout <<
"column Lists: "<<std::endl;
466 for (
size_t i=0; i< _colLists.size();++i)
468 fout <<
"x="<<i<<
": ";
469 typename List1D::const_iterator beg=_colLists[i].begin(), end=_colLists[i].end();
470 for (;beg!=end;++beg)
472 fout <<
"("<<(*beg)._coordinate<<
","<<(*beg)._pbufElement->_value<<
")";
478 for (
size_t i=0;i<printBuffer.size();++i)
479 if (printBuffer[i]!=NaN())
480 fout <<
"("<<_buffer[i]._value<<
","<<(*_buffer[i]._rowIterator)._coordinate <<
","<< (*_buffer[i]._colIterator)._coordinate<<
")";
482 fout <<
"(nan,nan,nan)";
489 template<
class BinaryTable2D>
492 for (
size_t x=0;x<xsize();++x)
493 for (
size_t y=0;y<ysize();++y)
496 for (
size_t i=0; i<xsize();++i)
499 for (;beg!=end;++beg)
500 (*pbin)(beg.
x(),beg.
y())=(*beg);
514 typedef typename std::vector<T>::iterator
iterator;
521 const_iterator
begin()
const {
return _array.begin();}
522 const_iterator
end ()
const {
return _array.end();}
523 iterator
begin() {
return _array.begin();}
524 iterator
end () {
return _array.end();}
526 const T&
operator() (
size_t x,
size_t y)
const{
return _array[y*_xsize + x];}
527 T&
operator() (
size_t x,
size_t y) {
return _array[y*_xsize + x];}
531 #ifdef TRWS_DEBUG_OUTPUT
532 std::ostream& print(std::ostream& out)
const
534 const_iterator it=
begin();
535 out<<
"["<<_xsize<<
","<<_ysize<<
"](";
536 for (
size_t y=0;y<_ysize;++y)
538 if (y!=0) out <<
",";
540 for (
size_t x=0;x<_xsize;++x)
542 if (x!=0) out <<
",";
554 size_t _xsize, _ysize;
555 std::vector<T> _array;
562 for (
size_t x=0;x<input.
xsize();++x)
563 for (
size_t y=0;y<input.
ysize();++y)
564 result(y,x)=input(x,y);
570 template <
class InputIterator,
class OutputIteratorValue,
class OutputIteratorIndex,
class UnaryPredicate>
571 OutputIteratorValue
copy_if (InputIterator first, InputIterator last,
572 OutputIteratorValue result, OutputIteratorIndex resultIndex, UnaryPredicate pred)
575 while (first!=last) {
588 template<
class Iterator,
class T>
591 T acc=std::accumulate(begin,end,(T)0.0);
592 std::transform(begin,end,begin,std::bind1st(std::multiplies<T>(),1.0/acc));
593 return initialValue+acc;
612 template<
class OPTIMIZER,
class DenseMatrix>
623 typedef std::list<typename FeasiblePoint::const_iterator>
CycleList;
630 #ifdef TRWS_DEBUG_OUTPUT
631 std::ostream& fout=std::cerr,
633 floatType relativePrecision=floatTypeEps,
size_t maxIterationNumber=defaultMaxIterationNumber):
634 #ifdef TRWS_DEBUG_OUTPUT
637 _pbinInitial(0),_xsize(0),_ysize(0),_relativePrecision(relativePrecision),_basicSolution(0,0,0),_maxIterationNumber(maxIterationNumber)
639 assert(relativePrecision >0);
643 #ifdef TRWS_DEBUG_OUTPUT
644 std::ostream& fout=std::cout,
646 floatType relativePrecision=floatTypeEps,
size_t maxIterationNumber=100):
647 #ifdef TRWS_DEBUG_OUTPUT
650 _pbinInitial(&bin),_xsize(xsize),_ysize(ysize),_relativePrecision(relativePrecision),_basicSolution(xsize,ysize,_nnz(xsize,ysize)),_maxIterationNumber(maxIterationNumber)
652 assert(relativePrecision >0);
653 Init(xsize,ysize,bin);
657 void Init(
size_t xsize,
size_t ysize,
const DenseMatrix& bin);
664 template <
class Iterator>
665 floatType
Solve(Iterator xbegin,Iterator ybegin);
671 template<
class OutputMatrix>
673 #ifdef TRWS_DEBUG_OUTPUT
674 void PrintTestData(std::ostream& fout)
const;
675 void PrintProblemDescription(
const UnaryDense& xarr,
const UnaryDense& yarr);
678 void _InitBasicSolution(
const UnaryDense& xarr,
const UnaryDense& yarr);
679 bool _isOptimal(std::pair<size_t,size_t>* pmove);
680 bool _CheckDualConstraints(
const UnaryDense& xdual,
const UnaryDense& ydual,std::pair<size_t,size_t>* pmove )
const;
681 CoordDir _findSingleNeighborNode(
const FeasiblePoint&)
const;
682 void _BuildDuals(UnaryDense* pxdual,UnaryDense* pydual);
683 void _FindCycle(FeasiblePoint* pfp,
const std::pair<size_t,size_t>& move);
684 void _ChangeSolution(
const FeasiblePoint& fp,
const std::pair<size_t,size_t>& move);
685 bool _MovePotentials(
const std::pair<size_t,size_t>& move);
689 static size_t _nnz(
size_t xsize,
size_t ysize){
return xsize+ysize;}
690 template <
class Iterator>
691 static floatType _FilterBound(Iterator xbegin,
size_t xsize,UnaryDense& out,IndexArray* pactiveIndexes, floatType precision);
692 void _FilterObjectiveMatrix();
693 void _checkCounter(
size_t* pcounter,
const char* errmess);
695 mutable floatType _primalValueNumericalPrecision;
697 #ifdef TRWS_DEBUG_OUTPUT
700 const DenseMatrix* _pbinInitial;
701 MatrixWrapper<floatType> _matrix;
702 size_t _xsize,_ysize;
703 floatType _relativePrecision;
704 FeasiblePoint _basicSolution;
705 IndexArray _nonZeroXcoordinates;
706 IndexArray _nonZeroYcoordinates;
707 size_t _maxIterationNumber;
710 template<
class OPTIMIZER,
class DenseMatrix>
711 const typename TransportationSolver<OPTIMIZER,DenseMatrix>::floatType TransportationSolver<OPTIMIZER,DenseMatrix>::floatTypeEps=std::numeric_limits<TransportationSolver<OPTIMIZER,DenseMatrix>::floatType>::epsilon();
713 template<
class OPTIMIZER,
class DenseMatrix>
714 const size_t TransportationSolver<OPTIMIZER,DenseMatrix>::MAXSIZE_T=std::numeric_limits<size_t>::max();
716 template<
class OPTIMIZER,
class DenseMatrix>
717 const size_t TransportationSolver<OPTIMIZER,DenseMatrix>::defaultMaxIterationNumber=100;
719 template<
class OPTIMIZER,
class DenseMatrix>
725 _basicSolution.resize(xsize,ysize,_nnz(xsize,ysize));
726 _nonZeroXcoordinates.clear();
727 _nonZeroYcoordinates.clear();
728 _primalValueNumericalPrecision=0;
731 template<
class OPTIMIZER,
class DenseMatrix>
735 if ((*pcounter)++ < std::max(_xsize*_ysize*100,_maxIterationNumber) )
738 throw std::runtime_error(errmess);
741 template<
class OPTIMIZER,
class DenseMatrix>
742 void TransportationSolver<OPTIMIZER,DenseMatrix>::
743 _InitBasicSolution(
const UnaryDense& xarr,
const UnaryDense& yarr)
749 _basicSolution.resize(xarr.size(),yarr.size(),_nnz(xarr.size(),yarr.size()));
750 typename UnaryDense::iterator rbeg=row.begin(), rend=row.end();
751 typename UnaryDense::iterator cbeg=col.begin(), cend=col.end();
754 while ((rbeg!=rend)&&(cbeg!=cend))
759 _basicSolution.push(rbeg-row.begin(), cbeg-col.begin(),*rbeg);
768 _basicSolution.push(rbeg-row.begin(),cbeg-col.begin(),*cbeg);
776 _checkCounter(&counter,
"_InitBasicSolution-infinite loop!\n");
779 size_t basicNum=xarr.size()+yarr.size()-1;
780 if (counter!=basicNum)
781 throw std::runtime_error(
"TransportationSolver::_InitBasicSolution() : INTERNAL ERROR: Can not initialize basic solution!");
790 template<
class OPTIMIZER,
class DenseMatrix>
791 typename TransportationSolver<OPTIMIZER,DenseMatrix>::CoordDir
792 TransportationSolver<OPTIMIZER,DenseMatrix>::_findSingleNeighborNode(
const FeasiblePoint& fp)
const
794 for (
size_t i=0;i<_nonZeroXcoordinates.size();++i)
795 if (fp.colSize(i)==1)
796 return std::make_pair(i,X);
798 for (
size_t i=0;i<_nonZeroYcoordinates.size();++i)
799 if (fp.rowSize(i)==1)
800 return std::make_pair(i,Y);
802 return std::make_pair(MAXSIZE_T,X);
805 template<
class OPTIMIZER,
class DenseMatrix>
806 void TransportationSolver<OPTIMIZER,DenseMatrix>::
807 _BuildDuals(UnaryDense* pxdual,UnaryDense* pydual)
809 UnaryDense& xdual=*pxdual;
810 UnaryDense& ydual=*pydual;
812 xdual.assign(_nonZeroXcoordinates.size(),0.0);
813 ydual.assign(_nonZeroYcoordinates.size(),0.0);
815 FeasiblePoint fpcopy(_basicSolution);
816 CoordDir currNode=_findSingleNeighborNode(fpcopy);
818 if (currNode.first==MAXSIZE_T)
819 throw std::runtime_error(
"_BuildDuals: can not build duals: no single neighbor node available!");
821 if (currNode.second==X)
824 currNode.first=fpcopy.colBegin(currNode.first).coordinate();
828 currNode.first=fpcopy.rowBegin(currNode.first).coordinate();
837 if (qu.front().second==Y)
839 size_t y=qu.front().first;
841 typename FeasiblePoint::iterator beg=fpcopy.rowBegin(y),
842 end=fpcopy.rowEnd(y);
843 for (;beg!=end;++beg)
845 size_t x=beg.coordinate();
847 xdual[x]=_matrix(x,y)-ydual[y];
848 qu.push(std::make_pair(x,X));
854 size_t x=qu.front().first;
856 typename FeasiblePoint::iterator beg=fpcopy.colBegin(x),
857 end=fpcopy.colEnd(x);
858 for (;beg!=end;++beg)
860 size_t y=beg.coordinate();
862 ydual[y]=_matrix(x,y)-xdual[x];
863 qu.push(std::make_pair(y,Y));
871 _checkCounter(&counter,
"_BuildDuals-infinite loop!\n");
872 }
while (!qu.empty());
876 template<
class OPTIMIZER,
class DenseMatrix>
877 bool TransportationSolver<OPTIMIZER,DenseMatrix>::
878 _CheckDualConstraints(
const UnaryDense& xdual,
const UnaryDense& ydual,std::pair<size_t,size_t>* pmove)
const
880 floatType eps=(OPTIMIZER::bop(1,0) ? 1.0 : -1.0)*floatTypeEps;
881 floatType delta, precision;
884 for (
typename UnaryDense::const_iterator ybeg=ydual.begin();ybeg<ydual.end();++ybeg)
885 for (
typename UnaryDense::const_iterator xbeg=xdual.begin();xbeg<xdual.end();++xbeg)
887 delta=*mit-*xbeg-*ybeg;
888 precision=(fabs(*mit)+fabs(*xbeg)+fabs(*ybeg))*eps;
889 if (OPTIMIZER::bop(delta,precision))
891 pmove->first=xbeg-xdual.begin(); pmove->second=ybeg-ydual.begin();
900 template<
class OPTIMIZER,
class DenseMatrix>
901 void TransportationSolver<OPTIMIZER,DenseMatrix>::
902 _FindCycle(FeasiblePoint* pfp,
const std::pair<size_t,size_t>& move)
904 FeasiblePoint& fp=*pfp;
906 fp.insert(move.first,move.second,0);
908 CoordDir cd=_findSingleNeighborNode(fp);
911 while (cd.first<MAXSIZE_T)
914 fp.colErase(cd.first);
916 fp.rowErase(cd.first);
918 cd=_findSingleNeighborNode(fp);
920 _checkCounter(&counter,
"_FindCycle-infinite loop!\n");
925 template<
class OPTIMIZER,
class DenseMatrix>
926 void TransportationSolver<OPTIMIZER,DenseMatrix>::
927 _move2Neighbor(
const FeasiblePoint& fp,
typename FeasiblePoint::const_iterator &it)
const
929 typename FeasiblePoint::const_iterator beg=fp.rowBegin(0);
930 if (it.isRowIterator())
932 beg=fp.rowBegin(it.y());
936 beg=fp.colBegin(it.x());
945 template<
class OPTIMIZER,
class DenseMatrix>
946 void TransportationSolver<OPTIMIZER,DenseMatrix>::
947 _ChangeSolution(
const FeasiblePoint& fp,
const std::pair<size_t,size_t>& move)
950 for (;y<fp.ysize();++y)
952 assert( (fp.rowSize(y)==2) || (fp.rowSize(y)==0) ) ;
953 if (fp.rowSize(y)!=0)
957 CycleList plusList, minusList;
958 CycleList* pplus=&plusList, *pPlusList=0;
959 CycleList* pminus=&minusList, *pMinusList=0;
962 typename FeasiblePoint::const_iterator it=fp.rowBegin(y);
963 std::pair<size_t,size_t> c0(it.x(),it.y());
965 pplus->push_back(it);
966 if ( (it.x()==move.first) && (it.y()==move.second) )
972 _move2Neighbor(fp,it);
974 }
while (! ( (it.x()==c0.first) && (it.y()==c0.second) ) );
976 assert (pMinusList!=0);
977 assert (pPlusList!=0);
980 floatType min=std::numeric_limits<floatType>::max();
981 typename CycleList::const_iterator iterMinVal, beg=pMinusList->begin(), end=pMinusList->end();
982 for (;beg!=end;++beg)
984 if ( ( **beg < min) ||
986 ( (beg->y() < iterMinVal->y()) ||
987 ( ((beg->y() == iterMinVal->y())
988 && (beg->x() < iterMinVal->x())) ) ) ) )
996 _basicSolution.insert(move.first,move.second,0);
998 beg=pMinusList->begin(), end=pMinusList->end();
999 for (;beg!=end;++beg)
1000 _basicSolution.buffer((*beg).index())-=min;
1002 beg=pPlusList->begin(), end=pPlusList->end();
1003 for (;beg!=end;++beg)
1004 _basicSolution.buffer((*beg).index())+=min;
1006 _basicSolution.erase((*iterMinVal).index());
1009 template<
class OPTIMIZER,
class DenseMatrix>
1010 bool TransportationSolver<OPTIMIZER,DenseMatrix>::
1011 _MovePotentials(
const std::pair<size_t,size_t>& move)
1013 floatType ObjVal=GetObjectiveValue();
1014 floatType primalValueNumericalPrecisionOld=_primalValueNumericalPrecision;
1015 FeasiblePoint fp=_basicSolution;
1017 _FindCycle(&fp,move);
1019 _ChangeSolution(fp,move);
1022 floatType newObjValue=GetObjectiveValue();
1023 if ( (OPTIMIZER::bop(ObjVal,newObjValue)) && (fabs(ObjVal-newObjValue)>(_primalValueNumericalPrecision+primalValueNumericalPrecisionOld) ) )
1025 #ifdef TRWS_DEBUG_OUTPUT
1026 std::cerr<<_fout<<std::setprecision (std::numeric_limits<floatType>::digits10+1) << std::endl<<
"ObjVal="<<ObjVal
1027 <<
", newObjValue="<<newObjValue
1028 <<
", fabs(ObjVal-newObjValue)="<<fabs(ObjVal-newObjValue)<<
", _primalValueNumericalPrecision="<<_primalValueNumericalPrecision
1029 <<
", primalValueNumericalPrecisionOld="<< primalValueNumericalPrecisionOld <<std::endl;
1030 _fout <<
"Basic solution before move:" <<std::endl;
1031 fp.PrintTestData(_fout);
1032 _fout <<
"Move:" << move<<std::endl;
1041 template<
class OPTIMIZER,
class DenseMatrix>
1042 bool TransportationSolver<OPTIMIZER,DenseMatrix>::
1043 _isOptimal(std::pair<size_t,size_t>* pmove)
1047 UnaryDense xduals,yduals;
1048 _BuildDuals(&xduals,&yduals);
1050 return _CheckDualConstraints(xduals,yduals,pmove);
1053 template<
class OPTIMIZER,
class DenseMatrix>
1054 template <
class Iterator>
1055 typename TransportationSolver<OPTIMIZER,DenseMatrix>::floatType TransportationSolver<OPTIMIZER,DenseMatrix>::
1056 _FilterBound(Iterator xbegin,
size_t xsize,UnaryDense& out,IndexArray* pactiveIndexes,floatType precision)
1058 size_t numOfMeaningfulValues=std::count_if(xbegin,xbegin+xsize,std::bind2nd(std::greater<floatType>(),precision));
1060 if (numOfMeaningfulValues==0)
1061 throw std::runtime_error(
"TransportationSolver:_FilterBound(): Error: empty output array. Was the _relativePrecision parameter selected properly?");
1063 out.resize(numOfMeaningfulValues);
1064 pactiveIndexes->resize(numOfMeaningfulValues);
1065 TransportSolver::copy_if(xbegin,xbegin+xsize,out.begin(),pactiveIndexes->begin(),std::bind2nd(std::greater<floatType>(),precision));
1066 return _Normalize(out.begin(),out.end(),(floatType)0.0);
1069 #ifdef TRWS_DEBUG_OUTPUT
1070 template<
class OPTIMIZER,
class DenseMatrix>
1071 void TransportationSolver<OPTIMIZER,DenseMatrix>::
1072 PrintProblemDescription(
const UnaryDense& xarr,
const UnaryDense& yarr)
1074 size_t maxprecision=std::numeric_limits<floatType>::digits10;
1075 _fout<< std::setprecision (maxprecision+1) <<
"xarr=" << xarr<< std::endl;;
1076 _fout<< std::setprecision (maxprecision+1) <<
"yarr=" << yarr << std::endl;
1078 for (
size_t x=0;x<xarr.size();++x)
1079 for (
size_t y=0;y<yarr.size();++y)
1080 _fout << std::setprecision (maxprecision+1)<<
"; bin("<<_nonZeroXcoordinates[x]<<
","<<_nonZeroYcoordinates[y]<<
")="<<_matrix(x,y)<<std::endl;
1082 _fout <<std::endl<<
"Current basic solution:"<<std::endl;
1083 _basicSolution.PrintTestData(_fout);
1087 template<
class OPTIMIZER,
class DenseMatrix>
1088 void TransportationSolver<OPTIMIZER,DenseMatrix>::_FilterObjectiveMatrix()
1090 _matrix.resize(_nonZeroXcoordinates.size(),_nonZeroYcoordinates.size());
1092 for (
size_t y=0;y<_nonZeroYcoordinates.size();++y)
1093 for (
size_t x=0;x<_nonZeroXcoordinates.size();++x)
1095 size_t ycurr=_nonZeroYcoordinates[y];
1096 *begin=(*_pbinInitial)(_nonZeroXcoordinates[x],ycurr);
1101 template<
class OPTIMIZER,
class DenseMatrix>
1102 template<
class Iterator>
1106 _recalculated=
false;
1109 _FilterBound(xbegin,_xsize,xarr,&_nonZeroXcoordinates,_relativePrecision*_xsize*_ysize);
1110 _FilterBound(ybegin,_ysize,yarr,&_nonZeroYcoordinates,_relativePrecision*_xsize*_ysize);
1111 _FilterObjectiveMatrix();
1114 _InitBasicSolution(xarr,yarr);
1117 std::pair<size_t,size_t> move;
1118 bool objectiveImprovementFlag=
true;
1121 while ((objectiveImprovementFlag)&&(!_isOptimal(&move)))
1123 objectiveImprovementFlag=_MovePotentials(move);
1125 if (counter++ > std::max(_xsize*_ysize*100,_maxIterationNumber))
1127 #ifdef TRWS_DEBUG_OUTPUT
1128 _fout <<
"Warning! TransportationSolver::Solve(): maximal number of iterations reached! A non-optimal solution is possible!"<<std::endl;
1132 if (!objectiveImprovementFlag)
1134 #ifdef TRWS_DEBUG_OUTPUT
1135 PrintProblemDescription(xarr,yarr);
1137 throw std::runtime_error(
"TransportationSolver::Solve: INTERNAL ERROR: Objective has become worse. Interrupting!");
1140 return GetObjectiveValue();
1144 template<
class OPTIMIZER,
class DenseMatrix>
1145 template<
class OutputMatrix>
1148 for (
size_t y=0;y<_ysize;++y)
1149 for (
size_t x=0;x<_xsize;++x)
1153 _basicSolution.get2DTable(&matrix);
1154 for (
size_t y=0;y<matrix.ysize();++y)
1155 for (
size_t x=0;x<matrix.xsize();++x)
1156 (*pbin)(_nonZeroXcoordinates[x],_nonZeroYcoordinates[y])=matrix(x,y);
1158 return GetObjectiveValue();
1161 #ifdef TRWS_DEBUG_OUTPUT
1162 template<
class OPTIMIZER,
class DenseMatrix>
1165 fout <<
"_relativePrecision="<<_relativePrecision<<std::endl;
1166 fout <<
"_xsize="<<_xsize<<
", _ysize="<<_ysize<<std::endl;
1167 fout <<
"_basicSolution:"<<std::endl;
1168 _basicSolution.PrintTestData(fout);
1169 fout <<std::endl<<
"_nonZeroXcoordinates: "<<_nonZeroXcoordinates;
1170 fout <<std::endl<<
"_nonZeroYcoordinates: "<<_nonZeroYcoordinates;
std::list< listElement > List1D
iterator_template< typename List1D::const_iterator, const T > const_iterator
void resize(size_t xsize, size_t ysize)
std::list< typename FeasiblePoint::const_iterator > CycleList
void resize(size_t xsize, size_t ysize, size_t nnz)
static const floatType floatTypeEps
List1D::iterator _colIterator
List1D::iterator _rowIterator
iterator rowBegin(size_t y)
iterator_template & operator++()
bufferElement * _pbufElement
T inner_product2D(const BinaryTable2D &bin, T *pprecision=0) const
void get2DTable(BinaryTable2D *pbin) const
floatType Solve(Iterator xbegin, Iterator ybegin)
listElement(size_t coordinate, bufferElement *pbufElement)
std::vector< floatType > UnaryDense
const_iterator rowEnd(size_t y) const
typeT & operator*() const
size_t coordinate() const
const_iterator rowBegin(size_t y) const
bufferElement(const bufferElement &other)
const_iterator colEnd(size_t x) const
iterator_template changeDir() const
bufferElement & operator=(const bufferElement &other)
MatrixWrapper(size_t xsize, size_t ysize)
const BinaryViewExpression< E1, T1, E2, T2, marray_detail::Times< T1, T2, typename marray_detail::PromoteType< T1, T2 >::type > > operator*(const ViewExpression< E1, T1 > &expression1, const ViewExpression< E2, T2 > &expression2)
iterator colEnd(size_t x)
iterator rowEnd(size_t y)
bool operator()(const E &e) const
void Init(size_t xsize, size_t ysize, const DenseMatrix &bin)
OutputIteratorValue copy_if(InputIterator first, InputIterator last, OutputIteratorValue result, OutputIteratorIndex resultIndex, UnaryPredicate pred)
void assign(size_t xsize, size_t ysize, T value)
std::vector< T >::iterator iterator
bool operator()(const E &e) const
T inner_product1D(const BinaryTable1D &bin) const
List2D(size_t xsize, size_t ysize, size_t nnz)
size_t rowSize(size_t y) const
const_iterator end() const
std::vector< List1D > List1DSeq
void transpose(const MatrixWrapper< T > &input, MatrixWrapper< T > &result)
MatrixWrapper(size_t xsize, size_t ysize, T value)
std::vector< bufferElement > Buffer
floatType GetSolution(OutputMatrix *pbin) const
returns value of the current basic solution
DenseMatrix::ValueType floatType
std::vector< size_t > IndexArray
List2D & operator=(const List2D &)
T _Normalize(Iterator begin, Iterator end, T initialValue)
const_iterator colBegin(size_t x) const
const_iterator begin() const
std::queue< CoordDir > Queue
iterator_template< typename List1D::iterator, T > iterator
const T & operator()(size_t x, size_t y) const
bufferElement(const T &val, typename List1D::iterator rowIterator, typename List1D::iterator colIterator)
TransportationSolver(const size_t &xsize, const size_t &ysize, const DenseMatrix &bin, floatType relativePrecision=floatTypeEps, size_t maxIterationNumber=100)
static const size_t MAXSIZE_T
iterator_template(Parent it, const bufferElement *pbuffer0)
iterator colBegin(size_t x)
bool insert(size_t x, size_t y, const T &val)
static const size_t defaultMaxIterationNumber
View< T, false, A > & operator--(View< T, false, A > &v)
iterator_template & operator--()
floatType GetObjectiveValue() const
bool isRowIterator() const
TransportationSolver(floatType relativePrecision=floatTypeEps, size_t maxIterationNumber=defaultMaxIterationNumber)
size_t colSize(size_t x) const
std::pair< size_t, Direction > CoordDir
bool push(size_t x, size_t y, const T &val)
const T & buffer(size_t index) const
std::vector< T >::const_iterator const_iterator
List2D< floatType > FeasiblePoint
std::pair< bool, T > getValue(size_t x, size_t y) const
not very efficient function. Implemented mainly for test purposes.
View< T, false, A > & operator++(View< T, false, A > &v)