use of org.matheclipse.core.interfaces.IASTMutable in project symja_android_library by axkr.
the class Solve method of.
/**
* @param ast the <code>Solve(...)</code> ast
* @param numeric if true, try to find a numerically solution
* @param engine
* @return
*/
public static IExpr of(final IAST ast, boolean numeric, EvalEngine engine) {
boolean[] isNumeric = new boolean[] { numeric };
try {
if (ast.arg1().isEmptyList()) {
return F.list(F.CEmptyList);
}
IAST userDefinedVariables = Validate.checkIsVariableOrVariableList(ast, 2, ast.topHead(), engine);
if (userDefinedVariables.isPresent()) {
IAST equationVariables = VariablesSet.getVariables(ast.arg1());
if (userDefinedVariables.isEmpty()) {
userDefinedVariables = equationVariables;
}
ISymbol domain = S.Complexes;
if (ast.isAST3()) {
if (!ast.arg3().isSymbol()) {
LOGGER.log(engine.getLogLevel(), "{}: domain definition expected at position 3 instead of {}", ast.topHead(), ast.arg3());
return F.NIL;
}
domain = (ISymbol) ast.arg3();
if (domain.equals(S.Booleans)) {
return BooleanFunctions.solveInstances(ast.arg1(), userDefinedVariables, Integer.MAX_VALUE);
}
if (domain.equals(S.Integers)) {
return solveIntegers(ast, equationVariables, userDefinedVariables, Integer.MAX_VALUE, engine);
}
if (!domain.equals(S.Reals) && !domain.equals(S.Complexes)) {
Level level = engine.getLogLevel();
LOGGER.log(level, "{}: domain definition expected at position 3 instead of {}", ast.topHead(), domain);
return F.NIL;
}
}
IAssumptions oldAssumptions = engine.getAssumptions();
try {
IAssumptions assum = setVariablesReals(userDefinedVariables, domain);
if (assum != null) {
engine.setAssumptions(assum);
}
IAST termsList = Validate.checkEquationsAndInequations(ast, 1);
IASTMutable[] lists = SolveUtils.filterSolveLists(termsList, F.NIL, isNumeric);
boolean numericFlag = isNumeric[0] || numeric;
if (lists[2].isPresent()) {
IExpr result = solveNumeric(lists[2], numericFlag, engine);
if (!result.isPresent()) {
return IOFunctions.printMessage(ast.topHead(), "nsmet", F.list(ast.topHead()), engine);
}
return checkDomain(result, domain);
}
IASTMutable termsEqualZeroList = lists[0];
IExpr result = solveRecursive(termsEqualZeroList, lists[1], numericFlag, userDefinedVariables, engine);
if (!result.isPresent()) {
return IOFunctions.printMessage(ast.topHead(), "nsmet", F.list(ast.topHead()), engine);
}
return checkDomain(result, domain);
} finally {
engine.setAssumptions(oldAssumptions);
}
}
} catch (ValidateException ve) {
return IOFunctions.printMessage(S.Solve, ve, engine);
} catch (LimitException e) {
LOGGER.log(engine.getLogLevel(), S.Solve, e);
} catch (RuntimeException rex) {
LOGGER.debug("Solve.of() failed() failed", rex);
}
return F.NIL;
}
use of org.matheclipse.core.interfaces.IASTMutable in project symja_android_library by axkr.
the class Solve method solveRecursive.
// /**
// * Check if all rules in the list return a real result. Try to get a real solution from
// * <code>ConditionalExpression</code>s.
// *
// * @param listOfRules a list of rules <code>Rule(variable, value)</code>
// * @return
// */
// private static boolean isReal(IASTAppendable listOfRules) {
// if (listOfRules.isListOfRules(false)) {
// for (int i = 1; i < listOfRules.size(); i++) {
// IAST rule = listOfRules.getAST(i);
// IExpr rhs = rule.second();
// if (!rhs.isRealResult()) {
// try {
// IExpr res = rhs.replaceAll(x -> rewriteConditionalExpressionIfReal(x));
// if (res.isPresent()) {
// listOfRules.set(i, rule.setAtCopy(2, res));
// continue;
// }
// return false;
// } catch (NoEvalException noeex) {
// return false;
// }
// }
// }
// return true;
// }
// return false;
// }
// /**
// * If <code>expr</code> is a <code>ConditionalExpression</code> try to rewrite <code>expr</code>
// * as a real expression.
// *
// * @param expr
// * @return {@link F#NIL} if no <code>ConditionalExpression</code> was matched
// * @throws NoEvalException if <code>ConditionalExpression</code> can not be rewritten as a real
// * result.
// */
// private static IExpr rewriteConditionalExpressionIfReal(IExpr expr) throws NoEvalException {
// if (expr.isConditionalExpression()) {
// IExpr function = expr.first();
// IExpr condition = expr.last();
// IExpr result = EvalEngine.get().evaluate(F.Refine(F.Re(function), condition));
// if (result.isRealResult()) {
// return result;
// }
// throw NoEvalException.CONST;
// }
// return F.NIL;
// }
/**
* Solve the list of equations recursively. Return a list of rules <code>
* {var1->expr1, var1->expr2, ...}</code> (typically for NSolve function) or return a "list
* of list of rules" (typically for Solve function) <code>
* {{var1->expr11, var1->expr12,...}, {var1->expr21, var1->expr22,...}, ...}</code>. The method
* solves for the first variable from the <code>variables</code> list and inserts the solution
* back in the remaining equations and calls the method recursively again with this new system.
*
* @param termsEqualZeroList the list of expressions, which should equal <code>0</code>
* @param inequationsList a list of inequality constraints
* @param numericFlag if <code>true</code>, try to find a numeric solution
* @param variables the variables for which the equations should be solved
* @param engine
* @return a list of rules (typically NSolve) or a list of list of rules (typically Solve) of the
* solutions, <code>F.NIL</code> otherwise.
*/
private static IExpr solveRecursive(IASTMutable termsEqualZeroList, IASTMutable inequationsList, boolean numericFlag, IAST variables, EvalEngine engine) {
IASTMutable temp = solveTimesEquationsRecursively(termsEqualZeroList, inequationsList, numericFlag, variables, true, engine);
if (temp.isPresent()) {
return solveNumeric(QuarticSolver.sortASTArguments(temp), numericFlag, engine);
}
if (inequationsList.isEmpty() && termsEqualZeroList.size() == 2 && variables.size() == 2) {
IExpr firstVariable = variables.arg1();
IExpr res = eliminateOneVariable(termsEqualZeroList, firstVariable, true, engine);
if (!res.isPresent()) {
if (numericFlag) {
// find numerically with start value 0
res = engine.evalQuiet(F.FindRoot(termsEqualZeroList.arg1(), F.list(firstVariable, F.C0)));
}
}
if (!res.isList() || !res.isFree(t -> t.isIndeterminate() || t.isDirectedInfinity(), true)) {
return F.NIL;
}
return solveNumeric(res, numericFlag, engine);
}
if (termsEqualZeroList.size() > 2 && variables.size() >= 3) {
// expensive recursion try
IExpr firstEquation = termsEqualZeroList.arg1();
IExpr firstVariable = variables.arg1();
IAST[] reduced = Eliminate.eliminateOneVariable(F.list(F.Equal(firstEquation, F.C0)), firstVariable, true, engine);
if (reduced != null) {
variables = variables.splice(1);
termsEqualZeroList = termsEqualZeroList.removeAtCopy(1);
// oneVariableRule = ( firstVariable -> reducedExpression )
IAST oneVariableRule = reduced[1];
IExpr replaced = termsEqualZeroList.replaceAll(oneVariableRule);
if (replaced.isList()) {
IExpr subResult = solveRecursive((IASTMutable) replaced, inequationsList, numericFlag, variables, engine);
if (subResult.isListOfLists()) {
IASTAppendable result = F.ListAlloc(subResult.size());
IASTAppendable appendable;
for (int i = 1; i < subResult.size(); i++) {
IAST listOfRules = (IAST) subResult.getAt(i);
replaced = oneVariableRule.second().replaceAll(listOfRules);
if (replaced.isPresent()) {
replaced = S.Simplify.of(engine, replaced);
appendable = listOfRules.copyAppendable();
appendable.append(F.Rule(firstVariable, replaced));
result.append(appendable);
}
}
return result;
} else if (subResult.isList()) {
// important for NSolve
replaced = oneVariableRule.second().replaceAll((IAST) subResult);
if (replaced.isPresent()) {
IASTAppendable appendable = ((IAST) subResult).copyAppendable();
appendable.append(F.Rule(firstVariable, replaced));
return appendable;
}
}
}
}
}
return F.NIL;
}
use of org.matheclipse.core.interfaces.IASTMutable in project symja_android_library by axkr.
the class Solve method solveTimesEquationsRecursively.
/**
* Analyze the <code>termsEqualZeroList</code> if it contains a <code>Times[..., ,...]</code>
* expression. If true, set the factors equal to <code>0</code> and solve the equations
* recursively.
*
* @param termsEqualZeroList the list of expressions, which should equal <code>0</code>
* @param numericFlag
* @param variables the variables for which the equations should be solved
* @param engine the evaluation engine
* @return
*/
private static IASTMutable solveTimesEquationsRecursively(IASTMutable termsEqualZeroList, IAST inequationsList, boolean numericFlag, IAST variables, boolean multipleValues, EvalEngine engine) {
try {
IASTMutable resultList = solveEquations(termsEqualZeroList, inequationsList, variables, 0, engine);
if (resultList.isPresent() && !resultList.isEmpty()) {
return resultList;
}
Set<IExpr> subSolutionSet = new TreeSet<IExpr>();
for (int i = 1; i < termsEqualZeroList.size(); i++) {
IExpr termEQZero = termsEqualZeroList.get(i);
if (termEQZero.isTimes()) {
solveTimesAST((IAST) termEQZero, termsEqualZeroList, inequationsList, numericFlag, variables, multipleValues, engine, subSolutionSet, i);
} else {
if (termEQZero.isAST()) {
// try factoring
termEQZero = S.Factor.of(engine, termEQZero);
if (termEQZero.isTimes()) {
solveTimesAST((IAST) termEQZero, termsEqualZeroList, inequationsList, numericFlag, variables, multipleValues, engine, subSolutionSet, i);
}
}
}
}
if (subSolutionSet.size() > 0) {
return F.ListAlloc(subSolutionSet);
}
return resultList;
} catch (LimitException le) {
LOGGER.debug("Solve.solveTimesEquationsRecursively() failed", le);
throw le;
} catch (RuntimeException rex) {
LOGGER.debug("Solve.solveTimesEquationsRecursively() failed", rex);
if (Config.SHOW_STACKTRACE) {
rex.printStackTrace();
}
}
return F.NIL;
}
use of org.matheclipse.core.interfaces.IASTMutable in project symja_android_library by axkr.
the class VisitorReplaceAll method visitAST.
@Override
protected IExpr visitAST(IAST ast) {
int size = ast.size();
for (int i = fOffset; i < size; i++) {
IExpr temp = ast.get(i).accept(this);
if (temp.isPresent()) {
// something was evaluated - return a new IAST:
IASTMutable result = ast.setAtCopy(i, temp);
ast.forEach(i + 1, size, (x, j) -> {
IExpr t = x.accept(this);
if (t.isPresent()) {
result.set(j, t);
}
});
return postProcessing(result);
}
}
return F.NIL;
}
use of org.matheclipse.core.interfaces.IASTMutable in project symja_android_library by axkr.
the class Sum method collectConstantFactors.
private static IExpr collectConstantFactors(final IAST ast, IAST prod, VariablesSet variablesSet) {
IASTAppendable filterAST = F.TimesAlloc(16);
IASTAppendable restAST = F.TimesAlloc(16);
prod.filter(filterAST, restAST, VariablesSet.isFree(variablesSet));
if (filterAST.size() > 1) {
IASTMutable reducedSum = ast.setAtCopy(1, restAST.oneIdentity1());
return F.Times(filterAST.oneIdentity0(), reducedSum);
}
return F.NIL;
}
Aggregations