using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using System.Diagnostics.Contracts;
namespace AutoDiff
{
///
/// Represents a term after it has been compiled for efficient evaluation/differentiation.
///
[ContractClass(typeof(CompiledTermContract))]
public interface ICompiledTerm
{
///
/// Evaluates the compiled term at the given point.
///
/// The point at which to evaluate.
/// The value of the function represented by the term at the given point.
/// The number at arg[i] is the value assigned to the variable Variables[i].
double Evaluate(params double[] arg);
///
/// Computes the gradient of the compiled term at the given point.
///
/// The point at which to differentiate.
/// A tuple, where the first item is the gradient at and the second item is
/// the value at . That is, the second value is the same as running on
/// .
/// The number at arg[i] is the value assigned to the variable Variables[i].
Tuple Differentiate(T arg) where T : IList;
///
/// Computes the gradient of the compiled term at the given point.
///
/// The point at which to differentiate.
/// A tuple, where the first item is the gradient at and the second item is
/// the value at . That is, the second value is the same as running on
/// .
/// The number at arg[i] is the value assigned to the variable Variables[i].
Tuple Differentiate(params double[] arg);
///
/// The collection of variables contained in this compiled term.
///
///
/// The order of variables in this collection specifies the meaning of each argument in or
/// . That is, the variable at Variables[i] corresponds to the i-th parameter of
/// and .
///
ReadOnlyCollection Variables { get; }
}
[ContractClassFor(typeof(ICompiledTerm))]
abstract class CompiledTermContract : ICompiledTerm
{
public double Evaluate(params double[] arg)
{
Contract.Requires(arg != null);
Contract.Requires(arg.Length == Variables.Count);
return default(double);
}
public Tuple Differentiate(T arg)
where T : IList
{
Contract.Requires(arg != null);
Contract.Requires(arg.Count == Variables.Count);
Contract.Ensures(Contract.Result>() != null);
Contract.Ensures(Contract.Result>().Item1.Length == arg.Count);
return null;
}
public Tuple Differentiate(params double[] arg)
{
Contract.Requires(arg != null);
Contract.Requires(arg.Length == Variables.Count);
Contract.Ensures(Contract.Result>() != null);
Contract.Ensures(Contract.Result>().Item1.Length == arg.Length);
return null;
}
public ReadOnlyCollection Variables
{
get
{
Contract.Ensures(Contract.Result>() != null);
return null;
}
}
}
}