Public
Edited
Feb 25, 2021
Insert cell
Insert cell
md`
- Basic expression rewriting:
+ ${tex`surjective(x, y, f) \leftrightarrow \forall y : Y, \exist x : X, f(x) = y`}
+ ${tex`injective(x_1, x_2, f) \leftrightarrow \forall x_1, x_2 : X, f(x_1) = f(x_2) \rightarrow x_1 = x_2 `}
- Resolving in space of function classes: if ${tex`S = \{g_1, g_2, g_3, \dots\}`} then ${tex`f \circ S (x)`} can be
+ ${tex`f \circ g_1 (x)`}
+ ${tex`f \circ g_2 (x)`}
+ ${tex`f \circ g_3 (x)`}
+ ${tex`\dots`}
-

`
Insert cell
Insert cell
class Expr {
constructor(root) {
if (!(root instanceof Array)) throw errors.inputMustBeArray;
this.root = root;
}
// Evaluating expression
eval() {
if (this.root === undefined || this.root.length === 0) throw errors.emptyRoot;
const first = this.root[0];
const rest = this.root.slice(1);
if (first instanceof Operation) {
const operation = first;
if (rest.length !== operation.types.length - 1) {
throw errors.wrongArgumentsLength(operation);
}
return operation.body.apply(null, rest.map(expr => expr.eval()));
} else if (first instanceof Constant) {
return first.eval();
} else {
throw errors.notImplemented;
}
}
// Checking expression types and length of arguments array (no throws)
check() {
}
}
Insert cell
{
const examples = [
new Expr([
operations.add,
new Expr([operations.mul, new Constant(10, T.nat), new Constant(20, T.nat)]),
new Constant(7, T.nat),
]),
new Expr([
new Constant(-100, T.nat), // check must be failed, because forall x : nat, x >= 0
]),
new Expr([
operations.sin,
new Constant(-100, T.int) // check failed wrong type
]),
new Expr([
operations.or,
new Constant(1, T.bool), // Constant constructor change 1 -> true, and check will work
new Constant(false, T.bool),
]),
];
const methodNames = ["eval", "check"];
const out = {};
for (const methodName of methodNames) {
out[methodName] = examples.map(expr => expr[methodName]());
}
return out;
}
Insert cell
Expr.prototype

Insert cell
Insert cell
Insert cell
operations = ({
sin: new Operation({ name: "sin", id: 0, types: [T.float, T.float], body: x => Math.sin(x) }),
cos: new Operation({ name: "cos", id: 1, types: [T.float, T.float], body: x => Math.cos(x) }),
sqrt: new Operation({ name: "sqrt", id: 2, types: [T.float, T.float], body: x => Math.sqrt(x) }),
add: new Operation({ name: "add", id: 3, types: [T.nat, T.nat, T.nat], body: (x, y) => x + y }),
mul: new Operation({ name: "mul", id: 4, types: [T.nat, T.nat, T.nat], body: (x, y) => x * y }),
and: new Operation({ name: "and", id: 5, types: [T.bool, T.bool, T.bool], body: (x, y) => x && y }),
or: new Operation({ name: "or", id: 6, types: [T.bool, T.bool, T.bool], body: (x, y) => x || y }),
pi: new Operation({ name: "pi", id: 7, types: [T.float], body: () => Math.PI}),
})
Insert cell
function Operation(options) {
Object.assign(this, options);
}
Insert cell
Insert cell
errors = ({
notImplemented: "Not implemented",
inputMustBeArray: "Input must be array",
emptyRoot: "Empty root",
assertionError: "Assertion error",
wrongArgumentsLength: (op) => `Wrong length of arguments list. ${op.name} : ${typesToString(op.types)}`
})
Insert cell
function typesToString(types) {
return `${types.map(n => T[n]).join(' -> ')}`;
}
Insert cell
testObjectAssign()
Insert cell
Insert cell
assert(expressionFromList(["add", ["mul", 10, 20], 3]).eval() === 203)
Insert cell
Insert cell
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more