New rules

This commit is contained in:
Andrea Cavalli 2018-05-06 18:05:21 +02:00
parent 59a8e79e4d
commit 6d024c5569
14 changed files with 428 additions and 85 deletions

View File

@ -84,4 +84,22 @@ public class Multiplication extends FunctionOperator {
return result;
}
}
public boolean isNegative() {
return parameter1.equals(new Number(getMathContext(), -1)) || parameter2.equals(new Number(getMathContext(), -1));
}
public Function toPositive() {
if (parameter1.equals(new Number(getMathContext(), -1))) {
return parameter2;
} else if (parameter2.equals(new Number(getMathContext(), -1))) {
return parameter2;
} else {
return null;
}
}
public static Multiplication newNegative(MathContext context, Function value2) {
return new Multiplication(context, new Number(context, -1), value2);
}
}

View File

@ -29,9 +29,6 @@ public class Undefined implements Function {
@Override
public boolean equals(Object o) {
if (o instanceof Undefined) {
return true;
}
return false;
}

View File

@ -27,12 +27,13 @@ public class MathSolver {
}
private final StepState[] stepStates = StepState.values();
@SuppressWarnings("unchecked")
private final ObjectArrayList<Function>[] lastFunctions = new ObjectArrayList[stepStates.length];
private final ObjectArrayList<Function>[][] lastFunctions = new ObjectArrayList[2][stepStates.length];
public MathSolver(Function initialFunction) {
this.initialFunction = initialFunction;
}
@SuppressWarnings("unchecked")
public ObjectArrayList<ObjectArrayList<Function>> solveAllSteps() throws InterruptedException, Error {
ObjectArrayList<ObjectArrayList<Function>> steps = new ObjectArrayList<>();
ObjectArrayList<Function> lastFnc = null, currFnc = new ObjectArrayList<>();
@ -42,9 +43,11 @@ public class MathSolver {
int initStepState = 0, endStepState = 0;
AtomicInteger stepState = new AtomicInteger(0);
do {
lastFunctions[1] = lastFunctions[0];
lastFunctions[0] = new ObjectArrayList[stepStates.length];
final String stepName = "Step " + stepNumber;
for (int i = initStepState; i < endStepState; i++) {
lastFunctions[i] = currFnc;
for (int i = initStepState; i <= endStepState; i++) {
lastFunctions[0][i] = currFnc;
}
lastFnc = currFnc;
initStepState = stepState.get();
@ -63,11 +66,19 @@ public class MathSolver {
Utils.out.println(Utils.OUTPUTLEVEL_DEBUG_VERBOSE, "Math Solver", stepName, "Step result: " + stepResult);
Utils.out.println(Utils.OUTPUTLEVEL_DEBUG_VERBOSE, "Math Solver", stepName, "Step result details: Consecutive steps that did nothing: " + consecutiveNullSteps + ", this step did " + stepStateRepetitions + " simplifications.");
Utils.out.println(Utils.OUTPUTLEVEL_DEBUG_VERBOSE, "Math Solver", stepName, "Next step state: " + stepStates[endStepState]);
} while(consecutiveNullSteps < stepStates.length && !checkEquals(currFnc, lastFunctions[endStepState]));
if (StaticVars.debugOn) {
Utils.out.println(Utils.OUTPUTLEVEL_DEBUG_VERBOSE, "Math Solver", stepName, currFnc + " is " + (checkEquals(currFnc, lastFunctions[0][endStepState]) ? "" : "not ") + "equals to [0]:" + lastFunctions[0][endStepState]);
}
if (StaticVars.debugOn) {
Utils.out.println(Utils.OUTPUTLEVEL_DEBUG_VERBOSE, "Math Solver", stepName, currFnc + " is " + (checkEquals(currFnc, lastFunctions[1][endStepState]) ? "" : "not ") + "equals to [1]:" + lastFunctions[1][endStepState]);
}
} while(consecutiveNullSteps < stepStates.length && !checkEquals(currFnc, lastFunctions[0][endStepState]) && !checkEquals(currFnc, lastFunctions[1][endStepState]));
if (consecutiveNullSteps >= stepStates.length) {
Utils.out.println(Utils.OUTPUTLEVEL_DEBUG_VERBOSE, "Math Solver", "Loop ended because " + consecutiveNullSteps + " >= " + stepStates.length);
} else if (checkEquals(currFnc, lastFunctions[0][endStepState])) {
Utils.out.println(Utils.OUTPUTLEVEL_DEBUG_VERBOSE, "Math Solver", "Loop ended because " + currFnc + " is equals to [0]:" + lastFunctions[0][endStepState]);
} else {
Utils.out.println(Utils.OUTPUTLEVEL_DEBUG_VERBOSE, "Math Solver", "Loop ended because " + currFnc + " is equals to " + lastFunctions[endStepState]);
Utils.out.println(Utils.OUTPUTLEVEL_DEBUG_VERBOSE, "Math Solver", "Loop ended because " + currFnc + " is equals to [1]:" + lastFunctions[1][endStepState]);
}
return steps;
}

Binary file not shown.

View File

@ -28,6 +28,11 @@ FractionsRule2
FractionsRule3
FractionsRule4
FractionsRule5
FractionsRule6
FractionsRule7
FractionsRule8
FractionsRule9
FractionsRule10
FractionsRule11
FractionsRule12
FractionsRule14

1 Rule file
28 FractionsRule3
29 FractionsRule4
30 FractionsRule5
31 FractionsRule6
32 FractionsRule7
33 FractionsRule8
34 FractionsRule9
35 FractionsRule10
36 FractionsRule11
37 FractionsRule12
38 FractionsRule14

View File

@ -3,6 +3,8 @@ SETTINGS: (please don't move this part)
PATH=ExpandRule2
*/
import org.warp.picalculator.Errors;
import org.warp.picalculator.Error;
import org.warp.picalculator.math.Function;
import org.warp.picalculator.math.FunctionOperator;
import org.warp.picalculator.math.MathContext;
@ -18,7 +20,7 @@ import org.warp.picalculator.math.functions.Number;
/**
* Expand rule
* -(-a) = a
* a(b+c)=ab+ac
*
* @author Andrea Cavalli
*
@ -42,90 +44,40 @@ public class ExpandRule2 implements Rule {
- An ObjectArrayList<Function> if it did something
*/
@Override
public ObjectArrayList<Function> execute(Function f) {
public ObjectArrayList<Function> execute(Function f) throws Error {
boolean isExecutable = false;
if (f instanceof Multiplication) {
FunctionOperator fnc = (FunctionOperator) f;
if (fnc.getParameter1().equals(new Number(fnc.getMathContext(), -1))) {
Function expr = fnc.getParameter2();
if (expr instanceof Sum) {
isExecutable = true;
} else if (expr instanceof Subtraction) {
isExecutable = true;
} else if (expr instanceof SumSubtraction) {
isExecutable = true;
}
}
} else if (f instanceof Subtraction || f instanceof SumSubtraction) {
FunctionOperator fnc = (FunctionOperator) f;
Function expr = fnc.getParameter2();
if (expr instanceof Sum) {
final Multiplication fnc = (Multiplication) f;
if (fnc.getParameter1() instanceof Sum) {
isExecutable = true;
} else if (expr instanceof Subtraction) {
isExecutable = true;
} else if (expr instanceof SumSubtraction) {
} else if (fnc.getParameter2() instanceof Sum) {
isExecutable = true;
} else {
isExecutable = false;
}
}
if (isExecutable) {
ObjectArrayList<Function> result = new ObjectArrayList<>();
MathContext root = f.getMathContext();
Function expr = null;
int fromSubtraction = 0;
Function subtraction = null;
if (f instanceof Multiplication) {
expr = ((FunctionOperator) f).getParameter2();
} else if (f instanceof Subtraction || f instanceof SumSubtraction) {
expr = ((FunctionOperator) f).getParameter2();
if (f instanceof Subtraction) {
fromSubtraction = 1;
} else {
fromSubtraction = 2;
}
final Multiplication fnc = (Multiplication) f;
final Sum sum;
final Function a;
if (fnc.getParameter1() instanceof Sum) {
sum = (Sum) fnc.getParameter1();
a = fnc.getParameter2();
} else if (fnc.getParameter2() instanceof Sum) {
sum = (Sum) fnc.getParameter2();
a = fnc.getParameter1();
} else {
throw new Error(Errors.UNBALANCED_STACK);
}
if (f instanceof SumSubtraction) {
}
FunctionOperator fnc = (FunctionOperator) expr;
if (fnc instanceof Sum) {
Function a = fnc.getParameter1();
Function b = fnc.getParameter2();
Function fnc2 = new Subtraction(root, new Multiplication(root, new Number(root, -1), a), b);
if (fromSubtraction > 0) {
subtraction = new Subtraction(root, ((FunctionOperator)f).getParameter1(), fnc2);
result.add(subtraction);
} else {
result.add(fnc2);
}
} else if (fnc instanceof Subtraction) {
Function a = fnc.getParameter1();
Function b = fnc.getParameter2();
Function fnc2 = new Sum(root, new Multiplication(root, new Number(root, -1), a), b);
if (fromSubtraction > 0) {
subtraction = new Subtraction(root, ((FunctionOperator)f).getParameter1(), fnc2);
result.add(subtraction);
} else {
result.add(fnc2);
}
} else if (fnc instanceof SumSubtraction) {
Function a = fnc.getParameter1();
Function b = fnc.getParameter2();
Function fnc2 = new Sum(root, new Multiplication(root, new Number(root, -1), a), b);
Function fnc3 = new Subtraction(root, new Multiplication(root, new Number(root, -1), a), b);
if (fromSubtraction > 0) {
subtraction = new SumSubtraction(root, ((FunctionOperator)f).getParameter1(), fnc2);
result.add(subtraction);
subtraction = new SumSubtraction(root, ((FunctionOperator)f).getParameter1(), fnc3);
result.add(subtraction);
result.add(subtraction);
} else {
result.add(fnc2);
result.add(fnc2);
}
}
final Function b = sum.getParameter1();
final Function c = sum.getParameter2();
final Multiplication ab = new Multiplication(root, a, b);
final Multiplication ac = new Multiplication(root, a, c);
result.add(new Sum(root, ab, ac));
return result;
} else {
return null;

View File

@ -0,0 +1,67 @@
/*
SETTINGS: (please don't move this part)
PATH=FractionsRule10
*/
import org.warp.picalculator.math.Function;
import org.warp.picalculator.math.FunctionOperator;
import org.warp.picalculator.math.FunctionDynamic;
import org.warp.picalculator.math.FunctionSingle;
import org.warp.picalculator.math.MathContext;
//Imports
import java.math.BigDecimal;
import org.warp.picalculator.Error;
import org.warp.picalculator.math.Function;
import org.warp.picalculator.math.MathContext;
import org.warp.picalculator.math.functions.Division;
import org.warp.picalculator.math.functions.Multiplication;
import org.warp.picalculator.math.functions.Number;
import org.warp.picalculator.math.functions.Power;
import org.warp.picalculator.math.rules.Rule;
import org.warp.picalculator.math.rules.RuleType;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
/**
* Number rule
* a/(-b) = -(a/b)
*
* @author Andrea Cavalli
*
*/
public class FractionsRule10 implements Rule {
// Rule name
@Override
public String getRuleName() {
return "FractionsRule10";
}
// Rule type
@Override
public RuleType getRuleType() {
return RuleType.EXPANSION;
}
/* Rule function
Returns:
- null if it's not executable on the function "f"
- An ObjectArrayList<Function> if it did something
*/
@Override
public ObjectArrayList<Function> execute(Function f) {
if (f instanceof Division) {
MathContext root = f.getMathContext();
Division div = (Division) f;
if (div.getParameter2() instanceof Multiplication && ((Multiplication)div.getParameter2()).isNegative()) {
ObjectArrayList<Function> result = new ObjectArrayList<>();
result.add(Multiplication.newNegative(root, new Division(root, div.getParameter1(), ((Multiplication)div.getParameter2()).toPositive())));
return result;
}
}
return null;
}
}

View File

@ -72,7 +72,7 @@ public class FractionsRule12 implements Rule {
a = fnc.getParameter2();
b = div2.getParameter1();
c = div2.getParameter2();
result.add(new Division(fnc.getMathContext(), new Multiplication(fnc.getMathContext(), a, c), b));
result.add(new Division(fnc.getMathContext(), b, new Multiplication(fnc.getMathContext(), c, a)));
return result;
} else {

View File

@ -0,0 +1,76 @@
/*
SETTINGS: (please don't move this part)
PATH=FractionsRule6
*/
import org.warp.picalculator.math.Function;
import org.warp.picalculator.math.FunctionOperator;
import org.warp.picalculator.math.FunctionDynamic;
import org.warp.picalculator.math.FunctionSingle;
import org.warp.picalculator.math.MathContext;
//Imports
import org.warp.picalculator.Error;
import org.warp.picalculator.math.Function;
import org.warp.picalculator.math.MathContext;
import org.warp.picalculator.math.functions.Division;
import org.warp.picalculator.math.functions.Multiplication;
import org.warp.picalculator.math.functions.Number;
import org.warp.picalculator.math.functions.Power;
import org.warp.picalculator.math.rules.Rule;
import org.warp.picalculator.math.rules.RuleType;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
/**
* Number rule
* a ^ -1 = 1/a
*
* @author Andrea Cavalli
*
*/
public class FractionsRule6 implements Rule {
// Rule name
@Override
public String getRuleName() {
return "FractionsRule6";
}
// Rule type
@Override
public RuleType getRuleType() {
return RuleType.EXPANSION;
}
/* Rule function
Returns:
- null if it's not executable on the function "f"
- An ObjectArrayList<Function> if it did something
*/
@Override
public ObjectArrayList<Function> execute(Function f) {
boolean isExecutable = false;
if (f instanceof Power) {
MathContext root = f.getMathContext();
Power pow = (Power) f;
if (pow.getParameter2() instanceof Number) {
Function numb = pow.getParameter2();
if (numb.equals(new Number(root, -1))) {
isExecutable = true;
}
}
}
if (isExecutable) {
MathContext root = f.getMathContext();
ObjectArrayList<Function> result = new ObjectArrayList<>();
Function a = new Division(root, new Number(root, 1), ((Power) f).getParameter1());
result.add(a);
return result;
} else {
return null;
}
}
}

View File

@ -0,0 +1,77 @@
/*
SETTINGS: (please don't move this part)
PATH=FractionsRule7
*/
import org.warp.picalculator.math.Function;
import org.warp.picalculator.math.FunctionOperator;
import org.warp.picalculator.math.FunctionDynamic;
import org.warp.picalculator.math.FunctionSingle;
import org.warp.picalculator.math.MathContext;
//Imports
import java.math.BigDecimal;
import org.warp.picalculator.Error;
import org.warp.picalculator.math.Function;
import org.warp.picalculator.math.MathContext;
import org.warp.picalculator.math.functions.Division;
import org.warp.picalculator.math.functions.Multiplication;
import org.warp.picalculator.math.functions.Number;
import org.warp.picalculator.math.functions.Power;
import org.warp.picalculator.math.rules.Rule;
import org.warp.picalculator.math.rules.RuleType;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
/**
* Number rule
* a ^ -b = 1/(a^b)
*
* @author Andrea Cavalli
*
*/
public class FractionsRule7 implements Rule {
// Rule name
@Override
public String getRuleName() {
return "FractionsRule7";
}
// Rule type
@Override
public RuleType getRuleType() {
return RuleType.EXPANSION;
}
/* Rule function
Returns:
- null if it's not executable on the function "f"
- An ObjectArrayList<Function> if it did something
*/
@Override
public ObjectArrayList<Function> execute(Function f) {
boolean isExecutable = false;
if (f instanceof Power) {
MathContext root = f.getMathContext();
Power pow = (Power) f;
if (pow.getParameter2() instanceof Number) {
Number numb = (Number) pow.getParameter2();
if (numb.getTerm().compareTo(BigDecimal.ZERO) < 0) {
ObjectArrayList<Function> result = new ObjectArrayList<>();
Function a = new Division(root, new Number(root, 1), new Power(root, ((Power) f).getParameter1(), ((Number)((Power)f).getParameter2()).multiply(new Number(root, -1))));
result.add(a);
return result;
}
} else if (pow.getParameter2() instanceof Multiplication && ((Multiplication)pow.getParameter2()).getParameter1().equals(new Number(root, -1))) {
ObjectArrayList<Function> result = new ObjectArrayList<>();
Function a = new Division(root, new Number(root, 1), new Power(root, ((Power) f).getParameter1(), ((Multiplication)((Power)f).getParameter2()).getParameter2()));
result.add(a);
return result;
}
}
return null;
}
}

View File

@ -0,0 +1,69 @@
/*
SETTINGS: (please don't move this part)
PATH=FractionsRule8
*/
import org.warp.picalculator.math.Function;
import org.warp.picalculator.math.FunctionOperator;
import org.warp.picalculator.math.FunctionDynamic;
import org.warp.picalculator.math.FunctionSingle;
import org.warp.picalculator.math.MathContext;
//Imports
import java.math.BigDecimal;
import org.warp.picalculator.Error;
import org.warp.picalculator.math.Function;
import org.warp.picalculator.math.MathContext;
import org.warp.picalculator.math.functions.Division;
import org.warp.picalculator.math.functions.Multiplication;
import org.warp.picalculator.math.functions.Number;
import org.warp.picalculator.math.functions.Power;
import org.warp.picalculator.math.rules.Rule;
import org.warp.picalculator.math.rules.RuleType;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
/**
* Number rule
* -a/-b = a/b
*
* @author Andrea Cavalli
*
*/
public class FractionsRule8 implements Rule {
// Rule name
@Override
public String getRuleName() {
return "FractionsRule8";
}
// Rule type
@Override
public RuleType getRuleType() {
return RuleType.CALCULATION;
}
/* Rule function
Returns:
- null if it's not executable on the function "f"
- An ObjectArrayList<Function> if it did something
*/
@Override
public ObjectArrayList<Function> execute(Function f) {
if (f instanceof Division) {
MathContext root = f.getMathContext();
Division div = (Division) f;
if (div.getParameter1() instanceof Multiplication && ((Multiplication)div.getParameter1()).isNegative()) {
if (div.getParameter2() instanceof Multiplication && ((Multiplication)div.getParameter2()).isNegative()) {
ObjectArrayList<Function> result = new ObjectArrayList<>();
result.add(new Division(root, ((Multiplication)div.getParameter1()).toPositive(), ((Multiplication)div.getParameter2()).toPositive()));
return result;
}
}
}
return null;
}
}

View File

@ -0,0 +1,67 @@
/*
SETTINGS: (please don't move this part)
PATH=FractionsRule9
*/
import org.warp.picalculator.math.Function;
import org.warp.picalculator.math.FunctionOperator;
import org.warp.picalculator.math.FunctionDynamic;
import org.warp.picalculator.math.FunctionSingle;
import org.warp.picalculator.math.MathContext;
//Imports
import java.math.BigDecimal;
import org.warp.picalculator.Error;
import org.warp.picalculator.math.Function;
import org.warp.picalculator.math.MathContext;
import org.warp.picalculator.math.functions.Division;
import org.warp.picalculator.math.functions.Multiplication;
import org.warp.picalculator.math.functions.Number;
import org.warp.picalculator.math.functions.Power;
import org.warp.picalculator.math.rules.Rule;
import org.warp.picalculator.math.rules.RuleType;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
/**
* Number rule
* (-a)/b = -(a/b)
*
* @author Andrea Cavalli
*
*/
public class FractionsRule9 implements Rule {
// Rule name
@Override
public String getRuleName() {
return "FractionsRule9";
}
// Rule type
@Override
public RuleType getRuleType() {
return RuleType.EXPANSION;
}
/* Rule function
Returns:
- null if it's not executable on the function "f"
- An ObjectArrayList<Function> if it did something
*/
@Override
public ObjectArrayList<Function> execute(Function f) {
if (f instanceof Division) {
MathContext root = f.getMathContext();
Division div = (Division) f;
if (div.getParameter1() instanceof Multiplication && ((Multiplication)div.getParameter1()).isNegative()) {
ObjectArrayList<Function> result = new ObjectArrayList<>();
result.add(Multiplication.newNegative(root, new Division(root, ((Multiplication)div.getParameter1()).toPositive(), div.getParameter2())));
return result;
}
}
return null;
}
}

View File

@ -53,7 +53,7 @@ public class DivisionRule implements Rule {
*/
@Override
public ObjectArrayList<Function> execute(Function f) throws Error {
if (f instanceof DivisionRule) {
if (f instanceof Division) {
ObjectArrayList<Function> result = new ObjectArrayList<>();
Function variable1 = ((FunctionOperator) f).getParameter1();
Function variable2 = ((FunctionOperator) f).getParameter2();

View File

@ -56,7 +56,11 @@ public class PowerRule implements Rule {
MathContext mathContext = f.getMathContext();
if (variable1 instanceof Number && variable2 instanceof Number) {
//a^b = c
result.add(((Number)variable1).pow((Number)variable2));
Number out = ((Number)variable1).pow((Number)variable2);
if (mathContext.exactMode && !out.isInteger()) {
return null;
}
result.add(out);
return result;
}
}