rework to allow for recursive evaluation

this enables expansion of a (functional) data structure
until exhaustion -- which is what we need to
build job functors by traversing and expanding
an arbitrarily nested job definition structure
This commit is contained in:
Fischlurch 2012-06-12 05:22:08 +02:00
parent 75df583607
commit 41180eb99c
2 changed files with 107 additions and 47 deletions

View file

@ -225,28 +225,17 @@ namespace lib {
typedef _COM_<IterExplorer,FUN> Combinator; // instantiation of the combinator strategy
typedef IterExplorer<Combinator, _COM_> ResultsIter; // result IterExplorer using that instance as state core
Combinator combinator(explorer); // build a new iteration state core
if (this->isValid()) // if source iterator isn't empty...
{
combinator.startWith( explorer(accessHeadElement())); // immediately apply the function to the first element
combinator.followUp (accessRemainingElements()); // and provide state to allow for continued exploration later
}
return ResultsIter (combinator);
return ResultsIter (
Combinator (explorer // build a new iteration state core
,accessRemainingElements())); // based on a copy of this iterator / sequence
}
private:
reference
accessHeadElement()
{
return this->operator* ();
}
IterExplorer const&
accessRemainingElements()
{
this->operator++ ();
return *this;
}
};
@ -336,12 +325,6 @@ namespace lib {
// using standard copy operations
void
setResultSequence (ResultIter firstExplorationResult)
{
results_ = firstExplorationResult;
}
void
setSourceSequence (SRC const& followUpSourceElements)
{
@ -402,21 +385,10 @@ namespace lib {
public:
DefaultCombinator() { }
DefaultCombinator(FUN explorerFunction)
DefaultCombinator(FUN explorerFunction, SRC const& sourceElements)
: CombinedIteratorEvaluation<SRC,FUN>(explorerFunction)
{ }
void
startWith (ResultIter firstExplorationResult)
{
this->setResultSequence (firstExplorationResult);
}
void
followUp (SRC const& followUpSourceElements)
{
this->setSourceSequence (followUpSourceElements);
{
this->setSourceSequence (sourceElements);
}
};
@ -499,6 +471,95 @@ namespace lib {
ChainedIters() { }
};
/**
* A "Combinator strategy" allowing to expand and evaluate a
* (functional) data structure successively and recursively.
* Contrary to the DefaultCombinator, here the explorer is evaluated
* repeatedly, feeding back the results until exhaustion. The concrete
* exploration function needs to embody some kind of termination condition,
* e.g. by returning an empty sequence at some point, otherwise infinite
* recursion might happen. Another consequence of this repeated re-evaluation
* is the requirement of the source sequence's element type to be compatible
* to the result sequence's element type -- we can't \em transform the contents
* of the source sequence into another data type, just explore and expand those
* contents into sub-sequences based on the same data type.
*
* To build a concrete combinator a special strategy template is required to define
* the actual implementation logic how to proceed with the evaluation (i.e. how to
* find the feed of the "next elements" and how to re-integrate the results of an
* evaluation step into the already expanded sequence of intermediary results.
* Moreover, these implementation strategy pattern is used as a data buffer
* to hold those intermediary results. Together, this allows to create
* various expansion patterns, e.g. depth-first or breadth-first.
*/
template<class SRC, class FUN
,template<class> class _BUF_
>
class RecursiveExhaustingEvaluation
{
typedef typename _Fun<FUN>::Ret ResultIter;
typedef typename SRC::value_type Val;
typedef typename SRC::reference reference;
typedef function<ResultIter(Val)> Explorer;
typedef _BUF_<Val> Buffer;
SRC srcSequence_;
Buffer resultBuf_;
Explorer explore_;
public:
RecursiveExhaustingEvaluation() { };
RecursiveExhaustingEvaluation (Explorer fun, SRC const& src)
: srcSequence_(src)
, resultBuf_()
, explore_(fun)
{ }
// standard copy operations
private:
ResultIter &
feed()
{
return resultBuf_.getFeed (srcSequence_);
}
void
iterate ()
{
ResultIter nextStep = explore_(*feed());
++ feed();
resultBuf_.feedBack (nextStep);
}
/* === Iteration control API for IterStateWrapper== */
friend bool
checkPoint (RecursiveExhaustingEvaluation const& seq)
{
return bool(unConst(seq).feed());
}
friend reference
yield (RecursiveExhaustingEvaluation const& seq)
{
return *(unConst(seq).feed());
}
friend void
iterNext (RecursiveExhaustingEvaluation & seq)
{
seq.iterate();
}
};
/**
* Helper template to bootstrap a chain of IterExplorers.
* This is a "state core", which basically just wraps a given

View file

@ -368,15 +368,14 @@ namespace test{
* \par Test data structure
* We build a functional datastructure here, on the fly, while exploring it.
* The \c exploreChildren(m) function generates this tree like datastructure:
* For a given node with number value i, it returns the children (2*i-1) and 2*i
* -- but only up to the given maximum value m.
* For a given number, it tries to divide by 5, 3 and 2 respectively, possibly
* generating multiple decimation sequences.
*
* If we start such a tree structure with a root node 1, and maximum = 8, this yields:
* If we start such a tree structure e.g. with a root node 30, this scheme yields:
* \code
* ( 1 )
* ( 1 2 )
* ( 1 2 3 4 )
* (1 2 3 4 5 6 7 8)
* ( 30 )
* ( 6 10 15 )
* ( 2 3 2 5 3 5 )
* \endcode
* This tree has no meaning in itself, beyond being an easy testbed for tree exploration schemes.
*
@ -401,10 +400,10 @@ namespace test{
{
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #892
typedef DepthFirstExplorer<NumberSequence> DepthFirst;
DepthFirst root (seq(1));
DepthFirst root (seq(30));
string explorationResult = materialise(root >>= exploreChildren(8));
CHECK (explorationResult == "1-1-1-1-2-2-3-4-2-3-5-6-4-7-8");
string explorationResult = materialise(root >>= exploreChildren);
CHECK (explorationResult == "30-6-2-3-10-2-5-15-3-5");
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #892
}
@ -421,10 +420,10 @@ namespace test{
{
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #892
typedef BreadthFirstExplorer<NumberSequence> BreadthFirst;
BreadthFirst root (seq(1));
BreadthFirst root (seq(30));
string explorationResult = materialise(root >>= exploreChildren(8));
CHECK (explorationResult == "1-1-2-1-2-3-4-1-2-3-4-5-6-7-8");
string explorationResult = materialise(root >>= exploreChildren);
CHECK (explorationResult == "30-6-10-15-2-3-2-5-3-5");
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #892
}