%mathpiper,def="OldSolve"
/********** Solve'System **********/

// for now, just use a very simple backsubstitution scheme
Solve'System(_eqns, _vars) <-- Solve'SimpleBackSubstitution(eqns,vars);

// Check(False, "Unimplemented", "Solve'System: not implemented");

10 # Solve'SimpleBackSubstitution'FindAlternativeForms((_lx) == (_rx)) <--
[
  Local(newEq);
  newEq := (Simplify(lx) == Simplify(rx));
  If (newEq != (lx == rx) And newEq != (0==0),DestructiveAppend(eq,newEq));
  newEq := (Simplify(lx - rx) == 0);
  If (newEq != (lx == rx) And newEq != (0==0),DestructiveAppend(eq,newEq));
];
20 # Solve'SimpleBackSubstitution'FindAlternativeForms(_equation) <--
[
];
UnFence("Solve'SimpleBackSubstitution'FindAlternativeForms",1);

/* Solving sets of equations using simple backsubstitution.
 * Solve'SimpleBackSubstitution takes all combinations of equations and
 * variables to solve for, and it then uses SuchThat to find an expression
 * for this variable, and then if found backsubstitutes it in the other
 * equations in the hope that they become simpler, resulting in a final
 * set of solutions.
 */
10 # Solve'SimpleBackSubstitution(eq_IsList,var_IsList) <--
[
 If(InVerboseMode(), Echo({"Entering Solve'SimpleBackSubstitution"}));

  Local(result,i,j,nrvar,nreq,sub,nrSet,origEq);
  eq:=FlatCopy(eq);
  origEq:=FlatCopy(eq);
  nrvar:=Length(var);
  result:={FlatCopy(var)};
  nrSet := 0;

//Echo("Before: ",eq);
  ForEach(equation,origEq)
  [
//Echo("equation ",equation);
    Solve'SimpleBackSubstitution'FindAlternativeForms(equation);
  ];
//  eq:=Simplify(eq);
//Echo("After: ",eq);

  nreq:=Length(eq);

  /* Loop over each variable, solving for it */

/* Echo({eq});  */

  For(j:=1,j<=nreq And nrSet < nrvar,j++)
  [
    Local(vlist);
    vlist:=VarListAll(eq[j],`Lambda({pt},Contains(@var,pt)));
    For(i:=1,i<=nrvar And nrSet < nrvar,i++)
    [

//Echo("eq[",j,"] = ",eq[j]);
//Echo("var[",i,"] = ",var[i]);
//Echo("varlist = ",vlist);
//Echo();

      If(Count(vlist,var[i]) = 1,
         [
           sub := FunctionToList(eq[j]);
           sub := sub[2]-sub[3];
//Echo("using ",sub);
           sub:=SuchThat(sub,var[i]);
           If(InVerboseMode(), Echo({"From ",eq[j]," it follows that ",var[i]," = ",sub}));
           If(SolveFullSimplify=True,
             result:=Simplify(Subst(var[i],sub)result),
             result[1][i]:=sub
             );
//Echo("result = ",result," i = ",i);
           nrSet++;

//Echo("current result is ",result);
           Local(k,reset);
           reset:=False;
           For(k:=1,k<=nreq  And nrSet < nrvar,k++)
           If(Contains(VarListAll(eq[k],`Lambda({pt},Contains(@var,pt))),var[i]),
           [
             Local(original);
             original:=eq[k];
             eq[k]:=Subst(var[i],sub)eq[k];
             If(Simplify(Simplify(eq[k])) = (0 == 0),
               eq[k] := (0 == 0),
               Solve'SimpleBackSubstitution'FindAlternativeForms(eq[k])
               );
//             eq[k]:=Simplify(eq[k]);
//             eq[k]:=Simplify(eq[k]); //@@@??? TODO I found one example where simplifying twice gives a different result from simplifying once!
             If(original!=(0==0) And eq[k] = (0 == 0),reset:=True);
             If(InVerboseMode(), Echo({"   ",original," simplifies to ",eq[k]}));
           ]);
           nreq:=Length(eq);
           vlist:=VarListAll(eq[j],`Lambda({pt},Contains(@var,pt)));
           i:=nrvar+1;
           // restart at the beginning of the variables.
           If(reset,j:=1);
         ]);
    ];
  ];


//Echo("Finished finding results ",var," = ",result);
//  eq:=origEq;
//  nreq := Length(eq);
  Local(zeroeq,tested);
  tested:={};
//  zeroeq:=FillList(0==0,nreq);

  ForEach(item,result)
  [
/*
    Local(eqSimplified);
    eqSimplified := eq;
    ForEach(map,Transpose({var,item}))
    [
      eqSimplified := Subst(map[1],map[2])eqSimplified;
    ];
    eqSimplified := Simplify(Simplify(eqSimplified));

    Echo(eqSimplified);

    If(eqSimplified = zeroeq,
    [
      DestructiveAppend(tested,Map("==",{var,item}));
    ]);
*/
    DestructiveAppend(tested,Map("==",{var,item}));
  ];



/* Echo({"tested is ",tested});  */
 If(InVerboseMode(), Echo({"Leaving Solve'SimpleBackSubstitution"}));
  tested;
];




/********** OldSolve **********/
10 # OldSolve(eq_IsList,var_IsList) <-- Solve'SimpleBackSubstitution(eq,var);


90 # OldSolve((left_IsList) == right_IsList,_var) <--
      OldSolve(Map("==",{left,right}),var);


100 # OldSolve(_left == _right,_var) <--
     SuchThat(left - right , 0 , var);

/* HoldArgument("OldSolve",arg1); */
/* HoldArgument("OldSolve",arg2); */

%/mathpiper



%mathpiper_docs,name="OldSolve",categories="User Functions;Solvers (Symbolic)"
*CMD OldSolve --- old version of {Solve}
*STD
*CALL
	OldSolve(eq, var)
	OldSolve(eqlist, varlist)

*PARMS

{eq} -- single identity equation

{var} -- single variable

{eqlist} -- list of identity equations

{varlist} -- list of variables

*DESC

This is an older version of {Solve}. It is retained for two
reasons. The first one is philosophical: it is good to have multiple
algorithms available. The second reason is more practical: the newer
version cannot handle systems of equations, but {OldSolve} can.

This command tries to solve one or more equations. Use the first form
to solve a single equation and the second one for systems of
equations.

The first calling sequence solves the equation "eq" for the variable
"var". Use the {==} operator to form the equation.
The value of "var" which satisfies the equation, is returned. Note
that only one solution is found and returned.

To solve a system of equations, the second form should be used. It
solves the system of equations contained in the list "eqlist" for
the variables appearing in the list "varlist". A list of results is
returned, and each result is a list containing the values of the
variables in "varlist". Again, at most a single solution is
returned.

The task of solving a single equation is simply delegated to {SuchThat}. Multiple equations are solved recursively:
firstly, an equation is sought in which one of the variables occurs
exactly once; then this equation is solved with {SuchThat}; and finally the solution is substituted in the
other equations by {Eliminate} decreasing the number
of equations by one. This suffices for all linear equations and a
large group of simple nonlinear equations.

*E.G.

In> OldSolve(a+x*y==z,x)
Result: (z-a)/y;
In> OldSolve({a*x+y==0,x+z==0},{x,y})
Result: {{-z,z*a}};

This means that "x = (z-a)/y" is a solution of the first equation
and that "x = -z", "y = z*a" is a solution of the systems of
equations in the second command.

An example which {OldSolve} cannot solve:

In> OldSolve({x^2-x == y^2-y,x^2-x == y^3+y},{x,y});
Result: {};

*SEE Solve, SuchThat, Eliminate, PSolve, ==
%/mathpiper_docs