Formula solver seems to work, now the UI should be reworked
This commit is contained in:
parent
5fabb4424c
commit
e3c5d9cef9
2 changed files with 104 additions and 38 deletions
|
|
@ -117,9 +117,7 @@ class FormulaEvaluator {
|
|||
} catch (e, stack) {
|
||||
// SPECIAL CASE: If the error message starts with signalMagicString, treat it as a signal message and return it instead of throwing an exception
|
||||
// SEE signal() function in the generated d4rt code above for how this is used
|
||||
print("#######################");
|
||||
if (e.toString().contains(signalMagicString)) {
|
||||
print("***********************");
|
||||
final signalMessage = e.toString().split(signalMagicString).last.trim();
|
||||
return signalMessage;
|
||||
}
|
||||
|
|
@ -295,6 +293,52 @@ class FormulaEvaluator {
|
|||
}
|
||||
}
|
||||
|
||||
Number formulaSolver(Formula formula,
|
||||
String variableToSolve,
|
||||
Map<String, dynamic> fixedInputValues, {
|
||||
Number hint = 0,
|
||||
Number step = 10,
|
||||
Number maxDelta = 0.01,
|
||||
int maxTries = 100,
|
||||
}) {
|
||||
|
||||
if( variableToSolve == formula.output.name ){
|
||||
return FormulaEvaluator().evaluate(formula, fixedInputValues);
|
||||
}
|
||||
|
||||
if (!formula.inputVarNames().contains(variableToSolve) ){
|
||||
throw ArgumentError(
|
||||
'Variable "$variableToSolve" is not an input or output variable of the formula "${formula
|
||||
.name}".',
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
final modifiedInputValues = Map<String, dynamic>.from(fixedInputValues);
|
||||
var evaluator = FormulaEvaluator();
|
||||
Number f(Number x) {
|
||||
modifiedInputValues[variableToSolve] = x;
|
||||
final result = evaluator.evaluate(formula, modifiedInputValues);
|
||||
if (result is Number) {
|
||||
return result;
|
||||
} else {
|
||||
throw FormulaEvaluationException(
|
||||
'Expected formula evaluation to return a number, but got: $result ${result.runtimeType}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
var fixedFormulaOutput = fixedInputValues[formula.output.name];
|
||||
|
||||
return functionSolver(
|
||||
(Number x) => f(x) - fixedFormulaOutput,
|
||||
hint: hint,
|
||||
step: step,
|
||||
maxDelta: maxDelta,
|
||||
maxTries: maxTries,
|
||||
);
|
||||
}
|
||||
|
||||
class NoSolutionException implements Exception {
|
||||
final String message;
|
||||
|
||||
|
|
|
|||
|
|
@ -5,53 +5,75 @@ import 'dart:math' as Math;
|
|||
|
||||
|
||||
void main() {
|
||||
test("Solve x^2", () {
|
||||
Number f(Number x) => x*x;
|
||||
var root = functionSolver(f, hint: 10, step: 1);
|
||||
expect(root, closeTo(0, 0.1));
|
||||
|
||||
group("Formulas", (){
|
||||
|
||||
test("Solve x^2 formula", () {
|
||||
final formula = Formula(
|
||||
name: 'Test x^2',
|
||||
input: [
|
||||
VariableSpec(name: 'x', unit: 'scalar'),
|
||||
],
|
||||
output: VariableSpec(name: 'y', unit: 'scalar'),
|
||||
d4rtCode: 'y = x*x;',
|
||||
);
|
||||
|
||||
var solution = formulaSolver(formula, "x", {"y": 25}, maxDelta: 1e-10);
|
||||
expect( solution, closeTo(5, 1e-10));
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
group('Native functions', () {
|
||||
test("Solve x^2", () {
|
||||
Number f(Number x) => x * x;
|
||||
var root = functionSolver(f, hint: 10, step: 1);
|
||||
expect(root, closeTo(0, 0.1));
|
||||
});
|
||||
|
||||
test("Solve (x-1000)^2", () {
|
||||
Number f(Number x) => (x-1000)*(x-1000);
|
||||
var root = functionSolver(f, hint: 10, step: 1, maxTries: 1000);
|
||||
expect(root, closeTo(1000, 0.1));
|
||||
});
|
||||
|
||||
test("Solve x^2 + 1", () {
|
||||
Number f(Number x) => x*x+1;
|
||||
test("Solve (x-1000)^2", () {
|
||||
Number f(Number x) => (x - 1000) * (x - 1000);
|
||||
var root = functionSolver(f, hint: 10, step: 1, maxTries: 1000);
|
||||
expect(root, closeTo(1000, 0.1));
|
||||
});
|
||||
|
||||
expect(()=> functionSolver(f, hint: 10, step: 1), throwsA(isA<NoSolutionException>()));
|
||||
});
|
||||
test("Solve x^2 + 1", () {
|
||||
Number f(Number x) => x * x + 1;
|
||||
|
||||
test("Solve (x-2)(x-10", () {
|
||||
Number f(Number x) => (x-2)*(x-10);
|
||||
expect(() => functionSolver(f, hint: 10, step: 1),
|
||||
throwsA(isA<NoSolutionException>()));
|
||||
});
|
||||
|
||||
expect( functionSolver(f, hint: 10, step: 1), closeTo(10, 0.1));
|
||||
});
|
||||
test("Solve (x-2)(x-10", () {
|
||||
Number f(Number x) => (x - 2) * (x - 10);
|
||||
|
||||
test('Solve sqrt(x) = 2 => x = 4', () {
|
||||
Number f(Number x) => Math.sqrt(x) - 2;
|
||||
var root = functionSolver(f, hint: 5, step: 1);
|
||||
expect(root, closeTo(4, 0.1));
|
||||
});
|
||||
expect(functionSolver(f, hint: 10, step: 1), closeTo(10, 0.1));
|
||||
});
|
||||
|
||||
test('Solve sin(x) = 0 near pi (hint 3)', () {
|
||||
Number f(Number x) => Math.sin(x);
|
||||
var root = functionSolver(f, hint: 3, step: 1);
|
||||
expect(root, closeTo(Math.pi, 0.01));
|
||||
});
|
||||
test('Solve sqrt(x) = 2 => x = 4', () {
|
||||
Number f(Number x) => Math.sqrt(x) - 2;
|
||||
var root = functionSolver(f, hint: 5, step: 1);
|
||||
expect(root, closeTo(4, 0.1));
|
||||
});
|
||||
|
||||
test('Solve tan(x) = 1 => x = pi/4', () {
|
||||
Number f(Number x) => Math.tan(x) - 1;
|
||||
var root = functionSolver(f, hint: 0, step: 1);
|
||||
expect(root, closeTo(Math.pi / 4, 0.01));
|
||||
});
|
||||
test('Solve sin(x) = 0 near pi (hint 3)', () {
|
||||
Number f(Number x) => Math.sin(x);
|
||||
var root = functionSolver(f, hint: 3, step: 1);
|
||||
expect(root, closeTo(Math.pi, 0.01));
|
||||
});
|
||||
|
||||
test('Solve exp(x) = 2 => x = ln(2)', () {
|
||||
Number f(Number x) => Math.exp(x) - 2;
|
||||
var root = functionSolver(f, hint: 1, step: 1);
|
||||
expect(root, closeTo(Math.log(2), 0.01));
|
||||
test('Solve tan(x) = 1 => x = pi/4', () {
|
||||
Number f(Number x) => Math.tan(x) - 1;
|
||||
var root = functionSolver(f, hint: 0, step: 1);
|
||||
expect(root, closeTo(Math.pi / 4, 0.01));
|
||||
});
|
||||
|
||||
test('Solve exp(x) = 2 => x = ln(2)', () {
|
||||
Number f(Number x) => Math.exp(x) - 2;
|
||||
var root = functionSolver(f, hint: 1, step: 1);
|
||||
expect(root, closeTo(Math.log(2), 0.01));
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue