using System;
using System.Collections.Generic;
using System.Text;
namespace FormulaEditor
{
class PolySum : IObjectOperation
{
Dictionary<ObjectFormulaTree, bool> summands = new Dictionary<ObjectFormulaTree, bool>();
bool positive;
internal PolySum(bool positive)
{
this.positive = positive;
}
#region IObjectOperation Members
int IObjectOperation.Arity
{
get { return summands.Count; }
}
object IObjectOperation.this[object[] x]
{
get { throw new Exception("The method or operation is not implemented."); }
}
object IObjectOperation.ReturnType
{
get { throw new Exception("The method or operation is not implemented."); }
}
bool IObjectOperation.IsPowered
{
get { throw new Exception("The method or operation is not implemented."); }
}
#endregion
private static ObjectFormulaTree sumSum(ObjectFormulaTree tree)
{
List<ObjectFormulaTree> l = new List<ObjectFormulaTree>();
for (int i = 0; i < tree.Count; i++)
{
ObjectFormulaTree t = tree[i];
t = ElementaryFormulaSimplification.Object.Simplify(t);
l.Add(sumSum(t));
}
IObjectOperation op = tree.Operation;
if (op is ElementaryBinaryOperation)
{
ElementaryBinaryOperation bo = op as ElementaryBinaryOperation;
char c = bo.Symbol;
PolySum ps = new PolySum(true);
if (c == '+' | c == '-')
{
bool b = c == '+';
PolySum p = new PolySum(true);
Dictionary<ObjectFormulaTree, bool> dic = p.summands;
for (int i = 0; i < l.Count; i++)
{
ObjectFormulaTree t = l[i];
if (PolyMult.IsZero(t))
{
continue;
}
bool kb = true;
if (i > 0)
{
kb = b;
}
IObjectOperation oo = t.Operation;
if (oo is PolySum)
{
PolySum pss = oo as PolySum;
Dictionary<ObjectFormulaTree, bool> d = pss.summands;
foreach (ObjectFormulaTree tr in d.Keys)
{
bool rb = d[tr];
if (!kb)
{
rb = !rb;
}
dic[tr] = rb;
}
continue;
}
dic[t] = kb;
}
return new ObjectFormulaTree(p, new List<ObjectFormulaTree>());
}
}
return new ObjectFormulaTree(op, l);
}
private static ObjectFormulaTree delConst(ObjectFormulaTree tree, ref bool simple)
{
IObjectOperation op = tree.Operation;
if (op is PolySum)
{
PolySum ps = op as PolySum;
return delConst(ps, ref simple);
}
List<ObjectFormulaTree> l = new List<ObjectFormulaTree>();
for (int i = 0; i < tree.Count; i++)
{
l.Add(delConst(tree[i], ref simple));
}
if ((op is ElementaryBrackets) | (op is ElementaryRoot) | (op is ElementaryPowerOperation))
{
if (l.Count == 2)
{
ObjectFormulaTree t = l[1];
if (ElementaryFormulaSimplification.IsConst(t))
{
double a = (double) t.Result;
if (a == 1)
{
simple = false;
return l[0];
}
}
}
}
return new ObjectFormulaTree(op, l);
}
private static ObjectFormulaTree delConst(PolySum ps, ref bool simple)
{
Dictionary<ObjectFormulaTree, bool> dd = ps.summands;
List<ObjectFormulaTree> del = new List<ObjectFormulaTree>();
Dictionary<ObjectFormulaTree, bool> d = new Dictionary<ObjectFormulaTree,bool>();
foreach (ObjectFormulaTree ttt in dd.Keys)
{
ObjectFormulaTree ts = ElementaryFormulaSimplification.Object.Simplify(ttt);
if (!PolyMult.IsZero(ts))
{
d[ts] = dd[ttt];
}
}
PolySum p = new PolySum(true);
Dictionary<ObjectFormulaTree, bool> forms = p.summands;
double a = 0;
int i = 0;
foreach (ObjectFormulaTree t in d.Keys)
{
bool b = d[t];
ObjectFormulaTree tr = delConst(t, ref simple);
if (PolyMult.IsZero(tr))
{
simple = false;
continue;
}
if (ElementaryFormulaSimplification.IsConst(tr))
{
double x = (double)tr.Result;
a += b ? x : -x;
++i;
if (i > 1)
{
simple = false;
}
}
else
{
forms[tr] = d[t];
}
}
if (a != 0)
{
ElementaryRealConstant ec = new ElementaryRealConstant(a);
forms[new ObjectFormulaTree(ec, new List<ObjectFormulaTree>())] = true;
}
if (forms.Count == 1)
{
foreach (ObjectFormulaTree f in forms.Keys)
{
bool b = forms[f];
if (b)
{
return f;
}
ElementaryFunctionOperation op = new ElementaryFunctionOperation('-');
List<ObjectFormulaTree> lop = new List<ObjectFormulaTree>();
lop.Add(f);
return new ObjectFormulaTree(op, lop);
}
}
return new ObjectFormulaTree(p, new List<ObjectFormulaTree>());
}
private static ObjectFormulaTree sumSumInverse(PolySum ps)
{
Dictionary<ObjectFormulaTree, bool> d = new Dictionary<ObjectFormulaTree, bool>(ps.summands);
ObjectFormulaTree first = null;
ObjectFormulaTree second = null;
bool bf = true;
foreach (ObjectFormulaTree t in d.Keys)
{
if (ElementaryFormulaSimplification.IsConst(t))
{
first = t;
}
}
if (first == null)
{
if (d.Count > 0)
{
foreach (ObjectFormulaTree t in d.Keys)
{
first = t;
bf = d[t];
break;
}
}
}
if (first == null)
{
ElementaryRealConstant er = new ElementaryRealConstant(0);
return new ObjectFormulaTree(er, new List<ObjectFormulaTree>());
}
d.Remove(first);
first = sumSumInverse(first);
if (!bf)
{
ElementaryFunctionOperation ef = new ElementaryFunctionOperation('-');
List<ObjectFormulaTree> l = new List<ObjectFormulaTree>();
l.Add(first);
first = new ObjectFormulaTree(ef, l);
}
if (d.Count == 0)
{
return first;
}
ObjectFormulaTree sec = null;
foreach (ObjectFormulaTree t in d.Keys)
{
sec = t;
}
bool kb = d[sec];
PolySum pp = new PolySum(true);
Dictionary<ObjectFormulaTree, bool> dd = pp.summands;
foreach (ObjectFormulaTree t in d.Keys)
{
if (PolyMult.IsZero(t))
{
continue;
}
bool bl = d[t];
if (!kb)
{
bl = !bl;
}
dd[t] = bl;
}
second = sumSumInverse(pp);
List<ObjectFormulaTree> lr = new List<ObjectFormulaTree>();
lr.Add(first);
lr.Add(second);
char c = kb ? '+' : '-';
if (PolyMult.IsZero(second))
{
return first;
}
Double type = 0;
ElementaryBinaryOperation eop = new ElementaryBinaryOperation(c, type);
return new ObjectFormulaTree(eop, lr);
}
private static ObjectFormulaTree sumSumInverse(ObjectFormulaTree tree)
{
ObjectFormulaTree tre = tree;
IObjectOperation op = tree.Operation;
if (op is PolySum)
{
PolySum ps = op as PolySum;
tre = sumSumInverse(ps);
op = tre.Operation;
}
List<ObjectFormulaTree> l = new List<ObjectFormulaTree>();
for (int i = 0; i < tre.Count; i++)
{
l.Add(sumSumInverse(tre[i]));
}
if (op is ElementaryBinaryOperation)
{
ElementaryBinaryOperation bo = op as ElementaryBinaryOperation;
char c = bo.Symbol;
if (c == '+' | c == '-')
{
if (PolyMult.IsZero(l[1]))
{
return l[0];
}
if (PolyMult.IsZero(l[0]))
{
return signed(l[1], c);
}
}
}
return new ObjectFormulaTree(op, l);
}
internal static ObjectFormulaTree signed(ObjectFormulaTree tree, bool sign)
{
if (sign)
{
return tree;
}
ElementaryFunctionOperation eo = new ElementaryFunctionOperation('-');
List<ObjectFormulaTree> l = new List<ObjectFormulaTree>();
l.Add(tree);
return new ObjectFormulaTree(eo, l);
}
internal static ObjectFormulaTree signed(ObjectFormulaTree tree, char sign)
{
return signed(tree, sign == '+');
}
internal static ObjectFormulaTree Simplify(ObjectFormulaTree tree, ref bool simple)
{
ObjectFormulaTree t = sumSum(tree);
t = delConst(t, ref simple);
return sumSumInverse(t);
}
}
}