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

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more