nicolewhite / algebra.js

Build, display, and solve algebraic equations.
http://algebra.js.org
MIT License
1.34k stars 111 forks source link

Simplification Options #4

Open nicolewhite opened 9 years ago

nicolewhite commented 9 years ago

Allow the user to display intermediate steps when building expressions. The plan is to add a simplify argument to all Expression operations, where setting simplify to false yields an unsimplified expression:

Expression.add(a, simplify);
Expression.subtract(a, simplify);
Expression.multiply(a, simplify);
Expression.divide(a, simplify);
Expression.pow(a, simplify);
var exp = new Expression("x").add(2);
console.log(exp.toString());

exp = exp.add("x", false);
console.log(exp.toString());
x + 2
x + x + 2

Then, add a simplify method.

exp = exp.simplify()
console.log(exp.toString());
2x + 2

Adding constants can also receive this argument.

exp = exp.add(4, false);
console.log(exp.toString());
2x + 2 + 4

And simplifying will combine these constants.

exp = exp.simplify()
console.log(exp.toString());
2x + 6

For multiplication:

exp = exp.multiply(5, false);
console.log(exp.toString());

This will yield something like:

5 * 2x + 5 * 6
exp = exp.simplify()
console.log(exp.toString());
10x + 30

I also want to add this argument to Fraction operations, so that any fraction manipulation that occurs within Expression operations also receives the simplify=false argument. Then you can display unreduced fractions.

exp = exp.divide(5, false);
console.log(exp.toString());
10/5x + 30/5
exp = exp.simplify();
console.log(exp.toString());
2x + 6
kevinbarabash commented 9 years ago

For the purposes of using this in tutorials it would be nice if there was an option to prevent any simplification when performing operations, e.g.

// assume exp = 2x + 6

exp = exp.multiply(5, false);
console.log(exp.toString());  // 5 * (2x + 6)

op = exp.query("*");
exp = exp.simplify(op);
console.log(exp.toString());  // 5 * 2x + 5 * 6

ops = exp.queryAll("*");
exp = exp.simplify(ops);
console.log(exp.toString());  // 10x + 30
nicolewhite commented 9 years ago

I definitely like the idea of choosing which operation to simplify by. You can follow the development of this over on the simplify branch.

nicolewhite commented 9 years ago

I'm thinking I'll use \cdot for the multiplication symbol in .toTex, unless you think it should be \times.

kevinbarabash commented 9 years ago

I think \cdot makes sense as a default with an option to use \times by passing an options dictionary to .toTex. \times probably won't be used that much, but it's easy to implement and it sets a precedent in terms how other rendering options should be implemented. Personally, I like using parentheses for multiplication.

nicolewhite commented 9 years ago

Even in the case of e.g. 5(2x)?

ivanistheone commented 9 years ago

I'm for \cdot over \times in general. It would be bonus points to allow an optional \times for kids in 5th grade and younger (this was the style guide at KA). This is not super important though, so rather keep the code simple and just use \cdot instead of making this customizable.

When possible e.g. in front of bracket like x(y+3), multiplication should be left implicit. In general with vars are easy to denote with implicit: 3 \cdot a \cdot b is better as 3ab, but it gets tricky with numerals like 5(2x) should it be 5\cdot 2 \cdot x or 5\cdot 2x? Not sure.

kevinbarabash commented 9 years ago

5(2x) but not usually not (5)(2x) and most definitely not (5)(2)(x) unless I was trying to make some point about commutativity which is really an edge case so I wouldn't worry about it. @ivanistheone's suggestion of keeping multiplication implicit is a good rule of thumb. The reason why I'm not a big fan of \cdot for multiplication is that it's also used for the dot product which is a different operation.

nicolewhite commented 9 years ago

FYI, I've started working on the next step of this, namely the ability to have parentheses around unsimplified multiplications.

var exp = new Expression("x").add(2); // x + 2
exp = exp.multiply(5, false); // 5(x + 2)

I also want to add more granular simplification options, so that you can do something like:

exp = exp.simplify(???); // 5x + 5 * 2
exp = exp.simplify(???); // 5x + 10

Though I'm uncertain how I'll go about that.