using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics.Contracts; namespace AutoDiff { /// /// A collection of static methods to build new terms /// public static class TermBuilder { /// /// Builds a new constant term. /// /// The constant value /// The constant term. public static Term Constant(double value) { Contract.Ensures(Contract.Result() != null); if (value == 0) return new Zero(); else return new Constant(value); } /// /// Builds a sum of given terms. /// /// The collection of terms in the sum. /// A term representing the sum of the terms in . public static Sum Sum(IEnumerable terms) { Contract.Requires(terms.Where(term => !(term is Zero)).Count() >= 2); // require at-least two non-zero terms. Contract.Requires(Contract.ForAll(terms, term => term != null)); Contract.Ensures(Contract.Result() != null); terms = terms.Where(term => !(term is Zero)); return new Sum(terms); } /// /// Builds a sum of given terms. /// /// The first term in the sum /// The second term in the sum /// The rest of the terms in the sum. /// A term representing the sum of , and the terms in . public static Sum Sum(Term v1, Term v2, params Term[] rest) { Contract.Requires(v1 != null); Contract.Requires(v2 != null); Contract.Requires(Contract.ForAll(rest, term => term != null)); Contract.Ensures(Contract.Result() != null); var allTerms = new Term[] { v1, v2 }.Concat(rest); return Sum(allTerms); } /// /// Builds a product of given terms. /// /// The first term in the product /// The second term in the product /// The rest of the terms in the product /// A term representing the product of , and the terms in . public static Term Product(Term v1, Term v2, params Term[] rest) { Contract.Requires(v1 != null); Contract.Requires(v2 != null); Contract.Requires(Contract.ForAll(rest, term => term != null)); Contract.Ensures(Contract.Result() != null); var result = new Product(v1, v2); foreach (var item in rest) result = new Product(result, item); return result; } /// /// Builds a power terms given a base and a constant exponent /// /// The power base term /// The exponent /// A term representing t^power. public static Term Power(Term t, double power) { Contract.Requires(t != null); Contract.Ensures(Contract.Result() != null); return new ConstPower(t, power); } /// /// Builds a power term given a base term and an exponent term. /// /// The base term /// The exponent term /// public static Term Power(Term baseTerm, Term exponent) { Contract.Requires(baseTerm != null); Contract.Requires(exponent != null); Contract.Ensures(Contract.Result() != null); return new TermPower(baseTerm, exponent); } /// /// Builds a term representing the exponential function e^x. /// /// The function's exponent /// A term representing e^arg. public static Term Exp(Term arg) { Contract.Requires(arg != null); Contract.Ensures(Contract.Result() != null); return new Exp(arg); } /// /// Builds a term representing the natural logarithm. /// /// The natural logarithm's argument. /// A term representing the natural logarithm of public static Term Log(Term arg) { Contract.Requires(arg != null); Contract.Ensures(Contract.Result() != null); return new Log(arg); } /// /// Constructs a 2D quadratic form given the vector components x1, x2 and the matrix coefficients a11, a12, a21, a22. /// /// First vector component /// Second vector component /// First row, first column matrix component /// First row, second column matrix component /// Second row, first column matrix component /// Second row, second column matrix component /// A term describing the quadratic form public static Term QuadForm(Term x1, Term x2, Term a11, Term a12, Term a21, Term a22) { Contract.Requires(x1 != null); Contract.Requires(x2 != null); Contract.Requires(a11 != null); Contract.Requires(a12 != null); Contract.Requires(a21 != null); Contract.Requires(a22 != null); Contract.Ensures(Contract.Result() != null); return Sum(a11 * Power(x1, 2), (a12 + a21) * x1 * x2, a22 * Power(x2, 2)); } } }