2D Algebra Typescript Module
A library for programatically building up large systems of equations for numerical analysis.
Project is created with:
- Typescript version: 3.6.2
- Node version: 12.10.0
- No external dependencies
To use this library
npm install 2d-algebra
yarn add 2d-algebra
Then in your code you can import and use the
expression(...) function to fluently build expressions.
;const m = 3; // slopeconst b = 4; // pointconst x = Symbol"x";const y = Symbol; // naming your symbols is optionalconst line = ;const solution = x 7483 y 22453;const err = line// err === 0const dxLine = line;const xSlope = dxLine;// xSlope === 0const dyLine = line;const ySlope = dyLine;// ySlope === 0const dx2Line = dxLine;const xCup = dx2Line;// xCup > 0const dy2Line = dyLine;const yCup = dx2Line;// yCup > 0const dxdyLine = dxLine;const hessianDet = dx2Line;const xySaddle = hessianDet;// xySaddle === 0
Creating a new
Expression is a easy as starting it off with the first
const one = expression(1).eval(new Map());
From there you can use the following methods to additional complexity. All methods do not change the existing Expression but return a new Expression (AKA immutable). The
b argument must be either a
|plus(b)||add the top term to
|times(b)||multiplies the top term with b and simplifies|
|toThe(n)||raises the top term by the
|sin()||replaces the top term with the sin(a)|
|cos()||replaces the top term with the cos(a)|
Once the expression is complete you can use the following methods
|eval(Map<symbol, number>)||fully evaluate the expression. throw error if not all of the symbols are defined.|
|apply(Map<symbol, Expression>)||substitute one or more variables with expressions and return the new expression.|
|derivative(symbol)||compute the partial derivative with respect to one symbol.|
|toString()||makes a ASCII art tree diagram of the expression tree.|
Why no parentheses?
At this point you've probably run into an expression where you only want to apply the next
squared to only part of what comes before. For example the unit (of radius 1) circle one might mistakenly define it as:
const r = 1;const x = Symbol;const y = Symbol;// EXAMPLE OF HOW TO DO IT WRONGconst circle =// x^2// x^2 + y// (x^2 + y)^2// (x^2 + y)^2 - r)^2; // ((x^2 + y)^2 - r)^2)^2
((x^2 + y)^2 - r)^2)^2. When I would have expected
(x^2 + y^2 - r^2)^2. Notice how in the wrong expression each application of the
squared() applied to the whole of expression defined up to that point. To fix this I'll introduce the
push(b) method that starts a new mini expression separate from what has been defined so far. When
push is used new zero argument versions of
eq() are available to cause the two mini expressions to be merged into one again.
The corrected code now looks like:
const circle =// x^2// x^2 | y <---- y here is separate from x^2// x^2 | y^2 <---- now that y is squared on its own// x^2 + y^2 <---- merge y^2 by adding it to x^2// x^2 + y^2 | r// x^2 + y^2 | r^2; // (x^2 + y^2 - r^2)^2
To submit changes to the project
- fork and clone the git repository
- make changes to the tests and source.
- If making changes to the
Expressionclass make sure matching changes are made to
- Changes to simplification logic can be quite tricky with all the symbiotic recursion.
- If making changes to the
yarn test. if they fail goto step 2
- push changes to your fork
- submit pull request
Other ussful commands
yarn compile: compile the typescript code to POJS
yarn test: run unit tests once.
yarn watch: continuously run unit tests.