MRS  1.0
A C++ Class Library for Statistical Set Processing
subpavings::MappedSPnode< T > Class Template Reference

A templated derived class based on SPnode. More...

+ Inheritance diagram for subpavings::MappedSPnode< T >:
+ Collaboration diagram for subpavings::MappedSPnode< T >:

List of all members.

Public Member Functions

virtual ~MappedSPnode ()
 Destructor.
 MappedSPnode ()
 No-argument constructor.
 MappedSPnode (const ivector &v)
 Initialised constructor.
 MappedSPnode (const LabBox &lb)
 Initialised constructor.
 MappedSPnode (const ivector &v, const T &r)
 Initialised constructor.
 MappedSPnode (const LabBox &lb, const T &r)
 Initialised constructor.
 MappedSPnode (const SPnode &other)
 Copy constructor.
 MappedSPnode (const MappedSPnode &other)
 Copy constructor.
MappedSPnode< T > & operator= (MappedSPnode< T > rhs)
 Copy assignment operator.
void replaceMe (MappedSPnode< T > newNode)
 Replace the properties of this node and its descendents with the properties of another node and its descendents.
MappedSPnode< T > * getParent () const
 Accessor for the parent of a node.
MappedSPnode< T > * getLeftChild () const
 Accessor for the left child of a node.
MappedSPnode< T > * getRightChild () const
 Accessor for the right child of a node.
getRange () const
 Accessor for the range.
void setRange (T r)
 Set the range.
std::string nodeStringSummary () const
 Get a string summary of this.
size_t allocateRanges (const std::vector< T > &rangesToAllocate, size_t index=0)
 Recursively allocate a collection of ranges to this and children.
bool splitToShape (std::string instruction)
 Splits paving according to string instruction.
virtual void nodeExpand (int comp)
 Add two sibling nodes to this provided this is a leaf.
virtual void nodeExpand ()
 Add two sibling nodes to this provided this is a leaf.
range
 A range of type T.
virtual void slice (const std::vector< int > &sliceDims, const std::vector< cxsc::real > &slicePts, const std::string &sliceFilename="")
 Slice this.
void acceptSPExpandVisitor (const SPExpandVisitor< T > &visitor)
 Accept a SPExpandVisitor.
void acceptSPValueVisitor (const SPValueVisitor< T > &visitor)
 Accept a SPValueVisitor visitor.
MappedSPnode< T > & operator+= (const MappedSPnode< T > &add)
 Addition to self operator.
const MappedSPnode< T > operator+ (const MappedSPnode< T > &add) const
 Addition operator.
MappedSPnode< T > & operator+= (const T &add)
 Self-scalar addition operator.
const MappedSPnode< T > operator+ (const T &add) const
 Scalar addition operator.
MappedSPnode< T > & operator-= (const MappedSPnode< T > &sub)
 Subtraction from self operator.
const MappedSPnode< T > operator- (const MappedSPnode< T > &sub) const
 Subtraction operator.
MappedSPnode< T > & operator-= (const T &sub)
 Self-scalar subtraction operator.
const MappedSPnode< T > operator- (const T &sub) const
 Scalar subtraction operator.
MappedSPnode< T > & operator*= (const MappedSPnode< T > &mult)
 Multiplication of self operator.
const MappedSPnode< T > operator* (const MappedSPnode< T > &mult) const
 Multiplication operator.
MappedSPnode< T > & operator*= (const T &mult)
 Self-scalar multiplication operator.
const MappedSPnode< T > operator* (const T &mult) const
 Scalar multiplication operator.
MappedSPnode< T > & operator/= (const MappedSPnode< T > &div)
 Division of self operator.
const MappedSPnode< T > operator/ (const MappedSPnode< T > &div) const
 Division operator.
MappedSPnode< T > & operator/= (const T &div)
 Self-scalar division operator.
const MappedSPnode< T > operator/ (const T &div) const
 Scalar division operator.
void minimiseLeaves ()
 Change this so that it has the minimum number of leaves necessary to represent the same overall 'shape' (combination of subpaving volumes and values) as before, by recombining any pair of sibling leaves with identical ranges so that their former parent becomes a leaf with the same range as formerly belonged to each child.
void swapMSPSR (MappedSPnode &spn)
 Swap the properties of this and another.
virtual std::ostream & nodePrint (std::ostream &os) const
 Print the details of a specific node in a subpaving.
virtual std::ostream & leafOutputTabs (std::ostream &os) const
 Print the details of a single leaf node, using tab delimiters.
void _reshapeTreesToUnion (MappedSPnode< T > *const rhs)
 Reshape this and so that both this and rhs have identical shapes after the operation and that shape is the non-minimal union of shape the of this shape and the shape of rhs before the operation.
virtual void _addRanges (const MappedSPnode< T > *const other)
 Give this a range equal to range of this and range of other.
virtual void _subtractRanges (const MappedSPnode< T > *const other)
 Give this a range equal to range of this - range of other.
virtual void _multRanges (const MappedSPnode< T > *const other)
 Give this a range equal to range of this * range of other.
virtual void _divRanges (const MappedSPnode< T > *const other)
 Give this a range equal to range of this divided by range of other.
virtual void _addNonMinimalUnion (const MappedSPnode< T > &rhs)
 Make a non-minimal union of subpavings using addition of ranges.
virtual void _subtractNonMinimalUnion (const MappedSPnode< T > &rhs)
 Make a non-minimal union of subpavings using subtraction of ranges.
virtual void _multiplyNonMinimalUnion (const MappedSPnode< T > &rhs)
 Make a non-minimal union of subpavings using multiplication of ranges.
virtual void _divideNonMinimalUnion (const MappedSPnode< T > &rhs)
 Make a non-minimal union of subpavings using division of ranges.
virtual void _scalarAdd (const T &add)
 Increment range collection of this.
virtual void _scalarSubtract (const T &sub)
 Increment range collection of this.
virtual void _scalarMult (const T &mult)
 Scale up range of this.
virtual void _scalarDiv (const T &div)
 Scale down range of this.
virtual void _slice (const std::vector< int > &sliceDims, const std::vector< cxsc::real > &slicePts, unsigned randID=0)
virtual void _slice (const std::vector< int > &sliceDims, const std::vector< cxsc::real > &slicePts, const string &sliceFilename)
virtual std::vector< cxsc::real > sliceCheck (const std::vector< int > &sliceDims, const std::vector< cxsc::real > &slicePts) const
 Check slice parameters and return a full vector of slice points.
virtual std::ostream & oneLineOutput (std::ostream &os, int level) const

Detailed Description

template<typename T>
class subpavings::MappedSPnode< T >

A templated derived class based on SPnode.

The base class SPnode is a node in the representation of a regular subpaving as a binary tree. A node represents a box (interval vector). SPnodes are linked together to form the tree. The initial box of the subpaving is the box represented by the root node of the tree. A box which has been split will be represented as node with one or two children. A subpaving of [x] (union of non-overlapping sub- boxes of [x]) is represented by the leaves (degenerate/ child-less) nodes in the tree.

The MappedSPnode template is parameterised on the type T of the range data mapped to (associated with) each node (i.e. with each element of the subpaving). Examples of range data types include reals, or intervals, or colours ...

A MappedSPnode node has a single value of type T mapped onto it. This value is referred to as the "range value" or "range".

This templatised class provides ways to perform some basic arithmetic-like operations on the subpaving and the data mapped to it.

It is probably best to regard this class as a class for non-minimal node-trees, ie a node either has two children or no children. The expand method will automatically make two children and there is no way of then creating a minimal tree by cutting off an 'unwanted' child. This means that the whole root paving is regarded as the 'support' of the mapping.


Constructor & Destructor Documentation

template<typename T>
subpavings::MappedSPnode< T >::MappedSPnode ( const ivector &  v) [inline, explicit]

Initialised constructor.

Initialised with a box.

        : SPnode(v) {}
template<typename T>
subpavings::MappedSPnode< T >::MappedSPnode ( const LabBox lb) [inline, explicit]

Initialised constructor.

Initialised with a labeled box.

        : SPnode(lb) {}
template<typename T>
subpavings::MappedSPnode< T >::MappedSPnode ( const ivector &  v,
const T &  r 
) [inline]

Initialised constructor.

Initialised with a box and a value of T for the range.

        : SPnode(v), range(r)
    {}
template<typename T>
subpavings::MappedSPnode< T >::MappedSPnode ( const LabBox lb,
const T &  r 
) [inline]

Initialised constructor.

Initialised with a labeled box and a value of T for the range.

        : SPnode(lb), range(r)
    {}
template<typename T>
subpavings::MappedSPnode< T >::MappedSPnode ( const SPnode other) [inline, explicit]

Copy constructor.

Copies from a plain SPnode.

Copies from given node downwards.

        : SPnode()
    {
    if (other.theBox != NULL) {
      theBox = new ivector( other.getBox() );
    }
  
    nodeName = other.nodeName;

    //recursion on the children
    if (other.leftChild) {
      nodeAddLeft(new MappedSPnode(
        *(other.getLeftChild())));
    }
    else leftChild=NULL;

    if (other.rightChild) {
      nodeAddRight(new MappedSPnode(
        *(other.getRightChild())));
    }
    else rightChild=NULL;
        
    }
template<typename T>
subpavings::MappedSPnode< T >::MappedSPnode ( const MappedSPnode< T > &  other) [inline]

Copy constructor.

Copies from a MappedSPnode.

Copies from given node downwards.

        : SPnode()
    {
    if (other.theBox != NULL) {
      theBox = new ivector( other.getBox() );
    }
  
    range = other.range;
    nodeName = other.nodeName;

    //recursion on the children
    if (other.leftChild) {
      nodeAddLeft(new MappedSPnode(
        *(other.getLeftChild())));
    }
    else leftChild=NULL;

    if (other.rightChild) {
      nodeAddRight(new MappedSPnode(
        *(other.getRightChild())));
    }
    else rightChild=NULL;
        
    }

Member Function Documentation

template<typename T>
virtual void subpavings::MappedSPnode< T >::_addRanges ( const MappedSPnode< T > *const  other) [inline, protected, virtual]

Give this a range equal to range of this and range of other.

Assumes that this and other are the same from leaves up to this and other, i.e. are roots of trees of the same shape up to the depth of this Note that other could be a taller trees than this: range collections are only combined up to the level of this.

  {
    if (other == NULL) {
      throw NullSubpavingPointer_Error(
        "MappedSPnode<T>::_addRanges(const MappedSPnode<T> * const)");
    }

    // recurse on the children if any first
    if (!isLeaf()) {
      getLeftChild()->_addRanges(
                          other->getLeftChild());
      getRightChild()->_addRanges(
                          other->getRightChild());

    }

    // deal with this range collection
    range = range + other->range;
  }
template<typename T>
virtual void subpavings::MappedSPnode< T >::_divideNonMinimalUnion ( const MappedSPnode< T > &  rhs) [inline, protected, virtual]

Make a non-minimal union of subpavings using division of ranges.

Precondition:
this and *rhs are non-empty.
    {
    if ((isEmpty()) || rhs.isEmpty()) {

      throw IncompatibleDimensions_Error(
        "MappedSPnode<T>::_divideNonMinimalUnion(const MappedSPnode<T> * const)");
    }
    
        // make copies of rhs to reshape

    MappedSPnode<T> rhsTemp(rhs);

    // reshape
    _reshapeTreesToUnion(&rhsTemp);

    _divRanges(&rhsTemp);

  }
template<typename T>
virtual void subpavings::MappedSPnode< T >::_divRanges ( const MappedSPnode< T > *const  other) [inline, protected, virtual]

Give this a range equal to range of this divided by range of other.

Assumes that this and other are the same from leaves up to this and other, i.e. are roots of trees of the same shape up to the depth of this Note that other could be a taller trees than this: range collections are only combined up to the level of this.

  {
    if (other == NULL) {
      throw NullSubpavingPointer_Error(
        "MappedSPnode<T>::_divRanges(const MappedSPnode<T> * const)");
    }

    // recurse on the children if any first
    if (!isLeaf()) {
      getLeftChild()->_divRanges(
                          other->getLeftChild());
      getRightChild()->_divRanges(
                          other->getRightChild());

    }

    // deal with this range collection
    range = range / other->range;
  }
template<typename T>
virtual void subpavings::MappedSPnode< T >::_multiplyNonMinimalUnion ( const MappedSPnode< T > &  rhs) [inline, protected, virtual]

Make a non-minimal union of subpavings using multiplication of ranges.

Precondition:
this and *rhs are non-empty.
    {
    // should not need to check on rhs not null here 
    if ((isEmpty()) || rhs.isEmpty()) {

      throw IncompatibleDimensions_Error(
        "MappedSPnode<T>::_multiplyNonMinimalUnion(const MappedSPnode<T> * const)");
    }
    
        // make copies of rhs to reshape

    MappedSPnode<T> rhsTemp(rhs);

    // reshape
    _reshapeTreesToUnion(&rhsTemp);

    _multRanges(&rhsTemp);

  }
template<typename T>
virtual void subpavings::MappedSPnode< T >::_multRanges ( const MappedSPnode< T > *const  other) [inline, protected, virtual]

Give this a range equal to range of this * range of other.

Assumes that this and other are the same from leaves up to this and other, i.e. are roots of trees of the same shape up to the depth of this Note that other could be a taller trees than this: range collections are only combined up to the level of this.

  {
    if (other == NULL) {
      throw NullSubpavingPointer_Error(
        "MappedSPnode<T>::_multRanges(const MappedSPnode<T> * const)");
    }

    // recurse on the children if any first
    if (!isLeaf()) {
      getLeftChild()->_multRanges(
                          other->getLeftChild());
      getRightChild()->_multRanges(
                          other->getRightChild());

    }

    // deal with this range collection
    range = range * other->range;
  }
template<typename T>
virtual void subpavings::MappedSPnode< T >::_scalarAdd ( const T &  add) [inline, protected, virtual]

Increment range collection of this.

Increment range by type T scalar.

Parameters:
addthe scalar increment, of same type as range, to use.
    {
    
    if (!isEmpty()) {
      range = range + add;
      // recurse on children
      if (hasLCwithBox())
        getLeftChild()->_scalarAdd(add);
      if (hasRCwithBox())
        getRightChild()->_scalarAdd(add);
    }
    }
template<typename T>
virtual void subpavings::MappedSPnode< T >::_scalarDiv ( const T &  div) [inline, protected, virtual]

Scale down range of this.

Division this range by type T scalar.

Parameters:
divthe scalar divisor, of same type as range, to use.
    {
    
    if (!isEmpty()) {
      range = range / div;
      // recurse on children
      if (hasLCwithBox())
        getLeftChild()->_scalarDiv(div);
      if (hasRCwithBox())
        getRightChild()->_scalarDiv(div);
    }
    }
template<typename T>
virtual void subpavings::MappedSPnode< T >::_scalarMult ( const T &  mult) [inline, protected, virtual]

Scale up range of this.

Multiplication this range by type T scalar.

Parameters:
multthe scalar multiplier, of same type as range, to use.
    {
    
    if (!isEmpty()) {
      range = range * mult;
      // recurse on children
      if (hasLCwithBox())
        getLeftChild()->_scalarMult(mult);
      if (hasRCwithBox())
        getRightChild()->_scalarMult(mult);
    }
    }
template<typename T>
virtual void subpavings::MappedSPnode< T >::_scalarSubtract ( const T &  sub) [inline, protected, virtual]

Increment range collection of this.

Increment range by type T scalar.

Parameters:
subthe scalar decrement, of same type as range, to use.
    {
    
    if (!isEmpty()) {
      range = range - sub;
      // recurse on children
      if (hasLCwithBox())
        getLeftChild()->_scalarSubtract(sub);
      if (hasRCwithBox())
        getRightChild()->_scalarSubtract(sub);
    }
    }
template<typename T>
virtual void subpavings::MappedSPnode< T >::_subtractNonMinimalUnion ( const MappedSPnode< T > &  rhs) [inline, protected, virtual]

Make a non-minimal union of subpavings using subtraction of ranges.

Precondition:
this and *rhs are non-empty.
    {
        // should not need to check on rhs not null here 
    if ((isEmpty()) || rhs.isEmpty()) {

      throw IncompatibleDimensions_Error(
        "MappedSPnode<T>::_subtractNonMinimalUnion(const MappedSPnode<T> * const)");
    }
    
    // make copies of rhs to reshape

    MappedSPnode<T> rhsTemp(rhs);

    // reshape
    _reshapeTreesToUnion(&rhsTemp);

    _subtractRanges(&rhsTemp);

  }
template<typename T>
virtual void subpavings::MappedSPnode< T >::_subtractRanges ( const MappedSPnode< T > *const  other) [inline, protected, virtual]

Give this a range equal to range of this - range of other.

Assumes that this and other are the same from leaves up to this and other, i.e. are roots of trees of the same shape up to the depth of this Note that other could be a taller trees than this: range collections are only combined up to the level of this.

  {
    if (other == NULL) {
      throw NullSubpavingPointer_Error(
        "MappedSPnode<T>::_subtractRanges(const MappedSPnode<T> * const)");
    }

    // recurse on the children if any first
    if (!isLeaf()) {
      getLeftChild()->_subtractRanges(
                          other->getLeftChild());
      getRightChild()->_subtractRanges(
                          other->getRightChild());

    }

    // deal with this range collection
    range = range - other->range;
  }
template<typename T>
void subpavings::MappedSPnode< T >::acceptSPExpandVisitor ( const SPExpandVisitor< T > &  visitor) [inline]

Accept a SPExpandVisitor.

If this is a leaf, and if the node is willing to split, accepts the visitor and sets the range equal to the value returned by the visitor's visit operation, then recursively asks children to accept visitor too.

The node's willingness to split is based on the results of the isSplittableNode() method.

Parameters:
visitora visitor capable of expanding this according to its own criteria and also of returning a value to used as the range of this.
  {
    #ifdef MYDEBUGVISITOR
      std::cout << "Using mappedspnode_sr expander accept" << std::endl;
    #endif
    
    // only accept the visit if this is a leaf and the node is splittable
    if (isLeaf() && isSplittableNode()) {
      range = visitor.visit(this);
      #ifdef MYDEBUGVISITOR
        std::cout << "after visit, range value = " << range << std::endl;
      #endif
    }
    
    
    #ifdef MYDEBUGVISITOR
      if (isLeaf() && !isSplittableNode()) {
        std::cout << "box is too small to split: volume is " << nodeRealVolume() << std::endl;
      }
    
      if(!isLeaf()) std::cout << "now visit children" << std::endl;
    #endif
    
    if (hasLCwithBox()) (getLeftChild())->acceptSPExpandVisitor(visitor);
    if (hasRCwithBox()) (getRightChild())->acceptSPExpandVisitor(visitor);
  }
template<typename T>
void subpavings::MappedSPnode< T >::acceptSPValueVisitor ( const SPValueVisitor< T > &  visitor) [inline]

Accept a SPValueVisitor visitor.

Accepts the visitor and sets the range equal to the value returned by the vistor's visit operation.

Recursively asks children to accept visitor too.

Parameters:
visitora visitor capable of returning a value to be used as the range of this.
  {
    #ifdef MYDEBUGVISITORE
      std::cout << "Using mappedspnode_sr valuer accept " << getNodeName() << std::endl;
    #endif
    
    range = visitor.visit(this);
    #ifdef MYDEBUGVISITORE
      std::cout << "after visit, range value = " << range << std::endl;
    #endif
    
    #ifdef MYDEBUGVISITORE
      if(!isLeaf()) std::cout << "now visit children" << std::endl;
    #endif
    
    if (hasLCwithBox()) (getLeftChild())->acceptSPValueVisitor(visitor);
    if (hasRCwithBox()) (getRightChild())->acceptSPValueVisitor(visitor);
  }
template<typename T>
size_t subpavings::MappedSPnode< T >::allocateRanges ( const std::vector< T > &  rangesToAllocate,
size_t  index = 0 
) [inline]

Recursively allocate a collection of ranges to this and children.

Throws a std::invalid_argument if there are fewer values in rangesToAllocate than there are nodes in this.

Allocation order is this, left child with remainder of allocation, right child with remainder.

Parameters:
rangesToAllocatea collection of range values to apply to the nodes of the tree rooted at this.
indexis the index of the value in rangesToAllocate to become the value of the range for this.
Precondition:
rangesToAllocate.size() - index >= number of nodes in tree rooted at this.
Postcondition:
The nodes in the tree rooted at this have values taken from the values in rangesToAllocate, starting at the value indexed index which is applied to this, then allocating the following values to the left child of this and its descendants and then the right child of this and its descendants.
    {
    if (index >= rangesToAllocate.size()) {
      throw std::invalid_argument("Range allocations too short");

    }

    range = rangesToAllocate[index];

    std::size_t newIndex = index+1;
    if (hasLCwithBox()) {
      newIndex = getLeftChild()->allocateRanges(rangesToAllocate, newIndex);
    }
    if (hasRCwithBox()) {
      newIndex = getRightChild()->allocateRanges(rangesToAllocate, newIndex);
    }

    // have done all the children
    // if this is the root, want to check we have used all the allocations
    if (NULL == getParent()) {
      if (newIndex < rangesToAllocate.size()) {
        throw std::invalid_argument("More ranges than nodes in tree");
      }

    }

    return newIndex;
  
    }
template<typename T>
MappedSPnode<T>* subpavings::MappedSPnode< T >::getLeftChild ( ) const [inline]

Accessor for the left child of a node.

Returns:
a copy of the pointer to leftChild node, cast to this type.

Reimplemented from subpavings::SPnode.

Reimplemented in subpavings::RealMappedSPnode, subpavings::BooleanValueMappedSPnode, and subpavings::IntervalMappedSPnode.

    { return (MappedSPnode<T>*) leftChild; }
template<typename T>
MappedSPnode<T>* subpavings::MappedSPnode< T >::getParent ( ) const [inline]

Accessor for the parent of a node.

Returns:
a copy of the pointer to parent node, cast to this type.

Reimplemented from subpavings::SPnode.

Reimplemented in subpavings::RealMappedSPnode, subpavings::BooleanValueMappedSPnode, and subpavings::IntervalMappedSPnode.

    { return (MappedSPnode<T>*) parent; }
template<typename T>
T subpavings::MappedSPnode< T >::getRange ( ) const [inline]

Accessor for the range.

Returns:
a copy of the range.

Reimplemented in subpavings::BooleanValueMappedSPnode.

    {   
        return T(range);
    }
template<typename T>
MappedSPnode<T>* subpavings::MappedSPnode< T >::getRightChild ( ) const [inline]

Accessor for the right child of a node.

Returns:
a copy of the pointer to rightChild node, cast this type.

Reimplemented from subpavings::SPnode.

Reimplemented in subpavings::RealMappedSPnode, subpavings::BooleanValueMappedSPnode, and subpavings::IntervalMappedSPnode.

    { return (MappedSPnode<T>*) rightChild; }
template<typename T>
void subpavings::MappedSPnode< T >::minimiseLeaves ( ) [inline]

Change this so that it has the minimum number of leaves necessary to represent the same overall 'shape' (combination of subpaving volumes and values) as before, by recombining any pair of sibling leaves with identical ranges so that their former parent becomes a leaf with the same range as formerly belonged to each child.

Eg a node with two leafs where both children have the same value $ r $ mapped to them can be represented as a single leaf with the value $ r $ mapped to it. minimiseLeaves can be used after arithmetic operations on nodes to deal with cases where sibling leaf nodes in the result are equivalent in terms of their range values.

The minimisation process works from the leaves upwards, so that a tree could potentially be reduced to a single node if every pair of sibling leaves encountered in the process can be recombined.

  {
    if (!isLeaf()) { // can't do anything if this is a leaf
      
      // recurse first
      if ( hasLCwithBox() ) getLeftChild()->minimiseLeaves();
      if ( hasRCwithBox() ) getRightChild()->minimiseLeaves();
      
      // now do me
      if ( isSubLeaf() && 
        (getLeftChild()->getRange() == getRightChild()->getRange()) ) {
        
          // make this range collection one of the childrens
          range = getLeftChild()->getRange();
          delete leftChild;
          leftChild = NULL;
          delete rightChild;
          rightChild = NULL;
      }
    
    }
  }
template<typename T>
virtual void subpavings::MappedSPnode< T >::nodeExpand ( int  comp) [inline, virtual]

Add two sibling nodes to this provided this is a leaf.

Creates two children each with half of the box of this. Split the box in half normal to dimension set by comp. comp argument is passed to Upper() and Lower()

Parameters:
compthe dimension on which to bisect this to create children.

Reimplemented from subpavings::SPnode.

Reimplemented in subpavings::IntervalMappedSPnode, subpavings::RealMappedSPnode, and subpavings::BooleanValueMappedSPnode.

    {
        // can only expand if there is a box
    if (isEmpty()) {
      throw NoBox_Error("MappedSPnode<T>::nodeExpand(int)");
    }
    
    // only do something if this node is a leaf
    if (isLeaf()) {
      
      MappedSPnode<T>* newLC = NULL;
      MappedSPnode<T>* newRC = NULL;
      
      try {
        // ivectors to become boxes for new children
        ivector lC, rC;
        // Call Lower() and Upper() to put split boxes
        // into lC and rC respectively
        Lower(getBox(), lC, comp);
        Upper(getBox(), rC, comp);

        // make and add the new children
        newLC = new MappedSPnode<T>(lC, range);
        newRC = new MappedSPnode<T>(rC, range);
        
        nodeAddLeft(newLC);
        nodeAddRight(newRC);
        // both children get the same range as this
        
        //name the new children
        getLeftChild()->setNodeName(nodeName + "L");
        getRightChild()->setNodeName(nodeName + "R");

        // new children have range collection from this
      }
      catch(std::exception& e) {
      // overkill, but try to deal with all eventualities...
        try {
          if (getLeftChild() != NULL) {
            delete (getLeftChild());
            leftChild = NULL;
          }
          
          if (getRightChild() != NULL) {
            delete (getRightChild());
            rightChild = NULL;
          }
          if (newLC != NULL) {
            delete newLC;
            newLC = NULL;
          }
          if (newRC != NULL) {
            delete newRC;
            newRC = NULL;
          }
        }
        catch(std::exception& e) {} //catch and swallow
        
        throw; // rethrow original exception
      }
    }
    }
template<typename T>
virtual void subpavings::MappedSPnode< T >::nodeExpand ( ) [inline, virtual]

Add two sibling nodes to this provided this is a leaf.

Creates two children each with half of the box of this.

Reimplemented from subpavings::SPnode.

Reimplemented in subpavings::IntervalMappedSPnode, subpavings::RealMappedSPnode, and subpavings::BooleanValueMappedSPnode.

    {
        int maxdiamcomp; // variable to hold first longest dimension
        double temp = ::MaxDiam(getBox(), maxdiamcomp);
        nodeExpand(maxdiamcomp); // complete nodeExpand
    }
template<typename T>
virtual std::ostream& subpavings::MappedSPnode< T >::nodePrint ( std::ostream &  os) const [inline, virtual]

Print the details of a specific node in a subpaving.

Prints: nodeName [tab] "Box is" [tab] ... each interval in the box in cxsc output format ... [tab] "Box volume is" [tab] volume [tab] "range data is" [tab] range [newline]

Parameters:
osthe stream to print to.

Reimplemented from subpavings::SPnode.

Reimplemented in subpavings::IntervalMappedSPnode, and subpavings::BooleanValueMappedSPnode.

    {
        // output for box in form:
        // box, volume, summary data

        if(theBox != NULL) { // do nothing if there is no box

            ivector thisBox = *theBox; // copy theBox

      os << nodeName << "\tBox is:\t";

            for (int i = Lb(thisBox); i <= Ub(thisBox) ; i++) {
                // c-xsc default output for intervals
                os << "\t" << thisBox[i];   }

            os << "\tBox volume is:\t" << nodeVolume();
            os << "\trange data:\t" << range << std::endl;
    }
        return os;
    }
template<typename T>
std::string subpavings::MappedSPnode< T >::nodeStringSummary ( ) const [inline, virtual]

Get a string summary of this.

Used for debugging.

Reimplemented from subpavings::SPnode.

  {
    std::ostringstream oss;
    
    oss << "I am " << getNodeName() << "(address " << this << "),\n";
    oss << "Dimension is " << getDimension() << ", address of box is " << theBox << "\n"; 
    oss << "range is " << range << "\n";
    oss << "my parent is ";
    if (getParent() != NULL) oss << getParent()->getNodeName();
    else oss << "NULL"; 
    oss << ", my left child is ";
    if (getLeftChild() != NULL) oss << getLeftChild()->getNodeName();
    else oss << "NULL"; 
    oss << ", my right child is ";
    if (getRightChild() != NULL) oss << getRightChild()->getNodeName();
    else oss << "NULL";
    
    return oss.str();
    
  }
template<typename T>
const MappedSPnode<T> subpavings::MappedSPnode< T >::operator* ( const MappedSPnode< T > &  mult) const [inline]

Multiplication operator.

Parameters:
multthe object to multiply this by to give the object returned.
Returns:
a non-minimal union of this and mult with a range equal to the range of this before the operation multiplied by the range of mult. If both this and mult were empty before the operation, the returned object will be empty post the operation.
Precondition:
either both this and mult are empty or both are non-empty and the boxes match.
    {
        MappedSPnode<T> result =(*this);
  
    result*= mult;
    
    return result;
    }
template<typename T>
const MappedSPnode<T> subpavings::MappedSPnode< T >::operator* ( const T &  mult) const [inline]

Scalar multiplication operator.

Parameters:
multthe value to multiply this by to give the object returned.
Returns:
a mapped paving with the same tree structure as this before the operation with range equal to the range of this before the operation multiplied by mult.
    {
        MappedSPnode<T> result =(*this);
  
    result*= mult;
  
    return result;
    }
template<typename T>
MappedSPnode<T>& subpavings::MappedSPnode< T >::operator*= ( const MappedSPnode< T > &  mult) [inline]

Multiplication of self operator.

Parameters:
multthe object to multiply this by.
Precondition:
either both this and mult are empty or both are non-empty and the boxes match.
Postcondition:
this is a non-minimal union of this and mult with a range equal to the range of this before the operation multiplied by the range of mult. If both this and mult were empty before the operation, this will be empty post the operation.
    {
    
    // if both empty, do nothing
    if (!isEmpty() || !mult.isEmpty()) {
      
      // just one empty or boxes don't match
      if ( isEmpty() || mult.isEmpty() ||
        (getBox() != mult.getBox() ) ) {
        throw IncompatibleDimensions_Error(
        "MappedSPnode<T>::operator*=(const MappedSPnode<T>& const)");
      }
      // both must be non-empty
      
      this->_multiplyNonMinimalUnion(mult);

      
    }
    
    return *this;
  }
template<typename T>
MappedSPnode<T>& subpavings::MappedSPnode< T >::operator*= ( const T &  mult) [inline]

Self-scalar multiplication operator.

Parameters:
multthe value to multiply this by.
Postcondition:
this has the same tree structure as before the operation with a range equal to the range of this before the operation multiplied by mult.
    {
    _scalarMult(mult);
    return *this;
  }
template<typename T>
const MappedSPnode<T> subpavings::MappedSPnode< T >::operator+ ( const MappedSPnode< T > &  add) const [inline]

Addition operator.

Parameters:
addthe object to add to this to give the object returned.
Returns:
a non-minimal union of this and add. with a range equal to the sum of the values in ranges of this before the operation and of add. If both this and add were empty before the operation, the object returned will be empty.
Precondition:
either both this and add are empty or both are non-empty and the boxes match.
    {
    MappedSPnode<T> result =(*this);
  
    result+= add;
    
    return result;
    }
template<typename T>
const MappedSPnode<T> subpavings::MappedSPnode< T >::operator+ ( const T &  add) const [inline]

Scalar addition operator.

Parameters:
addthe value to add to this to give the object returned.
Returns:
a mapped paving with the same tree structure as this before the operation with range equal to the range of this before the operation plus add.
    {
        MappedSPnode<T> result =(*this);
  
    result+= add;
  
    return result;
    }
template<typename T>
MappedSPnode<T>& subpavings::MappedSPnode< T >::operator+= ( const MappedSPnode< T > &  add) [inline]

Addition to self operator.

Parameters:
addthe object to add to this.
Precondition:
either both this and add are empty or both are non-empty and the boxes match.
Postcondition:
this is a non-minimal union of this and add with a range equal to the sum of the values in ranges of this before the operation and of add. If both this and add were empty before the operation, this will be empty post the operation.
    {
    // if both empty, do nothing
    if (!isEmpty() || !add.isEmpty()) {
      
      // just one empty or boxes don't match
      if ( isEmpty() || add.isEmpty() ||
        (getBox() != add.getBox() ) ) {
        throw IncompatibleDimensions_Error(
        "MappedSPnode<T>::operator+=(const MappedSPnode<T>& const)");
      }
      
      #ifdef LOGARITHMETIC
        int recordNumber = 0;
        std::string filename("MappedAddition");
        
        this->_addNonMinimalUnionAdditionSpecial(add,
                    filename, recordNumber);
      #else
        this->_addNonMinimalUnion(add);
      #endif
    
    }
    return *this;
    }
template<typename T>
MappedSPnode<T>& subpavings::MappedSPnode< T >::operator+= ( const T &  add) [inline]

Self-scalar addition operator.

Parameters:
addthe value to add to this.
Postcondition:
this has the same tree structure as before the operation with a range equal to the range of this before the operation plus add.
    {
    _scalarAdd(add);
    return *this;
  }
template<typename T>
const MappedSPnode<T> subpavings::MappedSPnode< T >::operator- ( const MappedSPnode< T > &  sub) const [inline]

Subtraction operator.

Parameters:
subthe object to subtract from this to give the object returned.
Returns:
a non-minimal union of this and sub with a range equal to the value of the range of this before the operation less the range of of sub. If both this and sub were empty before the operation, the returned object will be empty post the operation.
Precondition:
either both this and sub are empty or both are non-empty and the boxes match.
    {
        MappedSPnode<T> result =(*this);
  
    result-= sub;
  
    return result;
    }
template<typename T>
const MappedSPnode<T> subpavings::MappedSPnode< T >::operator- ( const T &  sub) const [inline]

Scalar subtraction operator.

Parameters:
subthe value to subtract from this to give the object returned.
Returns:
a mapped paving with the same tree structure as this before the operation with range equal to the range of this before the operation minus sub.
    {
        MappedSPnode<T> result =(*this);
  
    result-= sub;
  
    return result;
    }
template<typename T>
MappedSPnode<T>& subpavings::MappedSPnode< T >::operator-= ( const MappedSPnode< T > &  sub) [inline]

Subtraction from self operator.

Parameters:
subthe object to subtract from this.
Precondition:
either both this and sub are empty or both are non-empty and the boxes match.
Postcondition:
this is a non-minimal union of this and sub with a range equal to the range of this before the operation less the range of sub. If both this and sub were empty before the operation, this will be empty post the operation.
    {
    
    // if both empty, do nothing
    if (!isEmpty() || !sub.isEmpty()) {
      
      // just one empty or boxes don't match
      if ( isEmpty() || sub.isEmpty() ||
        (getBox() != sub.getBox() ) ) {
        throw IncompatibleDimensions_Error(
        "MappedSPnode<T>::operator-=(const MappedSPnode<T>& const)");
      }
      
      this->_subtractNonMinimalUnion(sub);
    
    }
    return *this;
  }
template<typename T>
MappedSPnode<T>& subpavings::MappedSPnode< T >::operator-= ( const T &  sub) [inline]

Self-scalar subtraction operator.

Parameters:
subthe value to subtract from this.
Postcondition:
this has the same tree structure as before the operation with a range equal to the range of this before the operation minus sub.
    {
    _scalarSubtract(sub);
    return *this;
  }
template<typename T>
const MappedSPnode<T> subpavings::MappedSPnode< T >::operator/ ( const MappedSPnode< T > &  div) const [inline]

Division operator.

Parameters:
divthe object to divide this by to give the object returned.
Returns:
a non-minimal union of this and div with a range equal to the range of this before the operation divided by the range of div. If both this and div were empty before the operation, the returned object will be empty post the operation.
Precondition:
either both this and div are empty or both are non-empty and the boxes match.
    {
        MappedSPnode<T> result =(*this);
  
    result/= div;
  
    return result;
    }
template<typename T>
const MappedSPnode<T> subpavings::MappedSPnode< T >::operator/ ( const T &  div) const [inline]

Scalar division operator.

Parameters:
divthe value to divide this by to give the object returned.
Returns:
an object with the same tree structure as this before the operation with a range equal to the range of this before the operation divided by div.
    {
        MappedSPnode<T> result =(*this);
  
    result/= div;
  
    return result;
    }
template<typename T>
MappedSPnode<T>& subpavings::MappedSPnode< T >::operator/= ( const MappedSPnode< T > &  div) [inline]

Division of self operator.

Parameters:
divthe object to divide this by.
Precondition:
either both this and div are empty or both are non-empty and the boxes match.
Postcondition:
this is a non-minimal union of this and div with a range equal to the range of this before the operation divided by the range of of div. If both this and div were empty before the operation, this will be empty post the operation.
    {
    // if both empty, do nothing
    if (!isEmpty() || !div.isEmpty()) {
      
      // just one empty or boxes don't match
      if ( isEmpty() || div.isEmpty()  ||
        (getBox() != div.getBox() ) ) {
        throw IncompatibleDimensions_Error(
        "MappedSPnode<T>::operator/=(const MappedSPnode<T>& const)");
      }
      // both must be non-empty
      
      this->_divideNonMinimalUnion(div);

      
    }
    return *this;
  }
template<typename T>
MappedSPnode<T>& subpavings::MappedSPnode< T >::operator/= ( const T &  div) [inline]

Self-scalar division operator.

Parameters:
divthe value to divide this by.
Postcondition:
this has the same tree structure as before the operation. with a range equal to the range of this before the operation divided by div.
    {
    _scalarDiv(div);
    return *this;
  }
template<typename T>
MappedSPnode<T>& subpavings::MappedSPnode< T >::operator= ( MappedSPnode< T >  rhs) [inline]

Copy assignment operator.

Copies from given node downwards.

Reimplemented in subpavings::RealMappedSPnode, subpavings::BooleanValueMappedSPnode, and subpavings::IntervalMappedSPnode.

    {
        rhs.swapMSPSR(*this); // make sure we use our version of swap
    return(*this);
    }
template<typename T>
void subpavings::MappedSPnode< T >::replaceMe ( MappedSPnode< T >  newNode) [inline]

Replace the properties of this node and its descendents with the properties of another node and its descendents.

Copies newNode node downwards into this, but keeps the relationship of this with its parent, ie if this is a node in a tree, the part of the tree rooted at this is made identical to newNode but the relationship to the rest of the tree,through the link between this and its parent, is retained.

Reimplemented in subpavings::RealMappedSPnode, subpavings::BooleanValueMappedSPnode, and subpavings::IntervalMappedSPnode.

  {
    
    MappedSPnode<T>* pNode = getParent();
    newNode.swapMSPSR(*this);
    
    if (NULL != pNode) {
      
      this->parent = pNode;
    }
  }
template<typename T>
void subpavings::MappedSPnode< T >::setRange ( r) [inline]

Set the range.

Parameters:
rthe value for the range.
    {   
        range = r;
    }
template<typename T>
virtual void subpavings::MappedSPnode< T >::slice ( const std::vector< int > &  sliceDims,
const std::vector< cxsc::real > &  slicePts,
const std::string &  sliceFilename = "" 
) [inline, virtual]

Slice this.

Slice this on at the point jointly specified by sliceDims and slicePts. For example, if this has a 3-dimensional root box [-1,1]x[-1,1]x[-1,1], ie dimensions {1,2,3} and sliceDims = {2,3} and slicePts is (0.0,0.5) then we are slicing at point 0.0 on dimension 2, point 0.5 on dimension 3. After the opertation this would then have only one-dimensional boxes on dimensions {1,2,3}2,3} = {1}, each box being one that did contain point 0.0 on dimension 2, point 0.5 on dimension 3. The range will be unchanged). Any boxes associated with the original this that did not contain the point 0.0 on dimension 2 and 0.5 on dimension 3 will not be represented in its new form.

Parameters:
sliceDimsis a vector of dimensions to slice on, indexed from 1 onwards.
slicePtsis a vector of points to slice on, assumed to correspond to the dimensions in sliceDims, ie the ith value in sliceDims gives the dimension for the ith point in slicePts.
sliceFilenameis the name of file to use to capture the boxes of this that are used in the slice by outputting them to the file named sliceFilename. Defaults to the empty string "". If sliceFilename is the empty string "" no boxes will be captured to file.
  {
    
    #ifdef SLICE_OUTPUT
      std::cout << "In MappedSPnode<T>::slice, I am " << getNodeName() << std::endl;
    #endif
    
    std::vector<cxsc::real> fullSlicePts = sliceCheck(sliceDims, slicePts);
    
    //start the file
    if (!sliceFilename.empty()) {
      std::ofstream os(sliceFilename.c_str());
      if (os.is_open()) os.close();
    }
    
    _slice(sliceDims, fullSlicePts, sliceFilename);
  }
template<typename T>
virtual std::vector< cxsc::real > subpavings::MappedSPnode< T >::sliceCheck ( const std::vector< int > &  sliceDims,
const std::vector< cxsc::real > &  slicePts 
) const [inline, protected, virtual]

Check slice parameters and return a full vector of slice points.

Checks that:

  • there is a box,
  • that dimensions of box are compatible with sliceDims given,
  • that slicePts is of same size as sliceDims,
  • that both sliceDims and slicePts are non-empty,
  • that sliceDims does not contain every dimension in this,
  • that for the ith dimension in sliceDims, the i-th value in slicePts is inside the interval of the box on the ith dimension in sliceDims.

Throws exceptions if any problems are encountered.

Parameters:
sliceDimsis a vector of dimensions to slice on.
slicePtsis a vector of points to slice on, assumed to correspond to the dimensions in sliceDims, ie the ith value in sliceDims gives the dimension for the ith point in slicePts.
Returns:
a vector of slice points with as many elements in as the dimensions of this, with the values from slicePts as the positions given by sliceDims and 0's (dummy values) otherwise.
  {
    std::vector < cxsc::real > fullSlicePts;
    
    if ( getParent() != NULL ) {
      throw NonRootNode_Error(
        "sliceCheck error found");
    }
    if ( !sliceDims.empty() || !slicePts.empty()) {
      
    
      if ( sliceDims.size() != slicePts.size()) {
        throw std::invalid_argument(
          "sliceCheck error found: sliceDims.size() != slicePts.size()");
      }
      
      /* get ordered unique values in sliceDims*/
      std::set<int> dimsSet(sliceDims.begin(), sliceDims.end());
      
      if ( dimsSet.size() < sliceDims.size()) {
        throw std::invalid_argument(
          "sliceCheck error found: duplicate dimensions in sliceDims");
      }
      
      if ( dimsSet.size() >= getDimension()) {
        throw std::invalid_argument(
          "sliceCheck error found: number of dimensions to slice on >= dimensions of this");
      }
      
      
      /* check that each of the values in sliceDims is a dimension of this*/
      ivector box = getBox();
      int lb = Lb(box);
      int ub = Ub(box);  // ub-lb+1 = dim of box
      
      // make a full vector of dim reals, 0.0's in all positions
      fullSlicePts =  std::vector< cxsc::real >(ub-lb+1, real(0.0));
      
      #ifdef SLICE_OUTPUT
        std::cout << "\nin slice" << getNodeName() << std::endl;
        std::cout << "lb = " << lb << " and ub = " << ub << std::endl;
      #endif
      
      std::vector < real >::const_iterator rit = slicePts.begin();
      for ( std::vector < int >::const_iterator cit = sliceDims.begin();
          cit < sliceDims.end();
          ++cit, ++rit) {
        int d = *cit;
        #ifdef SLICE_OUTPUT
          std::cout << "checking d =" << d << std::endl;
          std::cout << "*rit =" << (*rit) << std::endl;
        #endif
          
        if (d < lb || d > ub) {
          throw std::invalid_argument(
          "sliceCheck error found: illegal dimension in sliceDims");
        }
        #ifdef SLICE_OUTPUT
          std::cout << "box[d] =" << box[d] << std::endl;
          std::cout << "(*rit) <= box[d] =" << ((*rit) <= box[d]) << std::endl;
        #endif
        real r = *rit;
        if (!(r <= box[d])) {
          throw std::invalid_argument(
          "sliceCheck error found: illegal pt in slicePts");
        }
        #ifdef SLICE_OUTPUT
          std::cout << "fullSlicePts[" << (d-lb) << "] = " << r << std::endl;
        #endif
        
        fullSlicePts[d-lb] = r;
      }
      
    } // end check at least one is non-empty
    else  { // both empty
      throw std::invalid_argument(
        "sliceCheck error found: sliceDims and slicePts both empty");
    }
    return fullSlicePts;
  }
template<typename T>
bool subpavings::MappedSPnode< T >::splitToShape ( std::string  instruction) [inline]

Splits paving according to string instruction.

The instruction specifies the required shape in terms of the depth of the leaf nodes, in left to right order. The depth of a leaf node is equivalent to the number of bisections of the root box required to make the box represented by that leaf. i.e., the root has depth 0 and if that were bisected, the root node would have two child nodes each of level 1. Bisection of any one of the boxes represented by a child would give two more children, each of level 2 (2 bisections), etc.

Leaf levels in instruction can be separated by commas, spaces, or both.

For example, an instruction string "3, 3, 2, 1" would give an SPSnode tree with 4 leaves, 2 of which would be level 3 (i.e. representing boxes resulting from 3 bisections of the root box, each of which would have volume 1/8 the size of the root box). Another leaf would represent a box resulting from 2 bisections of the root box (volume 1/4 that of the root box) and the 'right-most' leaf (in a drawing of the tree) would be the result of a single bisection of the root box and would have half the volume of the root box. This is a valid instruction string because it is possible to get leaves of those levels by a series of successive bisections of the root box and the volume of the leaves adds up to the volume of the root box.

Throws the following exceptions:

  • Throws a NoBox_Error if the box is NULL.
  • Throws a NonRootNode_Error if this is not a root node (ie if this has a parent node).
  • Throws an std::invalid_argument exception if the instruction constain invalid characters (anything other than digits, whitespace or commas).
  • Throws an std::logic_error if the instruction is valid but does not describe an achievable tree shape.
Parameters:
instructionspecifies the required shape, eg "3, 3, 2, 1".
Returns:
true if the instruction could be successfully carried out, false if the instruction could not be carried out successfully.
Precondition:
The instruction must be valid and describe an achievable tree shape. This must be a non-empty root node.
Postcondition:
getLeafNodeLevelsString() == instruction
    {
    bool success = false;

    // checks:  is this the root?
    if (NULL != parent) {
      throw NonRootNode_Error("MappedSPNodeSingleRange<T>::splitToShape(std::string)");
    }

    // checks:  is there a root box
    if (NULL == theBox) {
      throw NoBox_Error("MappedSPNodeSingleRange<T>::splitToShape(std::string)");
    }


    // checks: is the string properly formed?
    if (instruction.length() == 0) {
      throw std::invalid_argument(
      "MappedSPNodeSingleRange<T>::splitToShape(std::string) : No instruction");
    }
    std::string legal(", 0123456789");
    if (instruction.find_first_not_of(legal) != std::string::npos) {
      throw std::invalid_argument(
      "MappedSPNodeSingleRange<T>::splitToShape(std::string) : Illegal character");
    }

    // all seems to be okay, we can start spliting the root
    // specify what to look for as numbers or decimal point or + or -

    success = splitRootToShape(instruction);

    if (!success) {
      throw std::logic_error(
      "MappedSPNodeSingleRange<T>::splitToShape(std::string) : instruction not a proper tree");
      
     }
     
    return success;
   }
template<typename T>
void subpavings::MappedSPnode< T >::swapMSPSR ( MappedSPnode< T > &  spn) [inline]

Swap the properties of this and another.

The properties swapped include all the node properties like name, box, etc, and children, and the range.

Parameters:
spnthe node to swap with.
Postcondition:
this has the properties that spn had before the operation, and spn has the properties this had before the operation.
  {
    /* theBox, parent, leftChild,
    rightChild and nodeName are inherited from base class */
    SPnode::swap(spn); // use the base version
    
    std::swap(range, spn.range);
  }

The documentation for this class was generated from the following file:
 All Classes Namespaces Functions Variables Typedefs Enumerations Friends