Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

#163 - Better sum-product factoring steps #210

Merged
merged 10 commits into from Aug 9, 2017

Conversation

alainakafkes
Copy link
Contributor

Following the conventions used in addConstantFractions.js, I broke down factorQuadratic into 3 substeps:

  • Break apart the middle term into two terms using our factor pair (p and q): ax^2 + bx + c --> ax^2 + px + qx + c
  • Factor both groups separately: first group as [ux(rx + s)] and second group as [v(rx + s)]
  • Finish factoring by combining the factored terms through grouping: (ux + v)(rx + s)

Please let me know if there are any problems and how I can fix them! 馃槉

Copy link
Contributor

@evykassirer evykassirer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great! Just left a few small comments

I'd love to see some new tests showing how this works - there are some tests already that test substeps (the fractions code you were basing this off of probably has some!) so you can do some stuff similar to that!

lemme know if you have any questions ^_^

// TODO: these should be actual substeps
// 1. Break apart the middle term into two terms using our factor pair (p and q):
// e.g. ax^2 + bx + c -> ax^2 + px + qx + c
// TODO: these should be actual substeps *alaina*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can get rid of this TODO now that it's done 馃帀 :D

let status;

// 1. Break apart the middle term into two terms using our factor pair
// (p and q)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's a bit redundant to put the steps above and also here - I could see putting them in detail at the beginning (so you can see them all together) and then just // STEP 1 above step 1 for example - but putting each detailed comment above each step is also fine.

The way you have it here probably is also fine (yay comments) so feel to disagree

const pValue = pair[0];
const qValue = pair[1];

// SUBSTEP: ax^2 + bx + c -> ax^2 + px + qx + c
const sq = Node.Creator.constant(2);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sq was confusing for me as I read it over, at first - maybe define it right before you create the node that uses it, or rename it to two or just put it right in the other creator function Node.Creator.polynomialTerm(symbol, Node.Creator.constant(2), a); or some combination of those ^_^

const qx = Node.Creator.polynomialTerm(symbol, null, q);
newNode = Node.Creator.operator('+', [ax2, px, qx, c], true);
status = Node.Status.nodeChanged(
ChangeTypes.SIMPLIFY_ARITHMETIC, node, newNode);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd make a new change type for this since it's a pretty unique use case and it'd be nice to describe it more accurately :)

substeps.push(status);
newNode = Node.Status.resetChangeGroups(status.newNode);

// 2. Consider the first two terms together and the second two terms
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find it odd how we point this out in the code but not in the steps we show. I think we should either wrap them in parens (ax^2 + px) + (qx + c) and make it a step, or take out references to it in the code and change 'Factor the first grouptoFactor the first two terms` or something

Not your fault - you did what it said - just leftover thinking about Ahmed's planning as we move into concrete substeps ^_^

@@ -249,6 +276,7 @@ function factorSumProductRule(node, symbol, aValue, bValue, cValue, negate) {
const firstParen = Node.Creator.parenthesis(
Node.Creator.operator('+', [rx, s]));

// 3B. Factor the second group
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if it'd be better to factor the first group and second group in two different substeps instead of the same one - what do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree! I'm going to implement this.

@@ -262,8 +290,17 @@ function factorSumProductRule(node, symbol, aValue, bValue, cValue, negate) {
const secondParen = Node.Creator.parenthesis(
Node.Creator.operator('+', [ux, v]));

// SUBSTEP: ux(rx + s) + v(rx + s)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you do a before -> after here too like you did above? :D

(and add it below too)

const pValue = pair[0];
const qValue = pair[1];

// SUBSTEP: ax^2 + bx + c -> ax^2 + px + qx + c
const sq = Node.Creator.constant(2);
const a = Node.Creator.constant(aValue);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there are some edge cases to consider here - the only one I can think of off the top of my head is that 'a' could defs be 1 here (i.e. x^2 + bx + c) - maybe poke around a bit in the logic that calls this code to see what is for sure defined and what isn't? I'll think a bit more about this too

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I'm a bit confused by this. What would be the problem when a = 1?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh I think in that case you'd end up with a step like 1x^2 + 2x + 3x + 6 or something, where the 1 shouldn't actually be there

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@evykassirer I think based on the tests I wrote, that extra "1" coefficient doesn't show up in front of x^2. Let me know if I've misunderstood!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh cool that must be handled somewhere else in the code then!

yay tests and yay code that just does what it should 馃帀


// e.g. 2 + x + 3 + x -> 5 + 2x
COLLECT_AND_COMBINE_LIKE_TERMS: 'COLLECT_AND_COMBINE_LIKE_TERMS',
// e.g. x + 2 + x^2 + x + 4 -> x^2 + (x + x) + (4 + 2)
COLLECT_LIKE_TERMS: 'COLLECT_LIKE_TERMS',
// e.g. 2x^2 + 4x + 2 -> 2x^2 + 2x + 2x + 2
BREAK_UP_TERM: 'BREAK_UP_TERM',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might make more sense to put this rule where the factoring changegroups are, since that helps give context into what it's used for

const px = Node.Creator.polynomialTerm(symbol, null, p);
const qx = Node.Creator.polynomialTerm(symbol, null, q);

// SUBSTEP: ax^2 + bx + c -> ax^2 + px + qx + c
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mrah sorry for not commenting on this last time, but I think it's confusing to say substep after step - I think just merge them into one comment at the top

// SUBSTEP 1: ax^2 + bx + c -> ax^2 + px + qx + c
...
// SUBSTEP 2 ...

does that make sense?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I can see that... Oops 馃槺

@aelnaiem
Copy link
Collaborator

aelnaiem commented Aug 3, 2017

Dope!

@alainakafkes
Copy link
Contributor Author

Okay @evykassirer I think I addressed all of your requested changes! 馃帀 Please let me know if I should make any more.

@evykassirer
Copy link
Contributor

changes look great! just one unaddressed comment I commented on

also

I'd love to see some new tests showing how this works - there are some tests already that test substeps (the fractions code you were basing this off of probably has some!) so you can do some stuff similar to that!

'(x - 1) * (x + 2)']
],
['-x^2 - 3x - 2',
['x^2 + x + 2x + 2', // per factorQuadratic, negative is added back in at the end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oo good test

this made sense when we didn't have substeps - here can we wrap all the substeps in unary minus?

the substeps should probably look like:

-x^2 - 3x - 2
- (x^2 + 3x + 2)
- ((x^2 + x) + (2x + 2))
- (x * (x + 1) + (2x + 2))
....
- (x * (x + 1) + 2 * (x + 1))
- -(x + 1) * (x + 2)

what do you think? sorry I keep asking you to do more things hehe

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lol it's ok! So I wasn't sure what to do here when I wrote this test. I knew that the negative sign would be added back at the end, but I didn't know how to convey that in the test case.

When I tried what you just suggested, I got this error from deepEqual. Should I leave what I had or does this point to a deeper problem with deepEqual?
screen shot 2017-08-09 at 1 51 26 pm

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mm so I think the unary minus just gets dropped in the code right now (unless I'm missing something) so you'd wanna go in and update the code when making the steps to add the unary minus bit around each substep if needed

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

edge casssesssss

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes that makes much more sense. 馃槀 Looks I just had to negate each newNode along the way.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sweet - not too bad of a fix then whew

'(x^2 + x) + (2x + 2)',
'x * (x + 1) + (2x + 2)',
'x * (x + 1) + 2 * (x + 1)',
'(x + 1) * (x + 2)']
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

eee this is awesome look at this sum product rule awesomeness

Copy link
Contributor

@evykassirer evykassirer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

YAY this is awesome thanks @alainakafkes :D

@evykassirer evykassirer merged commit c7d1f48 into google:master Aug 9, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants