From d9985edf5f21b8171a41266a58b0bc100f516578 Mon Sep 17 00:00:00 2001 From: PawelGt Date: Mon, 27 Jun 2016 19:04:07 +0200 Subject: [PATCH] Added Expander and ExpanderTests --- .../jagiellonian/implementation/Expander.java | 149 ++++++++++++++++++ .../interfaces/ITreeExpression.java | 7 + .../TreeExpressionExpanderTest.java | 115 ++++++++++++++ 3 files changed, 271 insertions(+) create mode 100644 src/main/java/pl/jagiellonian/implementation/Expander.java create mode 100644 src/test/java/pl/jagiellonian/TreeExpressionExpanderTest.java diff --git a/src/main/java/pl/jagiellonian/implementation/Expander.java b/src/main/java/pl/jagiellonian/implementation/Expander.java new file mode 100644 index 0000000..87b5288 --- /dev/null +++ b/src/main/java/pl/jagiellonian/implementation/Expander.java @@ -0,0 +1,149 @@ +package pl.jagiellonian.implementation; + +import pl.jagiellonian.interfaces.ITreeExpression; +import pl.jagiellonian.interfaces.IVariable; +import pl.jagiellonian.utils.Operation; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +public class Expander { + + /** + * @param iTreeExpression - {@link ITreeExpression} expression to expand + * @return {@link ITreeExpression} expanded polynomial + */ + public ITreeExpression expand(ITreeExpression iTreeExpression) { + return divideIntoMonomials(iTreeExpression); + } + + private ITreeExpression divideIntoMonomials(ITreeExpression iTreeExpression) { + ITreeExpression child0 = (ITreeExpression) iTreeExpression.getChildren().get(0); + ITreeExpression child1 = (ITreeExpression) iTreeExpression.getChildren().get(1); + + List firstList; + List secondList = convertToDoubleArray(new ArrayList<>(), 0, child1); + + if(isMultiplication(child0)) { + firstList = convertToDoubleArray(new ArrayList<>(), 0, divideIntoMonomials(child0)); + } + else { + firstList = convertToDoubleArray(new ArrayList<>(), 0, child0); + } + + return convertToTreePolynomial(multiplyCoefficients(firstList, secondList)); + } + + private boolean isMultiplication(ITreeExpression iTreeExpression) { + return iTreeExpression.getOperation() == Operation.MULT; + } + + + private List convertToDoubleArray(List list, int depth, ITreeExpression iTreeExpression) { + List listChildren = iTreeExpression.getChildren(); + + if(depth == 0) { //wyraz wolny + Operation sign = iTreeExpression.getOperation(); + IVariable iVariable = listChildren.get(1); + double doubleVar = Double.parseDouble(iVariable.toString()); + if(sign == Operation.SUB) { + doubleVar = - doubleVar; + } + list.add(doubleVar); + ITreeExpression next = (ITreeExpression) listChildren.get(0); + convertToDoubleArray(list, ++depth, next); + } + else if (depth == 1) { // x + ITreeExpression ite = (ITreeExpression) iTreeExpression.getChildren().get(0); + if(isNumber(ite)) { + list.add(Double.parseDouble(ite.getAllNodes().get(0).toString())); + } + else { + ITreeExpression var = (ITreeExpression) listChildren.get(1); + list.add(Double.parseDouble(var.getAllNodes().get(0).toString())); + ITreeExpression next = (ITreeExpression) listChildren.get(0); + convertToDoubleArray(list, ++depth, next); + } + } + else { + if(listChildren.size() == 1) { + ITreeExpression ite = (ITreeExpression) iTreeExpression.getChildren().get(0); + ITreeExpression var1 = (ITreeExpression) ite.getChildren().get(0); + list.add(Double.parseDouble(var1.getAllNodes().get(0).toString())); + return list; + } + else { + ITreeExpression ite = (ITreeExpression) iTreeExpression.getChildren().get(0); + if (!isNumber(ite)) { + ITreeExpression var = (ITreeExpression) listChildren.get(1); + ITreeExpression var1 = (ITreeExpression) var.getChildren().get(0); + list.add(Double.parseDouble(var1.getAllNodes().get(0).toString())); + ITreeExpression next = (ITreeExpression) listChildren.get(0); + convertToDoubleArray(list, ++depth, next); + } else { + ITreeExpression var = (ITreeExpression) listChildren.get(0); + list.add(Double.parseDouble(var.getAllNodes().get(0).toString())); + return list; + } + } + } + return list; + } + + private ITreeExpression convertToTreePolynomial(List list) { + Collections.reverse(list); + int degree = list.size() - 1; + + Iterator it = list.iterator(); + ITreeExpression iTreeExpression = null; + + while(it.hasNext()) { + ITreeExpression variable; + + if(degree == 0) { + variable = new TreeExpression(Operation.ADD, new Variable(it.next().toString())); + } + else if (degree == 1) { + ITreeExpression value = new TreeExpression(Operation.ADD, new Variable(it.next().toString())); + variable = value.mult("x"); + } + else { + ITreeExpression value = new TreeExpression(Operation.ADD, new Variable(it.next().toString())); + variable = new TreeExpression(Operation.POW, new Variable("x")); + variable = variable.pow(degree + ""); + variable = value.mult(variable); + } + + degree--; + + if(iTreeExpression == null) { + iTreeExpression = new TreeExpression(Operation.ADD, variable); + } + else { + iTreeExpression = iTreeExpression.add(variable); + } + } + + return iTreeExpression; + } + + private boolean isNumber(ITreeExpression iTreeExpression) { + return iTreeExpression.getAllNodes().size() == 1; + } + + private List multiplyCoefficients(List first, List second){ + int totalLength = first.size() + second.size() - 1; + List resultAsArray = new ArrayList<>(totalLength); + double[] result = new double[totalLength]; + for (int i = 0; i < first.size(); i++) + for (int j = 0; j < second.size(); j++) { + result[i + j] += first.get(i) * second.get(j); + } + for(double d: result){ + resultAsArray.add(d); + } + return resultAsArray; + } +} diff --git a/src/main/java/pl/jagiellonian/interfaces/ITreeExpression.java b/src/main/java/pl/jagiellonian/interfaces/ITreeExpression.java index 969d5ce..4a6d1c9 100644 --- a/src/main/java/pl/jagiellonian/interfaces/ITreeExpression.java +++ b/src/main/java/pl/jagiellonian/interfaces/ITreeExpression.java @@ -1,5 +1,7 @@ package pl.jagiellonian.interfaces; +import pl.jagiellonian.utils.Operation; + import java.util.List; /** @@ -19,6 +21,11 @@ public interface ITreeExpression extends IVariable { ITreeExpression setParenthesis(); Boolean getParenthesis(); + + Operation getOperation(); + + List getChildren(); + int degree(IVariable variable); int degree(List variables); } diff --git a/src/test/java/pl/jagiellonian/TreeExpressionExpanderTest.java b/src/test/java/pl/jagiellonian/TreeExpressionExpanderTest.java new file mode 100644 index 0000000..7ff6dca --- /dev/null +++ b/src/test/java/pl/jagiellonian/TreeExpressionExpanderTest.java @@ -0,0 +1,115 @@ +package pl.jagiellonian; + +import org.junit.Test; +import pl.jagiellonian.implementation.Expander; +import pl.jagiellonian.implementation.TreeExpression; +import pl.jagiellonian.implementation.Variable; +import pl.jagiellonian.interfaces.ITreeExpression; +import pl.jagiellonian.utils.Operation; + +import static org.junit.Assert.assertEquals; + +public class TreeExpressionExpanderTest { + + @Test + public void twoComponentsTest() { + ITreeExpression tree = new TreeExpression(Operation.ADD, new Variable("1")); + tree = tree.mult("x"); + tree = tree.sub("2"); + ITreeExpression tree2 = new TreeExpression(Operation.ADD, new Variable("1")); + tree2 = tree2.mult("x"); + tree2 = tree2.add("6"); + tree = tree.mult(tree2); + Expander expander = new Expander(); + String expected = "(1.0)*(x)^2+(4.0)*x+-12.0"; + + assertEquals(expected, expander.expand(tree).toString()); + } + + @Test + public void threeComponentsTest() { + ITreeExpression tree = new TreeExpression(Operation.ADD, new Variable("1")); + tree = tree.mult("x"); + tree = tree.sub("2"); + ITreeExpression tree2 = new TreeExpression(Operation.ADD, new Variable("1")); + tree2 = tree2.mult("x"); + tree2 = tree2.add("6"); + ITreeExpression tree3 = new TreeExpression(Operation.SUB, new Variable("6")); + tree3 = tree3.mult("x"); + tree3 = tree3.sub("5"); + tree = tree.mult(tree2); + tree = tree.mult(tree3); + Expander expander = new Expander(); + String expected = "(6.0)*(x)^3+(19.0)*(x)^2+(-92.0)*x+60.0"; + + assertEquals(expected, expander.expand(tree).toString()); + } + + @Test + public void fourComponentsTest() { + ITreeExpression tree = new TreeExpression(Operation.ADD, new Variable("-6")); + tree = tree.mult("x"); + tree = tree.sub("24"); + ITreeExpression tree2 = new TreeExpression(Operation.ADD, new Variable("1")); + tree2 = tree2.mult("x"); + tree2 = tree2.sub("10"); + ITreeExpression tree3 = new TreeExpression(Operation.ADD, new Variable("6")); + tree3 = tree3.mult("x"); + tree3 = tree3.sub("3"); + ITreeExpression tree4 = new TreeExpression(Operation.ADD, new Variable("-2")); + tree4 = tree4.mult("x"); + tree4 = tree4.sub("5"); + tree = tree.mult(tree2); + tree = tree.mult(tree3); + tree = tree.mult(tree4); + Expander expander = new Expander(); + String expected = "(72.0)*(x)^4+(-288.0)*(x)^3+(-3834.0)*(x)^2+(-5220.0)*x+3600.0"; + + assertEquals(expected, expander.expand(tree).toString()); + } + + @Test + public void multipleComponentsTest() { + ITreeExpression tree = new TreeExpression(Operation.ADD, new Variable("-1")); + tree = tree.mult("x"); + tree = tree.add("6"); + ITreeExpression tree2 = new TreeExpression(Operation.ADD, new Variable("-2")); + tree2 = tree2.mult("x"); + tree2 = tree2.add("4"); + ITreeExpression tree3 = new TreeExpression(Operation.ADD, new Variable("6")); + tree3 = tree3.mult("x"); + tree3 = tree3.sub("13"); + ITreeExpression tree4 = new TreeExpression(Operation.ADD, new Variable("-4")); + tree4 = tree4.mult("x"); + tree4 = tree4.add("5"); + ITreeExpression tree5 = new TreeExpression(Operation.ADD, new Variable("-3")); + tree5 = tree5.mult("x"); + tree5 = tree5.sub("2"); + ITreeExpression tree6 = new TreeExpression(Operation.ADD, new Variable("2")); + tree6 = tree6.mult("x"); + tree6 = tree6.add("10"); + ITreeExpression tree7 = new TreeExpression(Operation.ADD, new Variable("1")); + tree7 = tree7.mult("x"); + tree7 = tree7.add("2"); + ITreeExpression tree8 = new TreeExpression(Operation.ADD, new Variable("-5")); + tree8 = tree8.mult("x"); + tree8 = tree8.sub("3"); + ITreeExpression tree9 = new TreeExpression(Operation.ADD, new Variable("1")); + tree9 = tree9.mult("x"); + tree9 = tree9.add("11"); + tree = tree.mult(tree2); + tree = tree.mult(tree3); + tree = tree.mult(tree4); + tree = tree.mult(tree5); + tree = tree.mult(tree6); + tree = tree.mult(tree7); + tree = tree.mult(tree8); + tree = tree.mult(tree9); + Expander expander = new Expander(); + String expected = "(-1440.0)*(x)^9+(-11304.0)*(x)^8+(97516.0)*(x)^7+(408068.0)*(x)^6" + + "+(-1491980.0)*(x)^5+(-1924636.0)*(x)^4+(5544544.0)*(x)^3+(2407712.0)*(x)^2+(-4178880.0)*x+-2059200.0"; + + assertEquals(expected, expander.expand(tree).toString()); + } + +} \ No newline at end of file