using System;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Collections;
using System.Collections.Generic;
using System.Xml;
using System.Linq;
using CategoryTheory;
using DiagramUI;
using DiagramUI.Labels;
using DiagramUI.Interfaces;
using DiagramUI.Aliases;
using BaseTypes.Interfaces;
using SerializationInterface;
using GeneralLinearMethod;
using AnalyticPolynom;
using DataPerformer.Interfaces;
using FormulaEditor;
using FormulaEditor.Interfaces;
namespace DataPerformer
{
/// <summary>
/// Vector formula data transformer
/// </summary>
[Serializable()]
public class VectorFormulaConsumer : DataConsumer,
IMeasurements, ISerializable,
IPostSetArrow, IAlias, ICheckCorrectness,
ITimeMeasureConsumer, IVariableDetector,
IStarted, ITreeCollection, ITimeVariable, IReplaceMeasurements
{
#region Fields
/// <summary>
/// Resource string
/// </summary>
public static readonly string ExternalParameter_ = "External parameter ";
/// <summary>
/// Resource string
/// </summary>
public static readonly string _IsNotDefined = " is not defined";
/// <summary>
/// Output measurements
/// </summary>
protected FormulaMeasure[] measurements;
/// <summary>
/// Results of calculation
/// </summary>
protected object[,] result;
/// <summary>
/// String representation of formulas
/// </summary>
protected string[] formulaString;
/// <summary>
/// Formulas
/// </summary>
protected MathFormula[] formula;
/// <summary>
/// Input parameter
/// </summary>
protected DynamicalParameter par;
/// <summary>
/// Input arguments
/// </summary>
protected ArrayList arguments = new ArrayList();
/// <summary>
/// All variables
/// </summary>
protected string allVariables;
/// <summary>
/// Parameters
/// </summary>
protected Hashtable parameters = new Hashtable();
/// <summary>
/// External unaries
/// </summary>
protected ArrayList operations = new ArrayList();
/// <summary>
/// The "Formula" string
/// </summary>
const string Formula_ = "Formula_";
/// <summary>
/// Dictionary of acceptors
/// </summary>
private Dictionary<string, IOperationAcceptor> acc = new Dictionary<string, IOperationAcceptor>();
/// <summary>
/// Names of unaries
/// </summary>
protected Hashtable operationNames = new Hashtable();
/// <summary>
/// The "is serialized" sign
/// </summary>
protected bool isSerialized = false;
/// <summary>
/// Operation table
/// </summary>
protected Hashtable opTable;
/// <summary>
/// The "Calculate derivation" sign
/// </summary>
private bool calculateDerivation = false;
/// <summary>
/// Order of derivation
/// </summary>
protected int deriOrder = 0;
/// <summary>
/// Formula creator
/// </summary>
protected IFormulaObjectCreator creator;
/// <summary>
/// Feedback
/// </summary>
protected Dictionary<int, string> feedback = new Dictionary<int, string>();
/// <summary>
/// Feedback aliases
/// </summary>
protected Dictionary<int, AliasName> feedAliases = new Dictionary<int, AliasName>();
/// <summary>
/// Proxy
/// </summary>
protected ITreeCollectionProxy proxy;
/// <summary>
/// Update
/// </summary>
protected Action update;
/// <summary>
/// Time variable
/// </summary>
protected VariableMeasure timeVariable = null;
/// <summary>
/// Replacement of feedback
/// </summary>
protected Dictionary<string, string> replacement = new Dictionary<string, string>();
private Guid guid = Guid.NewGuid();
#endregion
#region Ctor
/// <summary>
/// Constructor
/// </summary>
public VectorFormulaConsumer()
: base(39)
{
init();
arguments = new ArrayList();
}
/// <summary>
/// Deserialization constructor
/// </summary>
/// <param name="info">Serialization info</param>
/// <param name="context">Streaming context</param>
public VectorFormulaConsumer(SerializationInfo info, StreamingContext context)
:
base(39)
{
init();
try
{
formulaString = (string[])info.GetValue("Formulas", typeof(string[]));
isSerialized = true;
arguments = (ArrayList)info.GetValue("Arguments", typeof(ArrayList));
parameters = (Hashtable)info.GetValue("Parameters", typeof(Hashtable));
operationNames = (Hashtable)info.GetValue("Unaries", typeof(Hashtable));
calculateDerivation = (bool)info.GetValue("CalculateDerivation", typeof(bool));
if (calculateDerivation)
{
deriOrder = 1;
}
try
{
comments = (byte[])info.GetValue("Comments", typeof(byte[]));
}
catch (Exception ex)
{
ex.Log();
}
deriOrder = (int)info.GetValue("DerivationOrder", typeof(int));
try
{
feedback = Serialization.Deserialize<Dictionary<int, string>>("Feedback", info);
}
catch (Exception exc)
{
exc.Log();
}
}
catch (Exception ex)
{
ex.Log();
}
init();
}
#endregion
#region Overriden Members
/// <summary>
/// ISerializable interface implementation
/// </summary>
/// <param name="info">Serialization info</param>
/// <param name="context">Streaming context</param>
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Formulas", formulaString);
info.AddValue("Arguments", arguments);
info.AddValue("Parameters", parameters);
info.AddValue("Unaries", operationNames);
info.AddValue("CalculateDerivation", calculateDerivation);
if (comments != null)
{
info.AddValue("Comments", comments);
}
info.AddValue("DerivationOrder", deriOrder);
Serialization.Serialize<Dictionary<int, string>>("Feedback", info, feedback);
}
/*new public XmlElement CreateXml(XmlDocument doc)
{
XmlElement el = doc.CreateElement("VectorFormulaConsumer");
for (int i = 0; i < formulaString.Length; i++)
{
XmlElement ef = doc.CreateElement("VectorFormula");
XmlAttribute attr = doc.CreateAttribute("Formula");
attr.Value = formulaString[i];
ef.Attributes.Append(attr);
XmlAttribute id = doc.CreateAttribute("FormulaId");
id.Value = i + "";
ef.Attributes.Append(id);
el.AppendChild(ef);
}
return el;
}*/
#endregion
#region IAlias Members
/// <summary>
/// Names of aliases
/// </summary>
public IList<string> AliasNames
{
get
{
List<string> s = new List<string>();
foreach (string str in parameters.Keys)
{
s.Add(str);
}
return s;
}
}
/// <summary>
/// Access to alias object
/// </summary>
public object this[string alias]
{
get
{
return parameters[alias];
}
set
{
//char c = alias[0];
/*if (arg != null)
{
arg[c] = value;
}*/
parameters[alias] = value;
// AliasNameVariable var = acc[value] as AliasNameVariable;
// var.
//acc[alias] = new AliasNameVariable(alias, this, alias);
}
}
/// <summary>
/// Gets object type
/// </summary>
/// <param name="name">Object name</param>
/// <returns>Returns type of alias object</returns>
public object GetType(string name)
{
return AliasTypeDetector.Detector.DetectType(this[name]);
}
#endregion
#region IMeasurements Members
/// <summary>
/// The count of measurements
/// </summary>
int IMeasurements.Count
{
get
{
return Dimension;
}
}
/// <summary>
/// Access to n - th measurement
/// </summary>
IMeasure IMeasurements.this[int n]
{
get
{
if (measurements == null)
{
this.Throw(new Exception("Undefined measurements"));
}
IMeasure m = measurements[n];
if (m == null)
{
this.Throw(new Exception("Undefined measure"));
}
return m;
}
}
/// <summary>
/// Updates measurements data
/// </summary>
public void UpdateMeasurements()
{
if (IsUpdated)
{
return;
}
try
{
if (par == null)
{
throw new Exception(DynamicalParameter.UndefinedParameters);
}
if (measurements == null)
{
throw new Exception("Formulas are not accepted");
}
UpdateChildrenData();
update();
foreach (int i in feedAliases.Keys)
{
IMeasure m = measurements[i];
object r = m.Parameter();
if (r != null)
{
feedAliases[i].SetValue(r);
}
}
isUpdated = true;
}
catch (Exception e)
{
e.Log();
this.Throw(e);
}
}
#endregion
#region ICheckCorrectness Members
/// <summary>
/// Checks its correctenss
/// </summary>
public void CheckCorrectness()
{
try
{
}
catch (Exception e)
{
e.Log();
this.Throw(e);
}
}
#endregion
#region ITimeMeasureConsumer Members
IMeasure ITimeMeasureConsumer.Time
{
get
{
return VariableMeasure.GetTimeMeasure(this);
}
set
{
VariableMeasure.Set(value, this);
}
}
#endregion
#region IVariableDetector Members
IOperationAcceptor IVariableDetector.Detect(MathSymbol sym)
{
string key = sym.String;
if (key.Length > 1)
{
return null;
}
if (!(sym is SimpleSymbol))
{
return null;
}
SimpleSymbol ss = sym as SimpleSymbol;
if (!ss.Italic)
{
return null;
}
if (acc.ContainsKey(key))
{
return acc[key];
}
return VariableDetector.Detect(sym, acc);
}
#endregion
#region IStarted Members
void IStarted.Start(double time)
{
foreach (FormulaMeasure fm in measurements)
{
fm.Reset();
}
}
#endregion
#region ITreeCollection Members
ObjectFormulaTree[] ITreeCollection.Trees
{
get
{
return FormulaMeasure.GetTrees(measurements);
}
}
#endregion
#region ITimeVariable Members
VariableMeasure ITimeVariable.Variable
{
get { return timeVariable; }
}
#endregion
#region IReplaceMeasurements Members
void IReplaceMeasurements.Replace(IMeasurements oldMeasurements, IMeasure oldMeasure, IMeasurements newMeasurements, IMeasure newMeasure)
{
if (oldMeasure == newMeasure)
{
return;
}
foreach (string key in acc.Keys)
{
object op = acc[key];
if (!(op is VariableMeasure))
{
continue;
}
VariableMeasure vm = op as VariableMeasure;
if (vm.Measure == oldMeasure)
{
if (vm == timeVariable)
{
timeVariable = null;
}
vm.Measure = newMeasure;
string s = vm.Symbol + " = ";
int i = 0;
for (; i < arguments.Count; i++)
{
string ss = arguments[i] as string;
ss = ss.Substring(0, 4);
if (ss.Equals(s))
{
break;
}
}
if (i < arguments.Count)
{
string so = arguments[i] as string;
string sr = s + this.GetRelativeName(newMeasurements as IAssociatedObject);
sr += "." + newMeasure.Name;
replacement[sr] = so;
arguments.Insert(i, sr);
arguments.RemoveAt(i + 1);
}
}
}
}
#endregion
#region IPostSetArrow
/// <summary>
/// The operation that performs after arrows setting
/// </summary>
public void PostSetArrow()
{
try
{
isSerialized = true;
DynamicalParameter parameter = new DynamicalParameter();
foreach (IMeasurements measurements in measurementsData)
{
string name = this.GetMeasurementName(measurements);
for (int i = 0; i < measurements.Count; i++)
{
IMeasure measure = measurements[i];
string p = name + "." + measure.Name;
foreach (string s in arguments)
{
if (s.Substring(4).Equals(p))
{
char c = s[0];
parameter.Add(c, measure);
string key = c + "";
//if (!acc.ContainsKey(key))
//{
acc[c + ""] = VariableMeasure.Create(c + "", measure, this);
//}
}
}
}
}
timeVariable = null;
IMeasure timeMeasure = StaticDataPerformerExtension.TimeProvider.TimeMeasure;
foreach (string s in arguments)
{
if (s.Substring(4).Equals("Time"))
{
//timeChar = s[0];
// parameter.Add(s[0], timeMeasure);
string key = s[0] + "";
if (!acc.ContainsKey(key))
{
timeVariable = VariableMeasure.Create(s[0] + "", timeMeasure, this);
acc[key] = timeVariable;
}
}
}
Parameter = parameter;
string argStr = AllVariables;
foreach (string key in parameters.Keys)
{
if (!acc.ContainsKey(key))
{
acc[key] = new AliasNameVariable(key, this, key);
}
}
postSetUnary();
}
catch (Exception ex)
{
ex.Log();
if (deriOrder >= 0)
{
if (ex.Message.Equals("VariableMeasure.Derivation"))
{
--deriOrder;
PostSetArrow();
return;
}
}
this.Throw(ex);
}
SetFeedback();
}
#endregion
#region Members
// #region Members
/// <summary>
/// Comments
/// </summary>
public ICollection Comments
{
get
{
return PureDesktopPeer.Deserialize(comments) as ICollection;
}
set
{
comments = PureDesktopPeer.Serialize(value);
}
}
/// <summary>
/// Feedback
/// </summary>
public Dictionary<int, string> Feedback
{
get
{
return feedback;
}
set
{
feedback = value;
SetFeedback();
}
}
/// <summary>
/// Adds operation
/// </summary>
/// <param name="op">The operation to add</param>
public void AddOperation(IObjectOperation op)
{
operations.Add(op);
}
/// <summary>
/// Count of external operations
/// </summary>
public int OperationsCount
{
get
{
return operations.Count;
}
}
/// <summary>
/// Gets i - th external opreation
/// </summary>
/// <param name="i">The index of operation</param>
/// <returns>The i - th unary</returns>
public IObjectOperation GetOperation(int i)
{
return operations[i] as IObjectOperation;
}
/// <summary>
/// Numbers of operations
/// </summary>
public ArrayList OperationNumbers
{
get
{
return SeriesSymbol.GetOperationIndexes(formula);
}
}
/// <summary>
/// Names of external unatries
/// </summary>
public Hashtable OperationNames
{
get
{
return operationNames;
}
}
/// <summary>
/// Removes operation source
/// </summary>
/// <param name="op">The source to add</param>
public void RemoveOperation(IObjectOperation op)
{
operations.Remove(op);
}
/// <summary>
/// The "Calculate derivation" sign
/// </summary>
public bool CalculateDerivation
{
get
{
return calculateDerivation;
}
set
{
calculateDerivation = value;
}
}
/// <summary>
/// Input parameters
/// </summary>
public string InputParameters
{
get
{
string var = Variables;
string s = "";
foreach (char c in var)
{
if (parameters.ContainsKey("" + c))
{
continue;
}
s += c;
}
return s;
}
}
/// <summary>
/// Accept parameters
/// </summary>
/// <param name="s">String that contains parameters characters</param>
public void AcceptParameters(string s)
{
parameters.Clear();
string str = "";
str = ElementaryObjectDetector.GetVariables(formula);
foreach (char c in s)
{
if (str.IndexOf(c) < 0)
{
throw new Exception("Illegal formula parameter");
}
}
foreach (char c in s)
{
double a = 0;
parameters["" + c] = a;
//arg[c] = a;
}
}
/// <summary>
/// The "is complete" sign
/// </summary>
public bool IsComplete
{
get
{
int n = 0;
foreach (object o in acc.Values)
{
if (o is VariableMeasure)
{
++n;
}
}
return n == arguments.Count;
}
}
/// <summary>
/// The name of measurements source
/// </summary>
public string SourceName
{
get
{
INamedComponent comp = Object as INamedComponent;
return comp.Name;
}
}
/// <summary>
/// Arguments of this object
/// </summary>
public ArrayList Arguments
{
get
{
return arguments;
}
set
{
string str = Variables;
//bool b = false;
foreach (char c in str)
{
foreach (string s in value)
{
if (s[0] == c)
{
goto m;
}
}
throw new Exception(VariablesShortage + " : " + c);
m:
continue;
}
arguments = value;
}
}
/// <summary>
/// The input dynamical parameter
/// </summary>
public DynamicalParameter Parameter
{
set
{
par = value;
proxy = null;
if (!isSerialized)
{
acc.Clear();
foreach (char c in par.Variables)
{
string key = c + "";
if (!acc.ContainsKey(key))
{
VariableMeasure v = VariableMeasure.Create(c + "", par[c], this);
acc[key] = v;
}
}
}
int n = Dimension;
measurements = new FormulaMeasure[n];
result = new object[n, 2];
ObjectFormulaTree[] trees = new ObjectFormulaTree[n];
if (!isSerialized)
{
arguments.Clear();
}
Hashtable ops = operationTable;
if (!isSerialized)
{
ops = opTable;
}
isSerialized = false;
Hashtable table = new Hashtable();
string var = par.Variables;
Double a = 0;
if (allVariables == null)
{
allVariables = AllVariables;
}
foreach (char c in allVariables)
{
table[c] = a;
}
string proh = "";
foreach (char c in var)
{
IMeasure m = par[c];
object t = m.Type;
if (t is IOneVariableFunction)
{
proh += c;
table[c] = m.Parameter();
}
else
{
table[c] = t;
}
}
foreach (string s in parameters.Keys)
{
object o = parameters[s];
table[s[0]] = AliasTypeDetector.Detector.DetectType(o);
if (!acc.ContainsKey(s))
{
acc[s] = new AliasNameVariable(s, this, s);
}
}
AssociatedAddition aa = new AssociatedAddition(this, null);
for (int i = 0; i < n; i++)
{
MathFormula f = formula[i].FullTransform(proh);
SeriesSymbol.SetOperations(f, ops);
try
{
ObjectFormulaTree t = ObjectFormulaTree.CreateTree(f, creator);
measurements[i] = FormulaMeasure.Create(t, deriOrder, Formula_ + (i + 1), aa);
}
catch (Exception ex)
{
ex.Log();
if (ex.Message.Equals("VariableMeasure.Derivation"))
{
throw ex;
}
throw new Exception("Formula " + (i + 1) + " : " + ex.Message);
}
}
try
{
proxy = this.CreateProxy();
/* Unfinished code !!! Debug of proxy
if (allVariables.Equals("cab"))
{
ITreeCollection tc = this;
List<ObjectFormulaTree> optional = new List<ObjectFormulaTree>();
ObjectFormulaTree[] t = ObjectFormulaTree.CreateList(tc.Trees, optional).ToArray<ObjectFormulaTree>();
proxy = new Calculation.Calculate(t);
}
*/
update = proxy.Update;
FormulaMeasure.Set(measurements, proxy);
foreach (string key in replacement.Keys)
{
string varp = key[0] + "";
if (!acc.ContainsKey(varp))
{
continue;
}
object o = acc[varp];
if (!(o is VariableMeasure))
{
continue;
}
VariableMeasure vm = o as VariableMeasure;
string name = key.Substring(4);
foreach (IMeasurements mea in measurementsData)
{
string sn = this.GetRelativeName(mea as IAssociatedObject);
for (int i = 0; i < mea.Count; i++)
{
IMeasure mm = mea[i];
string snn = sn + "." + mm.Name;
if (snn.Equals(name))
{
vm.Measure = mm;
goto me;
}
}
}
me:
continue;
}
SetFeedback();
}
catch (Exception ex)
{
ex.Log();
}
}
}
/// <summary>
/// All formulas variables
/// </summary>
public string AllVariables
{
get
{
//try
//{
if (allVariables == null)
{
formula = new MathFormula[formulaString.Length];
for (int i = 0; i < formula.Length; i++)
{
formula[i] = MathFormula.FromString(MathSymbolFactory.Sizes, formulaString[i]);
}
allVariables = ElementaryObjectDetector.GetVariables(formula);
}
return allVariables;
}
}
/// <summary>
/// Variables
/// </summary>
public string Variables
{
get
{
try
{
string s = "";
string str = ElementaryObjectDetector.GetVariables(formula);
foreach (char c in str)
{
if (!parameters.ContainsKey("" + c) & s.IndexOf(c) < 0)
{
s += c;
}
}
return s;
}
catch (Exception ex)
{
ex.Log();
}
return "";
}
}
/// <summary>
/// Create aliases
/// </summary>
/// <param name="str">String of aliases</param>
public void CreateAliases(string str)
{
parameters.Clear();
foreach (char c in str)
{
double a = 0;
parameters["" + c] = a;
}
}
/// <summary>
/// Dimension of output vector
/// </summary>
public int Dimension
{
get
{
return formulaString.Length;
}
set
{
formulaString = new string[value];
result = null;
formula = null;
}
}
/// <summary>
/// Set formula to i - th component
/// </summary>
/// <param name="s">The string representation of formula</param>
/// <param name="i">The component number</param>
public void SetFormula(string s, int i)
{
formulaString[i] = s;
}
/// <summary>
/// Gets i - th component formula
/// </summary>
/// <param name="i">The component number</param>
/// <returns>The string representation of formula</returns>
public string GetFormula(int i)
{
return formulaString[i];
}
/// <summary>
/// Accepts formulas
/// </summary>
public void AcceptFormulas()
{
try
{
int n = Dimension;
measurements = new FormulaMeasure[n];
formula = new MathFormula[n];
result = new object[n, 2];
parameters.Clear();
arguments.Clear();
par = null;
for (int i = 0; i < n; i++)
{
MathFormula form = MathFormula.FromString(MathSymbolFactory.Sizes, formulaString[i]);
formula[i] = form;
}
allVariables = ElementaryObjectDetector.GetVariables(formula);
}
catch (Exception e)
{
e.Log();
this.Throw(e);
}
}
/// <summary>
/// Accepts formulas
/// </summary>
private void acceptFormulas()
{
try
{
AssociatedAddition aa = new AssociatedAddition(this, null);
int n = Dimension;
measurements = new FormulaMeasure[n];
result = new object[n, 2];
for (int i = 0; i < n; i++)
{
MathFormula formula = MathFormula.FromString(MathSymbolFactory.Sizes, formulaString[i]);
MathFormula f = formula.FullTransform(null);
ObjectFormulaTree t = ObjectFormulaTree.CreateTree(f, ElementaryFunctionsCreator.Object);
measurements[i] = FormulaMeasure.Create(t, deriOrder, Formula_ + (i + 1), aa);
}
}
catch (Exception e)
{
e.Log();
this.Throw(e);
}
}
/// <summary>
/// The correctess sign
/// </summary>
public bool IsCorrect
{
get
{
return true;
}
}
/// <summary>
/// Operations
/// </summary>
public ArrayList Operations
{
get
{
return operations;
}
}
/// <summary>
/// Table of operations
/// </summary>
public Hashtable OperationTable
{
set
{
SeriesSymbol.SetOperations(formula, value);
opTable = value;
setOperationNames(value);
}
}
/// <summary>
/// Order of derivation
/// </summary>
public int DerivationOrder
{
get
{
return deriOrder;
}
set
{
deriOrder = value;
}
}
private void SetFeedback()
{
feedAliases.Clear();
foreach (int i in feedback.Keys)
{
feedAliases[i] = this.FindAliasName(feedback[i], false);
}
}
private void setOperationNames(Hashtable table)
{
operationNames.Clear();
foreach (int i in table.Keys)
{
ICategoryObject o = table[i] as ICategoryObject;
IObjectLabel l = o.Object as IObjectLabel;
operationNames[i] = this.GetRelativeName(o);
}
}
private void setUnaryTrees(Hashtable table)
{
string str = Variables;
}
private void postSetUnary()
{
Hashtable t = operationTable;
setUnaryTrees(t);
}
private Hashtable operationTable
{
get
{
Hashtable t = new Hashtable();
foreach (ICategoryObject o in operations)
{
IObjectLabel l = o.Object as IObjectLabel;
string name = this.GetRelativeName(o);//l.Name;
if (!operationNames.ContainsValue(name))
{
continue;
}
foreach (int i in operationNames.Keys)
{
if (name.Equals(operationNames[i]))
{
t[i] = o;
break;
}
}
}
return t;
}
}
/// <summary>
/// Initialization
/// </summary>
private void init()
{
update = delegate()
{
foreach (FormulaMeasure m in measurements)
{
m.Update();
}
};
creator = VariableDetector.GetCreator(this);
}
#endregion
}
}