Skip to content

Commit

Permalink
WIP - Non-trivial composite function example
Browse files Browse the repository at this point in the history
  • Loading branch information
fkleon committed Apr 14, 2019
1 parent 2047d8d commit 0b04574
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 5 deletions.
17 changes: 17 additions & 0 deletions lib/src/functions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,23 @@ class CustomFunction extends MathFunction {
String toFullString() => '$name($args) = $expression';
}

class FunctionCall extends Literal {
/**
* Create a custom function with the given name, argument variables,
* and expression.
*/
FunctionCall(String name) : super(name);

@override
Expression derive(String toVar) =>
throw new UnsupportedError('Can not differentiate FunctionCall');

@override
dynamic evaluate(EvaluationType type, ContextModel context) =>
context.getFunction(this.value).evaluate(type, context.createChildScope());

}

/**
* A default function is predefined in this library.
* It contains no expression because the appropriate evaluation method usually
Expand Down
111 changes: 106 additions & 5 deletions test/expression_test_set.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ class ExpressionTests extends TestSet {
/*
'Composite Function simplification': compFuncSimplification,
'Composite Function differentiation': compFuncDifferentiation,
'Composite Function evaluation': compFunEval
*/
'Composite Function evaluation': compFunEval
};

@override
Expand Down Expand Up @@ -1093,7 +1093,7 @@ class ExpressionTests extends TestSet {
throw new UnimplementedError();
}

/// Testss REAL evaluation of custom functions: `R^n -> R`
/// Tests REAL evaluation of custom functions: `R^n -> R`
void cusFuncRealEval() {
Variable x, y, z;
CustomFunction cf;
Expand Down Expand Up @@ -1130,12 +1130,12 @@ class ExpressionTests extends TestSet {
expect(cf.evaluate(real, cm), closeTo(4.1231, 0.0001));
}

/// Testss INTERVAL evaluation of custom functions
/// Tests INTERVAL evaluation of custom functions
void cusFuncIntervalEval() {
throw new UnimplementedError();
}

/// Testss VECTOR evaluation of custom functions
/// Tests VECTOR evaluation of custom functions
void cusFuncVectorEval() {
Variable x, y;
CustomFunction cf;
Expand Down Expand Up @@ -1225,7 +1225,108 @@ class ExpressionTests extends TestSet {
/// Tests evaluation of composite functions.
void compFunEval() {
// Evaluate composite functions.
throw new UnimplementedError();
//throw new UnimplementedError();

// Custom RGB colour encoding into an Integer
Variable red = new Variable('r'),
green = new Variable('g'),
blue = new Variable('b');
List<Variable> rgb = [red, green, blue];

Variable x = new Variable('x'),
shiftIndex = new Variable('i');

// The identity function returns the input. (R^? -> R^?)
CustomFunction identity = new CustomFunction('identity', [x], x);

// Shifting to the left makes the number larger, effectively multiplying the
// number by pow(2, shiftIndex).
// (R^2 -> R)
CustomFunction leftShift = new CustomFunction('leftshift', [x, shiftIndex],
x * new Power(2, shiftIndex));

// Shifting to the right makes the number smaller and drops the least
// significant bits, effectively doing an integer division by pow(2,
// shiftIndex).
// (R^2 -> R)
CustomFunction rightShift = new CustomFunction('rightshift', [x, shiftIndex],
x / new Power(2, shiftIndex));

// Applies the identity function and a left shift.
// This allows to encode the variable x and shiftIndex in a 2-dimensional
// input vector.
// (R^2 -> R^2 -> R)
// CustomFunction parameterizedLeftShift = new CustomFunction(
// 'leftshift', [x, shiftIndex], identity & leftShift);
CompositeFunction parameterizedLeftShift = identity & leftShift;
// (parameterize) (shift) (encode)
// R^3 -> R^3 -> R^3 -> R
// Applies the identity function and a right shift.
// This allows to encode the variable x and shiftIndex in a 2-dimensional
// input vector.
// (R^2 -> R^2 -> R)
CustomFunction parameterizedRightShift = new CustomFunction(
'leftshift', [x, shiftIndex], identity & rightShift);
/*
CustomFunction vectorize1 = new CustomFunction('vectorize', rgb,
new Vector([
new BoundVariable(new Vector([red, new Number(16)])),
new BoundVariable(new Vector([red, new Number(8)])),
new BoundVariable(new Vector([red, new Number(0)])),
]));
CustomFunction vectorLeftShift = new CustomFunction('ll', [red,green,blue],
new Vector[ContextModel]
);
ContextModel cm = new ContextModel()
..bindVariable(x, new Number(150))
..bindVariable(shiftIndex, new Number(16));
double shifted24 = ls.evaluate(real, cm);
*/

parameterizedLeftShift.name = 'leftshift';
ContextModel cm = new ContextModel()
..bindVariable(red, new Number(250))
..bindVariable(green, new Number(250))
..bindVariable(blue, new Number(250))
..bindFunction(parameterizedLeftShift);
//..bindVariable(x, new Vector([red, new Number(16)]))
//..bindVariable(x, new Vector([green, new Number(8)]))
//..bindVariable(x, new Vector([blue, new Number(0)]))


double redShifted = parameterizedLeftShift.evaluate(real, cm);
print('leftShift24: $redShifted vs. x << 24: ${250 << 24}}');

double shifted16 = parameterizedLeftShift.evaluate(real,
new ContextModel()..bindVariable(x, new Vector([new Number(250), new Number(16)])));
print('leftShift16: $shifted16 vs. x << 16: ${250 << 16}}');


/*
shifted24 = leftShift.evaluate(vector,
new ContextModel()..bindVariable(x, new Vector([new Number(250), new Number(24)])));
print('leftShift24: $shifted24 vs. x << 24: ${250 << 24}}');
*/
CustomFunction vectorize = new CustomFunction('vectorize', rgb,
new Vector([
new Vector([red, new Number(16)]),
new Vector([green, new Number(8)]),
new Vector([blue, new Number(0)]),
]));
CustomFunction encode = new CustomFunction('encode', rgb, red + green + blue);

CompositeFunction rgba = vectorize & leftShift & encode;
//new CustomFunction('rgba', vars, (alpha << 24) + (red << 16) << (green << 8) + blue);
Vector encoded = rgba.evaluate(vector, new ContextModel()
..bindVariable(red, new Number(255))
..bindVariable(green, new Number(100))
..bindVariable(blue, new Number(200)));

print(encoded);
}

/// Checks if the given operator contains the given members.
Expand Down

0 comments on commit 0b04574

Please sign in to comment.