Exemplo n.º 1
0
/**
 * Marginalise a maxsum::DiscreteFunction by averaging.
 * This function reduces the domain of inFun to that of outFun by
 * averaging, and stores the result in outFun.
 * @pre variables in domain of outFun are a subset of variables in inFun.
 * @post previous content of outFun is overwritten.
 * @post The domains of outFun and inFun remain unchanged.
 * @param[in] inFun function to marginalise
 * @param[out] outFun maxsum::DiscreteFunction in which to store result.
 * @throws maxsum::BadDomainException is the domain of outFun is not a
 * subset of inFun.
 * @see maxsum::marginal()
 * @see maxsum::minMarginal()
 * @see maxsum::maxMarginal()
 */
void maxsum::meanMarginal
(
 const DiscreteFunction& inFun,
 DiscreteFunction& outFun
)
{
   //**************************************************************************
   // Marginalise over free domain by summation
   //**************************************************************************
   marginal(inFun,add_m,outFun);

   //**************************************************************************
   // Now each element of the output is the sum over the relevant values
   // in the input function, so we need to normalise to get the average.
   //
   // Note: another way to do this would be to marginalise using a functor
   // class Mean, which is constructed using the size of the free domain, so
   // that it knows the number of values to average over. This might be
   // more numerically stable, and also only requires one pass rather than 
   // two. However, its not clear that the extra complexity would be worth it.
   //**************************************************************************
   ValType w = outFun.domainSize();
   w = w / inFun.domainSize();
   for(int k=0; k<outFun.domainSize(); ++k)
   {
      outFun(k) *= w;
   }

} // meanMarginal
Exemplo n.º 2
0
/**
 * Check that two maxsum::DiscreteFunction objects are equal within a
 * specified tolerance. This function returns true if and only if, for all
 * <code>k</code>:
 * <p>
 * <code>
 * -tol < 1-f1(k)/f2(k) < tol
 * </code>
 * </p>
 * @param[in] f1 First function to compare
 * @param[in] f2 Second function to compare
 * @param[in] tol tolerance used for comparing values
 * @see maxsum::DEFAULT_VALUE_TOLERANCE
 */
bool maxsum::equalWithinTolerance
(
 const DiscreteFunction& f1,
 const DiscreteFunction& f2,
 ValType tol
)
{
   //***************************************************************************
   // Iterator over the combined domain of f1 and f2
   //***************************************************************************
   DomainIterator it(f1);
   it.addVars(f2.varBegin(),f2.varEnd());
   while(it.hasNext())
   {
      //************************************************************************
      // Check that the difference in value for the current positions are
      // equal within tolerance.
      //************************************************************************
      ValType diff = 1-f1(it)/f2(it);
      if( (diff > tol) || (diff < -tol) )
      {
         return false;
      }

      ++it;

   } // for loop

   //***************************************************************************
   // If we get to here, everything is equal within tolerance
   //***************************************************************************
   return true;

} // function equalWithinTolerance
void updateDiscreteFunction(const Expr& newVals, Expr old)
{
    const DiscreteFunction* in = DiscreteFunction::discFunc(newVals);
    TEST_FOR_EXCEPT(in==0);
    DiscreteFunction* out = DiscreteFunction::discFunc(old);
    TEST_FOR_EXCEPT(out==0);
    Vector<double> vec = in->getVector();
    out->setVector(vec);
}
Exemplo n.º 4
0
/**
 * Check that two maxsum::DiscreteFunction objects have the same domain.
 * Two functions have the same domain, if they depend on the same set of
 * variables.
 * @param[in] f1 First function to compare
 * @param[in] f2 Second functions to compare
 * @returns true if both function have the same domain.
 */
bool maxsum::sameDomain(const DiscreteFunction& f1, const DiscreteFunction& f2)
{
   if(f1.noVars()!=f2.noVars())
   {
      return false;
   }

   return std::equal(f1.varBegin(),f1.varEnd(),f2.varBegin());

} // function sameDomain
Exemplo n.º 5
0
Precision Stencil::apply(
        const DiscreteFunction& u,
        const Position pos,
        const Index sx,
        const Index sy) const
{
    const Index nx = u.getNx();
    const Index ny = u.getNy();
    const Precision hx = u.getHx();
    const Precision hy = u.getHy();
    const Point origin = u.getOrigin();
    NumericArray opL = getL(pos,sx,sy,nx,ny,hx,hy,origin);
    PositionArray jX = getJx(pos,nx,ny);
    PositionArray jY = getJy(pos,nx,ny);
    Precision result = 0.0;
    for (Index i = 0; i<opL.size(); ++i)
        result+=opL[i]*u(sx+jX[i],sy+jY[i]);
    return result;
}
Exemplo n.º 6
0
/**
 * Construct Domain Iterator using domain of a given function.
 * This is more efficient that creating from sratch.
 * @param[in] fun Function whose domain should be copied.
 */
DomainIterator::DomainIterator(const DiscreteFunction& fun)
   : vars_i(fun.varBegin(),fun.varEnd()),    // copy variables
     subInd_i(fun.noVars(),0),               // set all subindices to zero
     ind_i(0),                               // set linear index to zero
     fixed_i(fun.noVars(),false),            // all variables are initially free
     sizes_i(fun.sizeBegin(),fun.sizeEnd()), // copy variable sizes
     finished_i(false)                       // iterator is not done yet
   {}                   // nothing left to do in constructor body
Exemplo n.º 7
0
/**
 * Returns the element-wise maximum of this function and a specified
 * scalar. That is, if M = N.max(s) then M(k)=max(N(k),s).
 * @param[in] s the scalar value to compare
 * @param[out] result the result of the operation.
 */
void DiscreteFunction::max(const ValType s, DiscreteFunction& result)
{

// If possible use eigen array op
#if ((EIGEN_WORLD_VERSION == 3) && (EIGEN_MAJOR_VERSION >= 1)) || (EIGEN_WORLD_VERSION > 3)
   result.values_i = this->values_i.max(s);

// Otherwise use basic implementation
#else
    result = *this;
    for(int k=0; k<result.domainSize(); k++)
    {
        result(k) = (s > result(k)) ? s : result(k);
    }

#endif

} // max
Exemplo n.º 8
0
/**
 * Make the domain of this function include the domain of another.
 * If necessary, the domain of this function is expanded to include the
 * domain of the parameter fun.
 * @param[in] fun function whose domain we want to expand to.
 * @todo Make this more efficient by using fun.size_i cache.
 * @post domain of this is union of its previous domain, with that of fun.
 */
void DiscreteFunction::expand(const DiscreteFunction& fun)
{
   this->expand(fun.varBegin(),fun.varEnd());
}
Exemplo n.º 9
0
int testMarginals(const DiscreteFunction inFun)
{
   int errorCount = 0;

   //***************************************************************************
   // Calculate aggregates over entire domain of input function
   //***************************************************************************
   double mean=0;
   double max=-DBL_MAX;
   double maxnorm=-DBL_MAX;
   long argmax=-1;
   double domainSize = inFun.domainSize();
   for(int k=0; k<inFun.domainSize(); ++k)
   {
      double val = inFun(k);
      double absVal = std::fabs(val);
      mean += val / domainSize;

      if(maxnorm<absVal)
      {
         maxnorm=absVal;
      }

      if(max<val)
      {
         max=val;
         argmax=k;
      }

   } // for loop

   //***************************************************************************
   // Check results for consistency
   //***************************************************************************
   const double funMean = inFun.mean();
   const double funMax = inFun.max();
   const double funMaxnorm = inFun.maxnorm();
   const long funArgMax = inFun.argmax();

   if(!nearlyEqual_m(max,funMax))
   {
      std::cout << "max: " << funMax << " should be " << max << '\n';
      ++errorCount;
   }

   if(!nearlyEqual_m(mean,funMean))
   {
      std::cout << "mean: " << funMean << " should be " << mean << '\n';
      ++errorCount;
   }

   if(!nearlyEqual_m(maxnorm,funMaxnorm))
   {
      std::cout << "maxnorm: " << funMaxnorm << " should be "
         << maxnorm << '\n';
      ++errorCount;
   }

   if(funArgMax!=argmax)
   {
      std::cout << "argmax: " << funArgMax << " should be " << argmax << '\n';
      ++errorCount;
   }

   //***************************************************************************
   // Return number of errors
   //***************************************************************************
   return errorCount;

} // testMarginals
double FunctionalEvaluator::fdGradientCheck(double h) const
{
  bool showAll = false;
  Tabs tabs;
  double f0, fPlus, fMinus;
  Expr gradF0 = evalGradient(f0);

  FancyOStream& os = Out::os();


  DiscreteFunction* df = DiscreteFunction::discFunc(varValues_);
  DiscreteFunction* dg = DiscreteFunction::discFunc(gradF0);
  Vector<double> x = df->getVector();
  Vector<double> x0 = x.copy();
  Vector<double> gf = dg->getVector();

  RCP<GhostView<double> > xView = df->ghostView();
  RCP<GhostView<double> > gradF0View = dg->ghostView();


  TEUCHOS_TEST_FOR_EXCEPTION(xView.get() == 0, std::runtime_error, 
    "bad pointer in FunctionalEvaluator::fdGradientCheck");
  TEUCHOS_TEST_FOR_EXCEPTION(gradF0View.get() == 0, std::runtime_error, 
    "bad pointer in FunctionalEvaluator::fdGradientCheck");

  int nTot = x.space().dim();
  int n = x.space().numLocalElements();
  int lowestIndex = x.space().baseGlobalNaturalIndex();

  os << tabs << "doing fd check:  h=" << h << std::endl;
  Array<double> df_dx(n);

  int localIndex = 0;
  for (int globalIndex=0; globalIndex<nTot; globalIndex++)
  {
    double tmp=0.0;
    bool isLocal = globalIndex >= lowestIndex 
      && globalIndex < (lowestIndex+n);
    if (isLocal)
    {
      tmp = xView->getElement(globalIndex);
      loadable(x)->setElement(globalIndex, tmp + h);
    }

    df->setVector(x);
    fPlus = evaluate();
    if (isLocal)
    {
      loadable(x)->setElement(globalIndex, tmp - h);
    }

    df->setVector(x);
    fMinus = evaluate();
      
    if (isLocal)
    {
      df_dx[localIndex] = (fPlus - fMinus)/2.0/h;
      os << "g=" << setw(5) << globalIndex << ", l=" << setw(5) << localIndex << " f0="
         << setw(12) << f0 
         << " fPlus=" << setw(12) << fPlus << " fMinus=" << setw(12) << fMinus << " df_dx="
         << setw(12) << df_dx[localIndex] << std::endl;
      if (showAll)
      {
        os << "i " << globalIndex << " x_i=" << tmp 
           << " f(x)=" << f0 
           << " f(x+h)=" << fPlus 
           << " f(x-h)=" << fMinus << std::endl;
      }
      loadable(x)->setElement(globalIndex, tmp);
      localIndex++;
    }
    df->setVector(x);
  }
  
  double localMaxErr = 0.0;

  showAll = true;
  VectorSpace<double> space = x.space();
  for (int i=0; i<space.numLocalElements(); i++)
  {
    double num =  fabs(df_dx[i]-gf[i]);
    double den = fabs(df_dx[i]) + fabs(gf[i]) + 1.0e-14;
    double r = 0.0;
    if (fabs(den) > 1.0e-16) r = num/den;
    else r = 1.0;
    if (showAll)
    {
      os << "i " << i;
      os << " FD=" << df_dx[i] 
         << " grad=" << gf[i]
         << " r=" << r << std::endl;
    }
    if (localMaxErr < r) localMaxErr = r;
  }
  os << "local max error = " << localMaxErr << std::endl;
  
  double maxErr = localMaxErr;
  df->mesh().comm().allReduce((void*) &localMaxErr, (void*) &maxErr, 1, 
    MPIDataType::doubleType(), MPIOp::maxOp());
  os << tabs << "fd check: max error = " << maxErr << std::endl;

  return maxErr;
}
Exemplo n.º 11
0
/**
 * Accessor method for factor function.
 * @param[in] id the unique identifier of the desired factor.
 * @param[in] factor the function representing this factor.
 * @returns a reference to the function associated with the factor with
 * unique identifier <code>id</code>.
 * @post A copy of <code>factor</code> is stored internally by
 * this maxsum::MaxSumController and used to form part of a factor graph.
 * @post Any previous value of the specified factor is overwritten.
 */
void MaxSumController::setFactor(FactorID id, const DiscreteFunction& factor)
{
   //***************************************************************************
   // Set the specified factor. (Note: oldValue is created automatically if
   // necessary).
   //***************************************************************************
   DiscreteFunction& oldValue = factors_i[id];

   //***************************************************************************
   // If this factor is currently related to any variables that it is no
   // longer related to, delete the appropriate edges.
   //***************************************************************************
   std::vector<VarID> toRemove(oldValue.noVars());
   std::set_difference(oldValue.varBegin(),oldValue.varEnd(),
         factor.varBegin(),factor.varEnd(),toRemove.begin());

   for(std::vector<VarID>::const_iterator it=toRemove.begin();
         it!=toRemove.end(); ++it)
   {
      //************************************************************************
      // Remove the redundant edges from the postoffice graphs
      //************************************************************************
      fac2varMsgs_i.removeEdge(id,*it);
      var2facMsgs_i.removeEdge(*it,id);

      //************************************************************************
      // If the variable is no longer related to any factors, then we remove
      // it from the value list.
      //************************************************************************
      if(!var2facMsgs_i.hasSender(*it))
      {
         values_i.erase(*it);
      }

   } // for loop

   //***************************************************************************
   // For each variable in this factor's domain
   //***************************************************************************
   for(DiscreteFunction::VarIterator it=factor.varBegin();
         it!=factor.varEnd(); ++it)
   {
      //************************************************************************
      // Initialise input and output messages between the factor and
      // the current variable
      //************************************************************************
      DiscreteFunction msgTemplate(*it,0);
      fac2varMsgs_i.addEdge(id,*it,msgTemplate);
      var2facMsgs_i.addEdge(*it,id,msgTemplate);

      //************************************************************************
      // Touch the variable to ensure that it is in the value list.
      //************************************************************************
      ValueMap::iterator pos = values_i.find(*it);
      if(values_i.end()==pos)
      {
         values_i[*it]=0;
      }

   } // for loop

   //***************************************************************************
   // Set the specified factor to its new value.
   //***************************************************************************
   factors_i[id] = factor;

   //***************************************************************************
   // Tell everyone to recheck their mail. Telling everyone to recheck is the
   // safest option, because the factor graph may have changed.
   //***************************************************************************
   var2facMsgs_i.notifyAll();

} // function setFactor