internal ScaleOffsetExpression(VectorParameterExpression operand, T scale, T offset) : base(UnaryElementWiseOperation.ScaleOffset, operand) { Operand = operand; Scale = scale; Offset = offset; }
public void AddBinaryElementWiseOperation <T>(VectorParameterExpression a, VectorParameterExpression b, VectorParameterExpression result, ExpressionType operation) { _operations.Add( Expression.Assign(result, Expression.MakeBinary(operation, a, b)) ); }
protected Expression VisitParameter(VectorParameterExpression variable, StringBuilder builder) { Write(variable.Name, builder); if (variable.ParameterType == Expressions.ParameterType.Argument) { Write(indexing, builder); } return(variable); }
public Expression AddInverseExpression(VectorParameterExpression a) { var paramA = a as ReferencingVectorParameterExpression <double>; if (paramA.IsScalar) { return(new ConstantExpression <double>(1 / paramA.ScalarValue)); } return(AddLocalAssignment <double>(new ScaleInverseExpression <double>(a, 1))); }
public Expression AddHalfInverseSquareRootExpression(VectorParameterExpression a) { var paramA = a as ReferencingVectorParameterExpression <double>; if (paramA.IsScalar) { return(new ConstantExpression <double>(0.5 / Math.Sqrt(paramA.ScalarValue))); } var newLocal = AddLocalAssignment <double>(new ScaleInverseExpression <double>(a, 1)); return(AddLocalAssignment <double>(new ScaleOffsetExpression <double>(newLocal, 0.5, 0))); }
/// <summary> /// Performs reverse-mode (adjoint) automatic differentiation /// </summary> /// <param name="builder"></param> /// <param name="dependentVariable"></param> /// <param name="independentVariables"></param> public static void Differentiate(BlockExpressionBuilder builder, out IList<Expression> derivativeExpressions, VectorParameterExpression dependentVariable, params VectorParameterExpression[] independentVariables) { if (independentVariables.Length == 0) { derivativeExpressions = null; return; } var block = builder.ToBlock(); // change the numbering of variables; arguments first, then locals List<int>[] jLookup; Function[] f; // we want a list of functions which can be unary or binary (in principle high order if it makes sense) and a look-up // each function is associated with a parameter, which is either an argument or a local // for each function index we return a list of the indices of the functions that reference the parameter GetFunctions(block, out f, out jLookup); int N = dependentVariable.Index; bool[] derivativeRequired; int[] derivativeExpressionIndex; IdentifyNeccesaryDerivatives(N, jLookup, independentVariables, out derivativeRequired, out derivativeExpressionIndex); // the list of operations needed to calculate the derivatives (*all* derivatives) derivativeExpressions = new Expression[independentVariables.Length]; var dxNdx = new Expression[N + 1]; dxNdx[N] = new ConstantExpression<double>(1.0); for (int i = N - 1; i >= 0; i--) { if (!derivativeRequired[i]) continue; // dxN / dxi // need to find all operation indices j such that p(j) contains i // that is, all functions that have xi as an argument (these must therefore have a higher index than i) VectorParameterExpression total = new ConstantExpression<double>(0); var xi = f[i].Parameter; //need sum of dfj/dxi dXN/dxj foreach (var j in jLookup[i]) { var fj = f[j]; var dfjdxi = Differentiate(fj, xi, builder); // dfj/dxi var dXNdxj = dxNdx[j]; // dXN/dxj var product = builder.AddProductExpression(dfjdxi, dXNdxj); total = builder.AddAdditionExpression(total, product); } dxNdx[i] = total; int targetIndex = derivativeExpressionIndex[i]; if (targetIndex != -1) derivativeExpressions[targetIndex] = total; } }
public Expression AddGaussian(VectorParameterExpression a) { var paramA = a as ReferencingVectorParameterExpression <double>; if (paramA.IsScalar) { return(new ConstantExpression <double>(_gaussianScaling * Math.Exp(-paramA.ScalarValue * paramA.ScalarValue / 2))); } var newLocal1 = AddLocalAssignment <double>(Expression.MakeBinary(ExpressionType.Multiply, paramA, paramA)); var newLocal2 = AddLocalAssignment <double>(new ScaleOffsetExpression <double>(newLocal1, -0.5, 0)); var newLocal3 = AddLocalAssignment <double>(new UnaryMathsExpression(UnaryElementWiseOperation.Exp, newLocal2)); return(AddLocalAssignment <double>(new ScaleOffsetExpression <double>(newLocal3, _gaussianScaling, 0))); }
/// <summary> /// Adds a division and negation expression efficiently; assumes that scalar independent variables can be combined /// i.e. that any differentiation has already occurred /// </summary> public Expression AddNegateDivideExpression(VectorParameterExpression a, VectorParameterExpression b) { var paramA = a as ReferencingVectorParameterExpression <double>; var paramB = b as ReferencingVectorParameterExpression <double>; if (paramA.IsScalar && paramB.IsScalar) { return(new ConstantExpression <double>( -paramA.ScalarValue / paramB.ScalarValue)); } var newLocal = AddLocalAssignment <double>(Expression.Divide(a, b)); return(AddLocalAssignment <double>(new ScaleOffsetExpression <double>(newLocal, -1, 0))); }
public VectorOperationExpression(VectorParameterExpression result) { Result = result; }
public static ScaleOffsetExpression <T> ScaleOffset <T>(VectorParameterExpression operand, T scale, T offset) { return(new ScaleOffsetExpression <T>(operand, scale, offset)); }
public static ScaleInverseExpression <T> ScaleInverse <T>(VectorParameterExpression operand, T scale) { return(new ScaleInverseExpression <T>(operand, scale)); }
public static UnaryMathsExpression MakeUnary(UnaryElementWiseOperation unaryType, VectorParameterExpression operand) { return(new UnaryMathsExpression(unaryType, operand)); }
internal UnaryMathsExpression(UnaryElementWiseOperation unaryType, VectorParameterExpression operand) { UnaryType = unaryType; Operand = operand; }
public VectorOperationExpression(VectorParameterExpression result) { Result = result; }
private static void UpdateOperationIndices(List<int>[] operationIndices, VectorParameterExpression expression, int operationIndex) { if (expression.Index != -1) operationIndices[expression.Index].Add(operationIndex); // -1 indices a constant }
private static void IdentifyNeccesaryDerivatives(int N, List<int>[] jLookup, VectorParameterExpression[] independentVariables, out bool[] derivativeRequired, out int[] derivativeExpressionIndex) { derivativeRequired = new bool[N + 1]; // true if the derivative expression is required derivativeExpressionIndex = Enumerable.Repeat(-1, N + 1).ToArray(); // the index of the independent variable that the derivative expression refers to for (int i = 0; i < independentVariables.Length; ++i) { int expessionindex = independentVariables[i].Index; derivativeExpressionIndex[expessionindex] = i; derivativeRequired[expessionindex] = true; } for (int i = 0; i < N; i++) { if (derivativeRequired[i]) { foreach (int j in jLookup[i]) { derivativeRequired[j] = true; } } } }
private static NArray <T> GetArray <T>(VectorParameterExpression expression) { return((expression as ReferencingVectorParameterExpression <T>).Array); }
internal ScaleInverseExpression(VectorParameterExpression operand, T scale) : base(UnaryElementWiseOperation.ScaleInverse, operand) { Scale = scale; }