Click here to Skip to main content
15,895,777 members
Articles / Programming Languages / C#

Universal Framework for Science and Engineering - Part 2: Regression

Rate me:
Please Sign up or sign in to vote.
4.77/5 (19 votes)
11 Jul 20067 min read 51.2K   5K   76  
An article on universal scalable engineering framework applications.
using System;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Collections;
using System.Collections.Generic;
using System.Xml;


using CategoryTheory;
using DiagramUI;
using FormulaEditor;
using GeneralLinearMethod;
using AnalyticPolynom;


namespace DataPerformer
{


	/// <summary>
	/// Formula transformer of mesurements. It is measurements consumer
	/// </summary>
	[Serializable()]
	public class FormulaDataConsumer : DataConsumer, IMeasurements, ISerializable,
		IPostSetArrow, IAlias
	{
		/// <summary>
		/// Output measurement
		/// </summary>
		private IMeasure measure;

		/// <summary>
		/// Output value
		/// </summary>
		private double result;

		/// <summary>
		/// String representation of formula
		/// </summary>
		private string formulaString = "";

		/// <summary>
		/// The object's formula
		/// </summary>
		private MathFormula formula;

		/// <summary>
		/// Tree of the formula
		/// </summary>
		private ObjectFormulaTree tree;

		/// <summary>
		/// The formula argument
		/// </summary>
		private ElementaryObjectArgument arg;

		/// <summary>
		/// Input parameter
		/// </summary>
		private DynamicalParameter par;

		/// <summary>
		/// The formula arguments
		/// </summary>
		private ArrayList arguments;

		/// <summary>
		/// Derivation of output parameter
		/// </summary>
		private double derivation;

		/// <summary>
		/// Partial derivations
		/// </summary>
		private Hashtable derivations = new Hashtable();

		/// <summary>
		/// Table of parameters
		/// </summary>
		private Hashtable parameters = new Hashtable();
		
		/// <summary>
		/// Constructor
		/// </summary>
		public FormulaDataConsumer() : base(11)
		{
			init();
			arguments = new ArrayList();
		}
		
		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="info">Serialization info</param>
		/// <param name="context">Streaming context</param>
		public FormulaDataConsumer(SerializationInfo info, StreamingContext context) : 
			base(11)
		{
			formulaString = (string)info.GetValue("Formula", typeof(string));
			if (formulaString.Length > 0)
			{
				Formula = formulaString;
			}
			arguments = (ArrayList)info.GetValue("Arguments", typeof(ArrayList));
			parameters = (Hashtable)info.GetValue("Parameters", typeof(Hashtable));
			init();
		}

		/// <summary>
		/// ISerializable interface implementation
		/// </summary>
		/// <param name="info">Serialization info</param>
		/// <param name="context">Streaming context</param>
		new public void GetObjectData(SerializationInfo info, StreamingContext context)
		{
			info.AddValue("Formula", formulaString);
			info.AddValue("Arguments", arguments);
			info.AddValue("Parameters", parameters);
		}

		/// <summary>
		/// Creates correspond xml
		/// </summary>
		/// <param name="doc">document to create element</param>
		/// <returns>The created element</returns>
		/*new public XmlElement CreateXml(XmlDocument doc)
		{
			XmlElement el = doc.CreateElement("FormulaDataConsumer");
			XmlAttribute attr = doc.CreateAttribute("Formula");
			attr.Value = Formula;
			el.Attributes.Append(attr);
			foreach (string s in arguments)
			{
				XmlElement ea = doc.CreateElement("FormulaArgument");
				XmlAttribute attrArg = doc.CreateAttribute("Argument");
				attrArg.Value = s;
				ea.Attributes.Append(attrArg);
				el.AppendChild(ea);
			}
			

			return el;
		}*/


		/// <summary>
		/// The count of measurements
		/// </summary>
		int IMeasurements.Count
		{
			get
			{
				return 1;
			}
		}

		/// <summary>
		/// Access to n - th measurement
		/// </summary>
		IMeasure IMeasurements.this[int n]
		{
			get
			{
				return measure;
			}
		}

		/// <summary>
		/// Updates measurements data
		/// </summary>
		public void UpdateMeasurements()
		{
			if (IsUpdated)
			{
				return;
			}
			try
			{
				if (par == null)
				{
					throw new Exception(DynamicalParameter.UndefinedParameters);
				}
				UpdateChildrenData();
				par.Set(arg);
				result = (double)tree.Result;
				derivation = 0;
				string str = arg.Variables;
				foreach (char c in str)
				{
					string s = c + "";
					if (parameters.ContainsKey(s))
					{
						continue;
					}
					IMeasure m = par[c];
                    if (!(m is IDerivation))
                    {
                        derivation = 0;
                        break;
                    }
                    IDerivation p = m as IDerivation;
					ObjectFormulaTree t = derivations[c] as ObjectFormulaTree;
					derivation += (double)t.Result * p.Derivation;
				}
				isUpdated = true;
			}
			catch (Exception e)
			{
				PureDesktop.ThrowException(this, e);
			}
		}

		/// <summary>
		/// The header control of measurements
		/// </summary>
		/*public Control HeaderControl
		{
			get
			{
				return new FormulaControl(this);
			}
		}*/

		/// <summary>
		/// Accepts parameters
		/// </summary>
		/// <param name="s">String of parameters</param>
		public void AcceptParameters(string s)
		{
			parameters.Clear();
			par = null;
			arg = new ElementaryObjectArgument();
			arg.Add(tree);
			string str = arg.Variables;
			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 operation that performs after arrows setting
		/// </summary>
		public void PostSetArrow()
		{
			if (tree == null)
			{
				return;
			}
			DynamicalParameter parameter = new DynamicalParameter();
            foreach (IMeasurements measurements in measurementsData)
			{
				/*IAssociatedObject cont = measurements as IAssociatedObject;
				INamedComponent comp = cont.Object as INamedComponent;*/
				string name = DataConsumer.GetName(this, measurements);//comp.Name;
				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);
						}
					}
				}
			}
			foreach (string s in arguments)
			{
				if (s.Substring(4).Equals("Time"))
				{
					parameter.Add(s[0], DataConsumer.TimeMeasure);
				}
			}
			Parameter = parameter;
			foreach (string s in AliasNames)
			{
				arg[s[0]] = this[s];
			}
		}


		/// <summary>
		/// The name of measurements source
		/// </summary>
		public string SourceName
		{
			get
			{
				INamedComponent comp = obj as INamedComponent;
				return comp.Name;
			}
		}
		
		/// <summary>
		/// String representation of formula
		/// </summary>
		public string Formula
		{
			get
			{
				return formulaString;

			}
			set
			{
				formula = MathFormula.FromString(MathSymbolFactory.Sizes, value);
				formulaString = value;
				MathFormula f = formula.FullTransform;
				tree = new ObjectFormulaTree(f, ElementaryFunctionsCreator.Object);
				arg = new ElementaryObjectArgument();
				arg.Add(tree);
				string var = arg.Variables;
				derivations.Clear();
				parameters.Clear();
				foreach (char c in var)
				{
					ObjectFormulaTree t = DerivationPerformer.Derivation(tree, c + "");
					arg.Add(t);
					t = ElementarySimplifier.Simplify(t);
					derivations[c] = t;
				}
			}
		}

		/// <summary>
		/// The formula arguments
		/// </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);
				m:
					b = b;
				}
				arguments = value;
			}
		}

		/// <summary>
		/// Input dynamical parameter
		/// </summary>
		public DynamicalParameter Parameter
		{
			set
			{
				arg = new ElementaryObjectArgument();
				arg.Add(tree);
				par = value;
			}
		}

		/// <summary>
		/// Formula variables
		/// </summary>
		public string Variables
		{
			get
			{
				string s = "";
				ElementaryObjectArgument arg = new ElementaryObjectArgument();
				string str = arg.Variables;
				foreach (char c in str)
				{
					if (!parameters.ContainsKey("" + c))
					{
						s += c;
					}
				}
				return s;
			}
		}


		/// <summary>
		/// Names of aliases
		/// </summary>
		public List<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];
				double a = (double)value;
				arg[c] = a;
				parameters[alias] = a;
			}
		}

        /// <summary>
        /// Gets alias type
        /// </summary>
        /// <param name="n"></param>
        /// <returns></returns>
        public object GetType(int n)
        {
            Double a = 0;
            return a;
        }


		/// <summary>
		/// Calculates formula result
		/// </summary>
		/// <returns>The formula result</returns>
		private object calculate()
		{
			return result;
		}

		/// <summary>
		/// Calculates derivation
		/// </summary>
		/// <returns>The derivation</returns>
		private object getDerivation()
		{
			return derivation;
		}
		
		/// <summary>
		/// Initialization
		/// </summary>
		private void init()
		{
			measure = new MeasureDerivation(tree.ReturnType, new MeasureParameter(calculate), new MeasureParameter(getDerivation), "result");
		}

	}


	/// <summary>
	/// Solver of ordinary differential equations systev
	/// </summary>
	[Serializable()]
	public class DifferentialEquationSolver : DataConsumer, IDifferentialEquationSolver, ISerializable,
		IPostSetArrow, IStarted, IAlias, ICheckCorrectness	
	{
		
		#region Fields
		/// <summary>
		/// arguments of right parts
		/// </summary>
		private ElementaryObjectArgument arg;

		/// <summary>
		/// Input dynamical parameter
		/// </summary>
		private DynamicalParameter par;

		/// <summary>
		/// Table of variables of equations. Table contains initial values and derivations of variables
		/// </summary>
		private Hashtable variables = new Hashtable();

		/// <summary>
		/// Table representation of input parameters
		/// </summary>
		private Hashtable parameters = new Hashtable();

		/// <summary>
		/// Output parameters
		/// </summary>
		private ArrayList output;
		
		/// <summary>
		/// The time
		/// </summary>
		private double time;

		/// <summary>
		/// Current time
		/// </summary>
		private double timeOld;

		/// <summary>
		/// List of right parts arguments
		/// </summary>
		private ArrayList arguments = new ArrayList();

		/// <summary>
		/// Table representation of variables
		/// </summary>
		private Hashtable vars = new Hashtable();

		/// <summary>
		/// Table representation of parameters
		/// </summary>
		private Hashtable pars = new Hashtable();

		/// <summary>
		/// Table of aliases
		/// </summary>
		private Hashtable aliases = new Hashtable();

		/// <summary>
		/// Table of aliases names
		/// </summary>
		private Hashtable aliasNames = new Hashtable();

		/// <summary>
		/// Table of external aliases
		/// </summary>
		private Hashtable  externalAliases = new Hashtable();


		/// <summary>
		/// The "is serialized" flag
		/// </summary>
		private bool isSerialized = false;

		#endregion

		#region Constructors
		
		/// <summary>
		/// Consructor
		/// </summary>
		public DifferentialEquationSolver() : base(30)
		{
			init();
			vars = new Hashtable();
			pars = new Hashtable();
			aliases = new Hashtable();
			arguments = new ArrayList();
		}
		

		/// <summary>
		/// Consructor
		/// </summary>
		/// <param name="info">Serialization info</param>
		/// <param name="context">Streaming context</param>
		public DifferentialEquationSolver(SerializationInfo info, StreamingContext context) : 
			base(30)
		{
			init();
			try
			{
				isSerialized = true; 
				vars = (Hashtable)info.GetValue("Vars", typeof(Hashtable));
				pars = (Hashtable)info.GetValue("Pars", typeof(Hashtable));
				aliases = (Hashtable)info.GetValue("Aliases", typeof(Hashtable));
				arguments = (ArrayList)info.GetValue("Arguments", typeof(ArrayList));
				aliasNames = (Hashtable)info.GetValue("AliasNames", typeof(Hashtable));
				comments = (ArrayList)info.GetValue("Comments", typeof(ArrayList));
			}
			catch (Exception)
			{
			}
		}

		#endregion

		/// <summary>
		/// ISerializable interface implementation
		/// </summary>
		/// <param name="info">Serialization info</param>
		/// <param name="context">Streaming context</param>
		new public void GetObjectData(SerializationInfo info, StreamingContext context)
		{
			info.AddValue("Vars", vars);
			info.AddValue("Pars", pars);
			info.AddValue("Aliases", aliases);
			info.AddValue("Arguments", arguments);
			info.AddValue("AliasNames", aliasNames);
			info.AddValue("Comments", comments);
		}


		/// <summary>
		/// Creates correspond xml
		/// </summary>
		/// <param name="doc">document to create element</param>
		/// <returns>The created element</returns>
		/*	new public XmlElement CreateXml(XmlDocument doc)
			{
				XmlElement el = doc.CreateElement("DifferentialEquationSolver");
				return el;
			}*/

		/// <summary>
		/// Keys of variables
		/// </summary>
		public ICollection Keys
		{
			get
			{
				return variables.Keys;
			}
		}

		/// <summary>
		/// Access to variable
		/// </summary>
		public string this[char c]
		{
			get
			{
				object[] o = variables[c] as object[];
				return o[0] as string;
			}
		}

		/// <summary>
		/// Sets values of variables
		/// </summary>
		/// <param name="b">Begin index</param>
		/// <param name="x">Array of variables</param>
		public void SetVariables(int b, double[] x)
		{
			int i = b;
			foreach (object[] o in variables.Values)
			{
				o[3] = x[i];
				++i;
			}
		}


		/// <summary>
		/// Comments
		/// </summary>
		public ArrayList Comments
		{
			get
			{
				return comments;
			}
			set
			{
				comments = value;
			}
		}

		
		/// <summary>
		/// The count of measurements
		/// </summary>
		int IMeasurements.Count
		{
			get
			{
				if (output == null)
				{
					return 0;
				}
				return output.Count;
			}
		}

		/// <summary>
		/// Access to n - th measurement
		/// </summary>
		IMeasure IMeasurements.this[int n]
		{
			get
			{
				return output[n] as IMeasure;
			}
		}

		/// <summary>
		/// Updates measurements data
		/// </summary>
		public void UpdateMeasurements()
		{
			if (IsUpdated)
			{
				return;
			}
			try
			{
				UpdateChildrenData();
				isUpdated = true;
			}
			catch (Exception e)
			{
				PureDesktop.ThrowException(this, e);
			}
		}


		/// <summary>
		/// The time
		/// </summary>
		new public double Time
		{
			set
			{
				time = value;
			}
		}

		/// <summary>
		/// The operation that performs after arrows setting
		/// </summary>
		public void PostSetArrow()
		{
			postDeserialize();
			postSetAlias();
		}

		/// <summary>
		/// Checks its correctenss
		/// </summary>
		public void CheckCorrectness()
		{
			try
			{
				//PostSetArrow();
			}
			catch (Exception e)
			{
				PureDesktop.ThrowException(this, e);
			}
		}


		/// <summary>
		/// Accepts measurements
		/// </summary>
		private void acceptMeasurements()
		{
			DynamicalParameter parameter = new DynamicalParameter();
			parameters.Clear();
			foreach (IMeasurements measurements in measurementsData)
			{
				/*IAssociatedObject cont = measurements as IAssociatedObject;
				INamedComponent nc = cont.Object as INamedComponent;*/
				string name = DataConsumer.GetName(this, measurements);//nc.Name;
				for (int i = 0; i < measurements.Count; i++)
				{
					IMeasure measure = measurements[i];
					string p = name + "." + measure.Name;
					foreach (char c in pars.Keys)
					{
						if (!pars.ContainsKey(c))
						{
							continue;
						}
						if (pars[c] == null)
						{
							continue;
						}
						string s = pars[c] as string;
						if (s.Equals(p))
						{
							parameter.Add(c, measure);
							parameters[c] = measure;
						}
					}
				}
			}
			foreach (string s in arguments)
			{
				if (s.Substring(s.Length - 4).Equals("Time"))
				{
					parameter.Add(s[0], DataConsumer.TimeMeasure);
					parameters[s[0]] = DataConsumer.TimeMeasure;
				}
			}
			foreach (char c in pars.Keys)
			{
				if (!parameters.ContainsKey(c))
				{
					if (pars[c] != null)
					{
						PureDesktop.ThrowException(this, new Exception(PureDesktop.GetResourceString(VectorFormulaConsumer.ExternalParameter_) +
							c + PureDesktop.GetResourceString(VectorFormulaConsumer._IsNotDefined)));
					}
				}
			}
			Parameter = parameter;
		}




		/// <summary>
		/// The name of measurements source
		/// </summary>
		public string SourceName
		{
			get
			{
				INamedComponent comp = obj as INamedComponent;
				return comp.Name;
			}
		}
		
		/// <summary>
		/// Arguments of equations
		/// </summary>
		public ArrayList Arguments
		{
			get
			{
				return arguments;
			}
			set
			{
				bool b = false;
				string str = InputParameters;
				string sc = ConstantNames;
				foreach (char c in str)
				{
					if (aliases.ContainsKey(c + ""))
					{
						continue;
					}
					foreach (string s in value)
					{
						if (s[0] == c)
						{
							goto m;
						}
					}
					throw new Exception(DataConsumer.VariablesShortage);
				m:
					b = !b;
				}
				arguments = value;
				pars.Clear();
				foreach (string s in arguments)
				{
					pars[s[0]] = s.Substring(4);
				}
			}
		}

		/// <summary>
		/// Input dynamical parameter
		/// </summary>
		public DynamicalParameter Parameter
		{
			set
			{
				par = value;
			}
		}

		/// <summary>
		/// Starts this object
		/// </summary>
		new public void Start()
		{
			try
			{
				timeOld = time;
				foreach (object[] o in variables.Values)
				{
					o[3] = o[4];
				}
				//calculateDerivations();
			}
			catch (Exception e)
			{
				PureDesktop.ThrowException(this, e);
			}
		}

		/// <summary>
		/// Calculates initial value of variable
		/// </summary>
		/// <param name="c">The variable key</param>
		/// <returns>Initial value of variable</returns>
		public double GetInitialValue(char c)
		{
			object[] o = variables[c] as object[];
			return (double)o[4];
		}
		
		/// <summary>
		/// Adds variable
		/// </summary>
		/// <param name="c">The variable key</param>
		public void AddVariable(char c)
		{
			double a = 0;
			variables[c] = new object[]{"", null, null, a, a, a}; 
			vars[c] = new object[]{"", a};
		}

		/// <summary>
		/// Sets right part formula to variable
		/// </summary>
		/// <param name="c">The variable key</param>
		/// <param name="formula">The string representation of formula</param>
		public void SetVariable(char c, string formula)
		{
			object[] o = variables[c] as object[];
			o[0] = formula;
			object[] ob = vars[c] as object[];
			ob[0] = formula;
		}

		/// <summary>
		/// Sets initial value of variable
		/// </summary>
		/// <param name="c">The variable key</param>
		/// <param name="a">Initial value of variable</param>
		public void SetValue(char c, double a)
		{
			object[] o = variables[c] as object[];
			o[4] = a;
			object[] ob = vars[c] as object[];
			ob[1] = a;
		}


		/// <summary>
		/// All variabeles in formulas
		/// </summary>
		public string AllVariables
		{
			get
			{
				string s = "";
				foreach (object[] o in variables.Values)
				{
					string st = o[0] as string;
					MathFormula f = MathFormula.FromString(MathSymbolFactory.Sizes, st);
					string str = ElementaryObjectDetector.GetVariables(f);
					foreach (char c in str)
					{
						if (s.IndexOf(c) < 0)
						{
							s += c;
						}
					}
				}
				return s;
			}
		}

		/// <summary>
		/// Preparation
		/// </summary>
		public void Prepare()
		{
			
			//parameters.Clear();
			output = new ArrayList();
			string str = "";
			aliases.Clear();
			Double a = 0;
			string var = AllVariables;
			Hashtable table = new Hashtable();
			foreach (char c in var)
			{
				table[c] = a;
			}
			foreach (char c in pars.Keys)
			{
				IMeasure m = parameters[c] as IMeasure;
				table[c] = m.Type;
			}
			IFormulaObjectCreator creator = new FormulaArrayObjectCreator(
				new ElementaryObjectsCreator(table));

			foreach (object[] o in variables.Values)
			{
				string st = o[0] as string;
				MathFormula f = MathFormula.FromString(MathSymbolFactory.Sizes, st);
				o[1] = f;
				ObjectFormulaTree t = new ObjectFormulaTree(f.FullTransform, creator);
				o[2] = t;
				string s = ElementaryObjectDetector.GetVariables(f);
				foreach (char c in s)
				{
					if (str.IndexOf(c) < 0)
					{
						if (!aliases.ContainsKey("" + c))
						{
							str += c;
							if (variables.ContainsKey(c))
							{
								parameters.Remove(c);
								pars.Remove(c);
							}
						}
					}

				}
			}
			foreach (char c in variables.Keys)
			{
				Variable v = new Variable(this, c);
				IMeasure m  = new MeasureDerivation(a, new MeasureParameter(v.calculate), 
					new MeasureParameter(v.derivation), c + "");
				output.Add(m);
				if (str.IndexOf(c) < 0)
				{
					str += c;
				}
			}
			foreach (string s in aliases.Keys)
			{
				str += s;
			}
			arg = new ElementaryObjectArgument();
			foreach (object[] o in variables.Values)
			{
				ObjectFormulaTree tree = o[2] as ObjectFormulaTree;
				arg.Add(tree);
			}
			foreach (string s in aliases.Keys)
			{
				arg[s[0]] = aliases[s];
			}
		}


		/// <summary>
		/// Clears parameters
		/// </summary>
		public void ClearParameters()
		{
			parameters.Clear();
			pars.Clear();
		}

		/// <summary>
		/// String of parameters
		/// </summary>
		public string Parameters
		{
			get
			{
				string s = "";
				foreach (char c in parameters.Keys)
				{
					s += c;
				}
				return s;
			}
		}

		/// <summary>
		/// String of input parameters
		/// </summary>
		public string InputParameters
		{
			get
			{
				string s = "";
				string all = AllVariables;
				foreach (char c in all)
				{
					if (aliases.ContainsKey("" + c) | variables.ContainsKey(c))
					{
						continue;
					}
					s += c;
				}
				return s;
			}
		}

		/// <summary>
		/// String of input parameters
		/// </summary>
		public string AllParameters
		{
			get
			{
				string s = "";
				string all = AllVariables;
				foreach (char c in all)
				{
					if (variables.ContainsKey(c))
					{
						continue;
					}
					s += c;
				}
				return s;
			}
		}


		/// <summary>
		/// Clears aliases
		/// </summary>
		public void ResetAliases()
		{
			aliases.Clear();
			foreach (char c in vars.Keys)
			{
				AddAlias("" + c);
			}
		}

		/// <summary>
		/// Adds alias
		/// </summary>
		/// <param name="alias">The alias to add</param>
		public void AddAlias(string alias)
		{
			double a = 0;
			aliases[alias] = a;
		}

		/// <summary>
		/// Sets input parameter
		/// </summary>
		/// <param name="c">The parameter key</param>
		/// <param name="m">The parameter measurement</param>
		public void SetParameter(char c, IMeasure m)
		{
			parameters[c] = m;
			pars[c] = m.Name;
		}


		/// <summary>
		/// String of constants names
		/// </summary>
		public string ConstantNames
		{
			get
			{
				string str = "";
				List<string> l = AliasNames;
				foreach (string s in l)
				{
					if (!vars.ContainsKey(s[0]))
					{
						str += s;
					}
				}
				return str;
			}
		}

		/// <summary>
		/// Names of aliases
		/// </summary>
		public List<string> AliasNames
		{
			get
			{
				List<string> s = new List<string>();
				foreach (string str in aliases.Keys)
				{
					s.Add(str);
				}
				return s;
			}
		}

		/// <summary>
		/// Access to alias object
		/// </summary>
		public object this[string alias]
		{
			get
			{
				return aliases[alias];
			}
			set
			{
				char c = alias[0];
				double a = (double)value;
				arg[c] = a;
				aliases[alias] = a;
				if (variables.ContainsKey(c))
				{
					SetValue(c, a);
				}
			}
		}

        public object GetType(int n)
        {
            Double a = 0;
            return a;
        }



		/// <summary>
		/// Clears set of variables
		/// </summary>
		public void ClearVariables()
		{
			variables.Clear();
			vars.Clear();
		}
		
		/// <summary>
		/// Gets derivaton of variable
		/// </summary>
		/// <param name="c">The variable key</param>
		/// <returns>The derivation</returns>
		double getDerivation(char c)
		{
			object[] o = variables[c] as object[];
			return (double)o[5];
		}


		/// <summary>
		/// Performs operations after deserialization
		/// </summary>
		private void postDeserialize()
		{
			output = new ArrayList();
			foreach (char c in vars.Keys)
			{
				object[] o = vars[c] as object[];
				double d = 0;
				variables[c] = new object[]{o[0], null, null, o[1], o[1], d}; 
			}
			string str = "";
			foreach (object[] o in variables.Values)
			{
				string st = o[0] as string;
				MathFormula f = MathFormula.FromString(MathSymbolFactory.Sizes, st);
				o[1] = f;
				string s = ElementaryObjectDetector.GetVariables(f);
			}
			Double a = 0;
			foreach (char c in variables.Keys)
			{
				Variable v = new Variable(this, c);
				IMeasure m  = new MeasureDerivation(a, new MeasureParameter(v.calculate), 
					new MeasureParameter(v.derivation), c + "");
				output.Add(m);
				if (str.IndexOf(c) < 0)
				{
					str += c;
				}
			}
			foreach (string s in aliases.Keys)
			{
				str += s;
			}
			if (!isSerialized)
			{
				pars.Clear();
				isSerialized = false;
				foreach (string ps in arguments)
				{
					pars[ps[0]] = ps.Substring(4);
				}
			}
			acceptMeasurements();
			Hashtable table = new Hashtable();
			foreach (char c in str)
			{
				table[c] = a;
			}
			foreach (char c in pars.Keys)
			{
				if (pars.ContainsKey(c))
				{
					if (pars[c] != null)
					{
						IMeasure m = parameters[c] as IMeasure;
						table[c] = m.Type;
					}
				}
			}
			IFormulaObjectCreator creator = new FormulaArrayObjectCreator(
				new ElementaryObjectsCreator(table));
			foreach (object[] o in variables.Values)
			{
				string st = o[0] as string;
				MathFormula f = MathFormula.FromString(MathSymbolFactory.Sizes, st);
				o[1] = f;
				ObjectFormulaTree t = new ObjectFormulaTree(f.FullTransform, creator);
				o[2] = t;

			}

			arg = new ElementaryObjectArgument();
			foreach (object[] o in variables.Values)
			{
				ObjectFormulaTree tree = o[2] as ObjectFormulaTree;
				arg.Add(tree);
			}
			foreach (string s in aliases.Keys)
			{
				arg[s[0]] = (double)aliases[s];
			}
		}
	
		/// <summary>
		/// Initialization
		/// </summary>
		private void init()
		{
		}

		/// <summary>
		/// Gets value of variable
		/// </summary>
		/// <param name="c">The variable keu</param>
		/// <returns>The value of variable</returns>
		private double getValue(char c)
		{
			object[] o = variables[c] as object[];
			return (double)o[3];
		}

		/// <summary>
		/// Calculates derivations
		/// </summary>
		public void CalculateDerivations()
		{
			try
			{
				foreach (char c in externalAliases.Keys)
				{
					object[] o = externalAliases[c] as object[];
					IAlias al = o[0] as IAlias;
					string s = o[1] as string;
					object[] ob = variables[c] as object[];
					al[s] = ob[3];
				}
				UpdateChildrenData();
				foreach (char c in parameters.Keys)
				{
					IMeasure m = parameters[c] as IMeasure;
					if (m == null)
					{
						throw new Exception(DynamicalParameter.UndefinedParameters);
					}
					arg[c] = m.Parameter();
				}
				foreach (char c in variables.Keys)
				{
					object[] o = variables[c] as object[]; 
					arg[c] = o[3];
				}
				foreach (char c in variables.Keys)
				{
					object[] o = variables[c] as object[];
					ObjectFormulaTree t = o[2] as ObjectFormulaTree;
					o[5] = t.Result;
				}
			}
			catch (Exception e)
			{
				PureDesktop.ThrowException(this, e);
			}
		}

		public Hashtable ExternalAliases
		{
			get
			{
				return aliasNames;
			}
			set
			{
				aliasNames = value;
				postSetAlias();
			}
		}

		public override List<string> AllAliases
		{
			get
			{
				List<string> a = new List<string>();
				DataConsumer.GetAliases(this, a);
				return a;
			}
		}

		private void postSetAlias()
		{
			externalAliases.Clear();
			if (aliasNames == null)
			{
				return;
			}
			foreach (char c in aliasNames.Keys)
			{
				string s = aliasNames[c] as string;
				externalAliases[c] = DataConsumer.FindAlias(this, s);
			}
		}


		/// <summary>
		/// Auxiliary class for providing output measurements of differential equations solver
		/// </summary>
		public class Variable
		{
			/// <summary>
			/// The solver
			/// </summary>
			DifferentialEquationSolver solver;

			/// <summary>
			/// Index of the variable 
			/// </summary>
			char indx;

			/// <summary>
			/// Constructor
			/// </summary>
			/// <param name="solver">The solver</param>
			/// <param name="indx">Index of the variable</param>
			public Variable(DifferentialEquationSolver solver, char indx)
			{
				this.solver = solver;
				this.indx = indx;
			}

			/// <summary>
			/// Calculates value of measurement
			/// </summary>
			/// <returns>Value of measurement</returns>
			public object calculate()
			{
				return solver.getValue(indx);
			}

			/// <summary>
			/// Calculates time derivation of measurement
			/// </summary>
			/// <returns>Time derivation</returns>
			public object derivation()
			{
				return solver.getDerivation(indx);
			}
		}

	}

	/// <summary>
	/// The state machine
	/// </summary>
	[Serializable()]
	public class StateMachine : DataConsumer, ISerializable,
		IPostSetArrow, IStarted, IMeasurements
	{
		/// <summary>
		/// Table of input parameters
		/// </summary>
		private Hashtable parameters = new Hashtable();

		/// <summary>
		/// Parameters
		/// </summary>
		private Hashtable pars;

		/// <summary>
		/// State transition table
		/// </summary>
		private int[,] table;

		/// <summary>
		/// Current state
		/// </summary>
		private int state;

		/// <summary>
		/// Initial state
		/// </summary>
		private int initialState;
		
		/// <summary>
		/// Table of parameters
		/// </summary>
		private Hashtable doubleParameters = new Hashtable();

		/// <summary>
		/// Output measurement
		/// </summary>
		private IMeasure measure;
		
		/// <summary>
		/// Constructor
		/// </summary>
		public StateMachine() : base(33)
		{
			pars = new Hashtable();
			init();
		}

		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="info">Serialization info</param>
		/// <param name="context">Streaming context</param>
		public StateMachine(SerializationInfo info, StreamingContext context) : 
			base(33)
		{
			table = (int[,])info.GetValue("Table", typeof(int[,]));
			pars = (Hashtable)info.GetValue("Parameters", typeof(Hashtable));
			initialState = (int)info.GetValue("Initial", typeof(int));
			init();
		}

		/// <summary>
		/// ISerializable interface implementation
		/// </summary>
		/// <param name="info">Serialization info</param>
		/// <param name="context">Streaming context</param>
		new public void GetObjectData(SerializationInfo info, StreamingContext context)
		{
			info.AddValue("Table", table);
			info.AddValue("Parameters", pars);
			info.AddValue("Initial", initialState);
		}

		/// <summary>
		/// Access to table
		/// </summary>
		public int this[int i, int j]
		{
			get
			{
				return table[i, j];
			}
		}

		/// <summary>
		/// The state
		/// </summary>
		public int State
		{
			get
			{
				return state;
			}
			set
			{
				state = value;
			}
		}

		/// <summary>
		/// The initial state
		/// </summary>
		public int InitialState
		{
			set
			{
				initialState = value;
			}
			get
			{
				return initialState;
			}
		}

		/// <summary>
		/// Gets state table dimension
		/// </summary>
		/// <param name="i">Numer of dimension</param>
		/// <returns></returns>
		public int GetLength(int i)
		{
			if (table == null)
			{
				return 0;
			}
			return table.GetLength(i);
		}

		/// <summary>
		/// The machine state transition table
		/// </summary>
		public int[,] Table
		{
			set
			{
				for (int i = 0; i < value.GetLength(0); i++)
				{
					for (int j = 0; j < value.GetLength(1); j++)
					{
						if (value[i, j] >= value.GetLength(0))
						{
							throw new Exception("State machine out of range");
						}
					}
				}
				doubleParameters.Clear();
				parameters.Clear();
				pars.Clear();
				table = value;
			}
		}

		/// <summary>
		/// The n th measurement
		/// </summary>
		new public IMeasure this[int n]
		{
			get
			{
				return parameters[n] as IMeasure;
			}
		}

		/// <summary>
		/// The count of measurements
		/// </summary>
		int IMeasurements.Count
		{
			get
			{
				return 1;
			}
		}

		/// <summary>
		/// Access to n - th measurement
		/// </summary>
		IMeasure IMeasurements.this[int n]
		{
			get
			{
				return measure;
			}
		}

		/// <summary>
		/// The keys of input parameters
		/// </summary>
		public ICollection Keys
		{
			get
			{
				return parameters.Keys;
			}
		}



		/// <summary>
		/// Creates correspond xml
		/// </summary>
		/// <param name="doc">document to create element</param>
		/// <returns>The created element</returns>
		/*new public XmlElement CreateXml(XmlDocument doc)
		{
			XmlElement el = doc.CreateElement("DifferentialEquationSolver");
			return el;
		}*/



		/// <summary>
		/// Updates measurements data
		/// </summary>
		public void UpdateMeasurements()
		{
			if (IsUpdated)
			{
				return;
			}
			try
			{
				UpdateChildrenData();
				foreach (int i in Keys)
				{
					double x = (double)doubleParameters[i];
					IMeasure m = this[i];
					double y = (double)m.Parameter();
					if ((y > 0) & (x <= 0))
					{
						state = table[state, i];
					}
					doubleParameters[i] = y;
				}
				isUpdated = true;
			}
			catch (Exception e)
			{
				PureDesktop.ThrowException(this, e);
			}
		}


		/// <summary>
		/// The operation that performs after arrows setting
		/// </summary>
		public void PostSetArrow()
		{
			postDeserialize();
			parameters.Clear();
			foreach (IMeasurements measurements in measurementsData)
			{
				/*IAssociatedObject cont = measurements as IAssociatedObject;
				INamedComponent c = cont.Object as INamedComponent;*/
				string name = DataConsumer.GetName(this, measurements);//c.Name;
				for (int i = 0; i < measurements.Count; i++)
				{
					IMeasure measure = measurements[i];
					string p = name + "." + measure.Name;
					foreach (int j in pars.Keys)
					{
						string s = pars[j] as string;
						if (s.Equals(p))
						{
							parameters[j] = measure;
						}
					}
				}
			}
		}

		/// <summary>
		/// The name of measurements source
		/// </summary>
		public string SourceName
		{
			get
			{
				INamedComponent comp = obj as INamedComponent;
				return comp.Name;
			}
		}
		
		/// <summary>
		/// Starts this object
		/// </summary>
		new public void Start()
		{
			try
			{
				foreach (int i in Keys)
				{
					double a = -1;
					doubleParameters[i] = a;
				}
				state = initialState;
			}
			catch (Exception e)
			{
				PureDesktop.ThrowException(this, e);
			}
		}

		/// <summary>
		/// Sets i - th input parameter
		/// </summary>
		/// <param name="i">The parameter number</param>
		/// <param name="name">The parameter name</param>
		/// <param name="m">The input measurement</param>
		public void SetParameter(int i, string name, IMeasure m)
		{
			parameters[i] = m;
			pars[i] = name + "." + m.Name;
		}

		/// <summary>
		/// Clears parameters
		/// </summary>
		public void ClearParameters()
		{
			parameters.Clear();
			pars.Clear();
			doubleParameters.Clear();
		}

		/// <summary>
		/// Gets name of i - th parameter
		/// </summary>
		/// <param name="i">The parameter number</param>
		/// <returns>The name of i - th parameter</returns>
		public string GetParameter(int i)
		{
			return pars[i] as string;
		}

		/// <summary>
		/// Operation after deserialization
		/// </summary>
		private void postDeserialize()
		{
			doubleParameters.Clear();
			parameters.Clear();
		}

		/// <summary>
		/// Gets state
		/// </summary>
		/// <returns></returns>
		private object getState()
		{
			return state;
		}

		/// <summary>
		/// Initialization
		/// </summary>
		private void init()
		{
			Int32 a = 0;
			measure = new Measure(a, new MeasureParameter(getState), "State");
		}

	}

	[Serializable()]
	public class Nulling : ICategoryObject, IMeasurements, ISerializable,
		IStarted
	{
		private double zero = 0;
		private double x;
		private double der;
		private bool switched = false;
		private IMeasure measure;
		private FormulaDataConsumer consumer;
		private StateMachine machine;
		private int state = 0;
		//private NamedComponent component;
		protected object obj;

		/// <summary>
		/// Update flag
		/// </summary>
		private bool isUpdated;


		public Nulling()
		{
			init();
		}

		public Nulling(SerializationInfo info, StreamingContext context) 
		{
			state = (int)info.GetValue("State", typeof(int));
			init();
		}

		/// <summary>
		/// ISerializable interface implementation
		/// </summary>
		/// <param name="info">Serialization info</param>
		/// <param name="context">Streaming context</param>
		public void GetObjectData(SerializationInfo info, StreamingContext context)
		{
			info.AddValue("State", state);
		}


		/// <summary>
		/// Creates correspond xml
		/// </summary>
		/// <param name="doc">document to create element</param>
		/// <returns>The created element</returns>
		/*public XmlElement CreateXml(XmlDocument doc)
		{
			XmlElement el = doc.CreateElement("Nulling");
			return el;
		}*/

		/// <summary>
		/// Associated object
		/// </summary>
		public object Object
		{
			get
			{
				return obj;
			}
			set
			{
				obj = value;
			}
		}


		/// <summary>
		/// Starts this object
		/// </summary>
		public void Start()
		{
			try
			{
				zero = 0;
				switched = false;
				if (consumer == null)
				{
					throw new Exception("Nulling has no consumer");
				}
				if (machine == null)
				{
					throw new Exception("Nulling has no machine");
				}
			}
			catch (Exception e)
			{
				PureDesktop.ThrowException(this, e);
			}
		}

		public int State
		{
			set
			{
				state = value;
			}
			get
			{
				return state;
			}
		}

		/// <summary>
		/// Updates measurements data
		/// </summary>
		public void UpdateMeasurements()
		{
			if (IsUpdated)
			{
				return;
			}
			try
			{
				consumer.UpdateMeasurements();
				IMeasurements m = consumer;
				IMeasure measure = m[0];
				x = (double)measure.Parameter();
                der = 0;
                if (measure is IDerivation)
                {
                    IDerivation d = measure as IDerivation;
                    der = d.Derivation;
                }
				machine.UpdateMeasurements();
				int s = machine.State;
				if (switched)
				{
					if (s != state)
					{
						switched = false;
					}
				}
				else
				{
					if (s == state)
					{
						zero = x;
						switched = true;
					}
				}
				isUpdated = true;
			}
			catch (Exception e)
			{
				PureDesktop.ThrowException(this, e);
			}
		}



		public void RemoveArrow(NullingArrow arrow)
		{
			object o = arrow.Target;
			if (o == machine)
			{
				machine = null;
				return;
			}
			if (o == consumer)
			{
				consumer = null;
			}
		}



		/// <summary>
		/// The name of measurements source
		/// </summary>
		public string SourceName
		{
			get
			{
				INamedComponent comp = obj as INamedComponent;
				return comp.Name;
			}
		}

		/// <summary>
		/// The category of this object
		/// </summary>
		public ICategory Category
		{
			get
			{
				return null;
			}
		}

		/// <summary>
		/// The identical arrow of this object
		/// </summary>
		public ICategoryArrow Id
		{
			get
			{
				return null;
			}
		}


		/// <summary>
		/// The n th measurement
		/// </summary>
		public IMeasure this[int n]
		{
			get
			{
				return measure;
			}
		}

		/// <summary>
		/// The count of measurements
		/// </summary>
		public int Count
		{
			get
			{
				return 1;
			}
		}


		public void SetMachine(StateMachine machine)
		{
			if (this.machine != null)
			{
				throw new Exception("Machine already exists");
			}
			this.machine = machine;
		}

		public void SetConsumer(FormulaDataConsumer consumer)
		{
			if (this.consumer != null)
			{
				throw new Exception("Consumer already exists");
			}
			this.consumer = consumer;
		}

		public int States
		{
			get
			{
				if (machine == null)
				{
					return 0;
				}
				return machine.GetLength(0);
			}
		}

		public StateMachine Machine
		{
			get
			{
				return machine;
			}
		}

		public FormulaDataConsumer Consumer
		{
			get
			{
				return consumer;
			}
		}


		private object getValue()
		{
			return x - zero;
		}
		private object getDerivation()
		{
			return der;
		}

		
		private void init()
		{
			Double a = 0;
			measure = new MeasureDerivation(a, new MeasureParameter(getValue), 
				new MeasureParameter(getDerivation), "Nulling");
		}

		/// <summary>
		/// Shows, wreather the object is updated
		/// </summary>
		public bool IsUpdated
		{
			get
			{
				return isUpdated;
			}
			set
			{
				isUpdated = value;
			}
		}

	}

	[Serializable()]
	public class NullingArrow : ICategoryArrow, IRemovableObject, ISerializable
	{
		public Nulling source;
		/// <summary>
		/// The target of this arrow
		/// </summary>
		public ICategoryObject target;
		/// <summary>
		/// Linked object
		/// </summary>
		protected object obj;
		int a = 0;
		public NullingArrow()
		{
		}

		public NullingArrow(SerializationInfo info, StreamingContext context) 
		{
			a = (int)info.GetValue("A", typeof(int));
		}

		/// <summary>
		/// ISerializable interface implementation
		/// </summary>
		/// <param name="info">Serialization info</param>
		/// <param name="context">Streaming context</param>
		public void GetObjectData(SerializationInfo info, StreamingContext context)
		{
			info.AddValue("A", a);
		}

		
		/// <summary>
		/// The source of this arrow
		/// </summary>
		public ICategoryObject Source
		{
			get
			{
				return source;
			}
			set
			{
				if (!(value is Nulling))
				{
					CategoryException.ThrowIllegalSourceException();
				}
				source = value as Nulling;
			}
		}

		/// <summary>
		/// The target of this arrow
		/// </summary>
		public ICategoryObject Target
		{
			get
			{
				return target;
			}
			set
			{
				if (value is StateMachine)
				{
					StateMachine machine = value as StateMachine;
					source.SetMachine(machine);
					return;
				}
				if (value is FormulaDataConsumer)
				{
					FormulaDataConsumer consumer = value as FormulaDataConsumer;
					source.SetConsumer(consumer);
					return;
				}
				CategoryException.ThrowIllegalTargetException();
			}
		}

		public bool IsMonomorphism
		{
			get
			{
				return false;
			}
		}

		public bool IsEpimorphism
		{
			get
			{
				return false;
			}
		}

		public bool IsIsomorphism
		{
			get
			{
				return false;
			}
		}


		/// <summary>
		/// Composes this arrow "f" with next arrow "g" 
		/// </summary>
		/// <param name="category"> The category of arrow</param>
		/// <param name="next"> The next arrow "g" </param>
		/// <returns>Composition "fg" </returns>
		public ICategoryArrow Compose(ICategory category, ICategoryArrow next)
		{
			return null;
		}

		/// <summary>
		/// Associated object
		/// </summary>
		public object Object
		{
			get
			{
				return obj;
			}
			set
			{
				obj = value;
			}
		}


		/// <summary>
		/// The post remove operation
		/// </summary>
		public void RemoveObject()
		{
			source.RemoveArrow(this);
		}

	}




	/// <summary>
	/// Multidimensional dynamical parameter
	/// </summary>
	public class DynamicalParameter
	{
		/// <summary>
		/// Strig of parameters labels
		/// </summary>
		private string labels = "";
		
		/// <summary>
		/// List of parameters
		/// </summary>
		private ArrayList parameters = new ArrayList();

		/// <summary>
		/// Error message of undefined parameter
		/// </summary>
		public static readonly string UndefinedParameter = "Undefined parameter";

		/// <summary>
		/// Error message of undefined parameters
		/// </summary>
		public static readonly string UndefinedParameters = "Undefined parameters";

		/// <summary>
		/// Constructor
		/// </summary>
		public DynamicalParameter()
		{
		}
		
		/// <summary>
		/// Adds measurement
		/// </summary>
		/// <param name="c">Measurement label</param>
		/// <param name="m">Measurement</param>
		public void Add(char c, IMeasure m)
		{
			if (labels.IndexOf(c) >= 0)
			{
				throw new Exception("Double parameter '" + c + "'");
			}
			labels += c;
			parameters.Add(m);
		}
		
		/// <summary>
		/// Checks whether formula argument contains all parameters
		/// </summary>
		/// <param name="arg"></param>
		/*public void Check(FormulaArgument arg)
		{
			arg.Check(labels);
		}*/

		/// <summary>
		/// Gets measurement
		/// </summary>
		public IMeasure this[char c]
		{
			get
			{
				int n = labels.IndexOf(c);
				if (n < 0)
				{
					throw new Exception(UndefinedParameter);
				}
				return parameters[n] as IMeasure;
			}
		}

		/// <summary>
		/// Sets formula argument
		/// </summary>
		/// <param name="arg"></param>
		public void Set(ElementaryObjectArgument arg)
		{
			foreach(char c in labels)
			{
				arg[c] = this[c].Parameter();
			}
		}
		
		/// <summary>
		/// String of parameter variables
		/// </summary>
		public string Variables
		{
			get
			{
				return labels;
			}
		}
	}


	/// <summary>
	/// Base class of data consumers
	/// </summary>
	[Serializable()]
	public class DataConsumer : IDataConsumer, ICategoryObject, 
		ISerializable
	{

		/// <summary>
		/// Desktop
		/// </summary>
		static private IDesktop desktop;

		/// <summary>
		/// Type of variable
		/// </summary>
		static private Double a = 0;

		/// <summary>
		/// Time
		/// </summary>
		//static private double time;


		/// <summary>
		/// Step
		/// </summary>
		static private int stepNumber;

		/// <summary>
		/// Desktop
		/// </summary>
		public static IDesktop Desktop
		{
			get
			{
				return desktop;
			}
			set
			{
				desktop = value;
			}
		}

		static IMeasure timeMeasure = new MeasureDerivation(a, new MeasureParameter(GetTime), new MeasureParameter(Unity), "Time");


        static public List<string> GetAllMeasurements(IDataConsumer consumer, object type)
        {
            List<string> list = new List<string>();
            for (int i = 0; i < consumer.Count; i++)
            {
                IMeasurements m = consumer[i];
                IAssociatedObject ao = m as IAssociatedObject;
                IAssociatedObject th = consumer as IAssociatedObject;
                string on = PureDesktop.GetRelativeName(th, ao) + ".";
                for (int j = 0; j < m.Count; j++)
                {
                    IMeasure mea = m[j];
                    string s = on + mea.Name;
                    if (type == null)
                    {
                        list.Add(s);
                        continue;
                    }
                    if (mea.Type.Equals(type))
                    {
                        list.Add(s);
                    }
                }
            }
            return list;
        }


        /// <summary>
        /// Gets measures type
        /// </summary>
        /// <param name="consumer">Consumer</param>
        /// <returns>Dictionary of types</returns>
        public static Dictionary<string, object> GetAllMeasuresType(IDataConsumer consumer)
        {
            Dictionary<string, object> dictionary = new Dictionary<string, object>();
            for (int i = 0; i < consumer.Count; i++)
            {
                IMeasurements m = consumer[i];
                IAssociatedObject ao = m as IAssociatedObject;
                IAssociatedObject th = consumer as IAssociatedObject;
                string on = PureDesktop.GetRelativeName(th, ao) + ".";
                for (int j = 0; j < m.Count; j++)
                {
                    IMeasure mea = m[j];
                    string s = on + mea.Name;
                    dictionary[s] = mea.Type;
                }
            }
            return dictionary;
        }


  
	/// <summary>
	/// The unity
	/// </summary>
	/// <returns>Unity</returns>
		static private object Unity()
		{
			return (double)1;
		}



			/// <summary>
			/// Measurement of time
			/// </summary>
		static public IMeasure TimeMeasure
		{
			get
			{
				return timeMeasure;
			}
		}

		/// <summary>
		/// Number of step
		/// </summary>
		static public int StepNumber
		{
			get
			{
				return stepNumber;
			}
			set
			{
				stepNumber = value;
			}
		}

		
		/// <summary>
		/// Gets time
		/// </summary>
		/// <returns>The time</returns>
		static private object GetTime()
		{
			return DataPerformerStrategy.Object.Time;
		}


		/// <summary>
		/// The time
		/// </summary>
/*		public static double Time
		{
			set
			{
				IDesktop desktop = Desktop;
				ICollection components = DataPerformerStrategy.Object.Components;
				time = value;
				foreach (INamedComponent comp in components)
				{
					IDynamical dynamical = null;
					if (comp is IObjectLabel)
					{
						IObjectLabel label = comp as IObjectLabel;
						ICategoryObject obj = label.Object;
						if (!(obj is IDynamical))
						{
							continue;
						}
						dynamical = obj as IDynamical;
					}
					else if (comp is IArrowLabel)
					{
						IArrowLabel label = comp as IArrowLabel;
						ICategoryArrow arr = label.Arrow;
						if (!(arr is IDynamical))
						{
							continue;
						}
						dynamical = arr as IDynamical;
					}
					dynamical.Time = value;
				}
				DataPerformerStrategy.Object.UpdateAll(desktop);
				DataConsumer.ResetUpdatedMeasurements(desktop);
			}
			get
			{
				return time;
			}
		}
*/


		
		/// <summary>
		/// Error message of variables shortage
		/// </summary>
		public static readonly string VariablesShortage = "Shortage of variables";
		
		/// <summary>
		/// Arrows to data providers
		/// </summary>
		protected List<IMeasurements> measurementsData;

		/// <summary>
		/// Type of consumer
		/// </summary>
		protected int type;

		/// <summary>
		/// Object factory
		/// </summary>
		//protected ElectromagneticUIFactory factory;

		/// <summary>
		/// Linked desktop component
		/// </summary>
		//protected NamedComponent control;

		/// <summary>
		/// Linked object
		/// </summary>
		protected object obj;

		/// <summary>
		/// Update flag
		/// </summary>
		protected bool isUpdated;

		/// <summary>
		/// Comments
		/// </summary>
		protected ArrayList comments = new ArrayList();


		/// <summary>
		/// Controls of graph
		/// </summary>
		private ArrayList graphControls = new ArrayList();

		/// <summary>
		/// Start
		/// </summary>
		private double start = 0;

		/// <summary>
		/// Step
		/// </summary>
		private double step = 1;

		/// <summary>
		/// Number of steps
		/// </summary>
		private int steps = 2;

		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="type">Type of consumer</param>
		public DataConsumer(int type)
		{
			this.type = type;
			initialize();
		}

		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="info">Serialization info</param>
		/// <param name="context">Streaming context</param>
		public DataConsumer(SerializationInfo info, StreamingContext context) 
		{
			type = (int)info.GetValue("Type", typeof(int));
			try
			{
				graphControls = (ArrayList)info.GetValue("GraphConrtols", typeof(ArrayList));
				start = (double)info.GetValue("Start", typeof(double));
				step =  (double)info.GetValue("Step", typeof(double));
				steps = (int)info.GetValue("Steps", typeof(int));
			}
			catch (Exception)
			{
			}
			initialize();
		}

		/// <summary>
		/// ISerializable interface implementation
		/// </summary>
		/// <param name="info">Serialization info</param>
		/// <param name="context">Streaming context</param>
		public void GetObjectData(SerializationInfo info, StreamingContext context)
		{
			info.AddValue("Type", type);
			info.AddValue("GraphConrtols", graphControls);
			info.AddValue("Start", start);
			info.AddValue("Step", step);
			info.AddValue("Steps", steps);
		}

		/// <summary>
		/// Creates correspond xml
		/// </summary>
		/// <param name="doc">document to create element</param>
		/// <returns>The created element</returns>
		/*public XmlElement CreateXml(XmlDocument doc)
		{
			XmlElement el = doc.CreateElement("DataConsumer");
			XmlAttribute attr = doc.CreateAttribute("Type");
			attr.Value = type + "";
			el.Attributes.Append(attr);
			if (ConsumerType == (int)ElectromagneticUI.ButtonKinds.GraphConsumer)
			{
				Form form = control.LabelForm;
				if (form != null)
				{
					IXmlElementCreator xml = form as IXmlElementCreator;
					XmlElement plotter = xml.CreateXml(doc);
					el.AppendChild(plotter);
				}
			}
			return el;
		}*/


        /// <summary>
        /// Gets all aliases of consumer and all its children
        /// </summary>
        /// <param name="consumer">The consumer</param>
        /// <param name="list">List of aliases</param>
        public static void GetAliases(IDataConsumer consumer, List<string> list)
        {
            getAliases(consumer, consumer, list);
        }


		/// <summary>
		/// Gets list children measurements of data consumer
		/// </summary>
		/// <param name="consumer">The consumer</param>
		/// <param name="measurements">Children measurements</param>
		public static void GetMeasurements(IDataConsumer consumer, ArrayList measurements)
		{
			if (consumer is IMeasurements)
			{
				if (!measurements.Contains(consumer))
				{
					measurements.Add(consumer);
				}
			}
			for (int i = 0; i < consumer.Count; i++)
			{
				object o = consumer[i];
				if (o is IDataConsumer)
				{
					IDataConsumer c = o as IDataConsumer;
					GetMeasurements(c, measurements);
				}
				else
				{
					if (!(measurements.Contains(o)))
					{
						measurements.Add(o);
					}
				}
			}
		}

		/// <summary>
		/// Resets updated measurements
		/// </summary>
		/// <param name="desktop">The desktop</param>
		public static void ResetUpdatedMeasurements(IDesktop desktop)
		{
			ICollection comp = DataPerformerStrategy.Object.Components;
			foreach (object o in comp)
			{
				if (!(o is IObjectLabel))
				{
					continue;
				}
				IObjectLabel l = o as IObjectLabel;
				object ob = l.Object;
				if (!(ob is IMeasurements))
				{
					continue;
				}
				IMeasurements m = ob as IMeasurements;
				m.IsUpdated = false;
			}
		}

		public static ArrayList GetDataConsumers(IDesktop desktop)
		{
			ArrayList list = new ArrayList();
			ICollection comp = desktop.AllComponents;
			foreach (object o in comp)
			{
				if (!(o is IObjectLabel))
				{
					continue;
				}
				IObjectLabel l = o as IObjectLabel;
				object ob = l.Object;
				if (!(ob is IDataConsumer))
				{
					continue;
				}
				list.Add(ob);
			}
			return list;
		}

		/// <summary>
		/// Aliases of this object and all its children
		/// </summary>
        public virtual List<string> AllAliases
        {
            get
            {
                List<string> a = new List<string>();
                DataConsumer.GetAliases(this, a);
                return a;
            }
        }

		/// <summary>
		/// Finds alias object
		/// </summary>
		/// <param name="c">Data consumer</param>
		/// <param name="alias">Full alias</param>
		/// <returns>Pair object[]{object, alias}</returns>
		public static object[] FindAlias(IDataConsumer consumer, string alias)
		{
			return findAlias(consumer, consumer, alias);
		}


		/// <summary>
		/// Gets relative name
		/// </summary>
		/// <param name="o">Base object</param>
		/// <param name="mea">Measurements</param>
		/// <returns>The name</returns>
		public static string GetName(IAssociatedObject o, IMeasurements mea)
		{
			IAssociatedObject ao = mea as IAssociatedObject;
			return PureDesktop.GetRelativeName(o, ao);
		}



		/// <summary>
		/// Controls of graph
		/// </summary>
		public ArrayList GraphControls
		{
			get
			{
				return graphControls;
			}
			set
			{
				graphControls = value;
			}
		}

		/// <summary>
		/// Adds target arrow
		/// </summary>
		/// <param name="arrow">Arrow to add</param>
		public void Add(IMeasurements arrow)
		{
			measurementsData.Add(arrow);
		}

		/// <summary>
		/// Removes target arrow
		/// </summary>
		/// <param name="arrow">Arrow to remove</param>
		public void Remove(IMeasurements arrow)
		{
			measurementsData.Remove(arrow);
		}



		/// <summary>
		/// Updates chidren measurements
		/// </summary>
		public void UpdateChildrenData()
		{
			try
			{
				foreach (IMeasurements m in measurementsData)
				{
					m.UpdateMeasurements();
				}
			}
			catch (Exception e)
			{
				PureDesktop.ThrowException(this, e);
			}
		}

		/// <summary>
		/// Resets measurements
		/// </summary>
		public void Reset()
		{
			Reset(this);
		}

		/// <summary>
		/// Resets data consumer
		/// </summary>
		/// <param name="consumer">The consumer</param>
		public static void Reset(IDataConsumer consumer)
		{
			if (consumer is IMeasurements)
			{
				IMeasurements mea = consumer as IMeasurements;
				mea.IsUpdated = false;
			}
			for (int i = 0; i < consumer.Count; i++)
			{
				IMeasurements m = consumer[i] as IMeasurements;
				m.IsUpdated = false;
				if (m is IDataConsumer)
				{
					IDataConsumer c = m as IDataConsumer;
					c.Reset();
				}
			}
		}

		/// <summary>
		/// Count of providers
		/// </summary>
		public int Count
		{
			get
			{
				return measurementsData.Count;
			}
		}

		/// <summary>
		/// Arrow of n th provider
		/// </summary>
		public IMeasurements this[int n]
		{
			get
			{
				return measurementsData[n];
			}
		}

		

		/// <summary>
		/// Gets aliases of this object and all its childen
		/// </summary>
		/// <param name="list"></param>
		//	public void GetAliases(ArrayList list)
		//	{
		//	}
		
		/// <summary>
		/// The category of this object
		/// </summary>
		public ICategory Category
		{
			get
			{
				return null;
			}
		}
		/// <summary>
		/// The identical arrow of this object
		/// </summary>
		public ICategoryArrow Id
		{
			get
			{
				return null;
			}
		}


		/// <summary>
		/// Type of consumer
		/// </summary>
		public int ConsumerType
		{
			get
			{
				return type;
			}
		}

		/// <summary>
		/// The UI factory of domain
		/// </summary>
		/*	public IUIFactory Facrory
			{
				get
				{
					return factory;
				}
				set
				{
					factory = value as ElectromagneticUIFactory;
				}
			}*/

		/// <summary>
		/// Associated object
		/// </summary>
		public object Object
		{
			get
			{
				return obj;
			}
			set
			{
				obj = value;
			}
		}

		/// <summary>
		/// Shows, wreather the object is updated
		/// </summary>
		public bool IsUpdated
		{
			get
			{
				return isUpdated;
			}
			set
			{
				isUpdated = value;
			}
		}

		/// <summary>
		/// Start
		/// </summary>
		public double Start
		{
			get
			{
				return start;
			}
			set
			{
				start = value;
			}
		}

		/// <summary>
		/// Step
		/// </summary>
		public double Step
		{
			get
			{
				return step;
			}
			set
			{
				step = value;
			}
		}

		/// <summary>
		/// Number of steps
		/// </summary>
		public int Steps
		{
			get
			{
				return steps;
			}
			set
			{
				steps = value;
			}
		}
		
		public static XmlDocument GetArraysXmlDocument(IDataConsumer consumer)
		{
			ArrayList meas = new ArrayList();
			int[] r = null;
			int n = consumer.Count;
			for (int i = 0; i < n; i++)
			{
				IMeasurements mea = consumer[i];
				int k = mea.Count;
				for (int j = 0; j < k; j++)
				{
					IMeasure m = mea[j];
					object type = m.Type;
					if (!(type is ArrayReturnType))
					{
						continue;
					}
                    ArrayReturnType art = type as ArrayReturnType;
					int[] rr = art.Dimension;
					if (rr.Length > 1)
					{
						continue;
					}
					if (r == null)
					{
						r = rr;
					}
					if (r[0] != rr[0])
					{
						continue;
					}
					meas.Add(m);
				}
			}
			if (r == null)
			{
				return null;
			}
			XmlDocument doc = new XmlDocument();
			doc.LoadXml("<?xml version=\"1.0\"?><ExperimentalData><Root></Root></ExperimentalData>");
			XmlElement root = doc.GetElementsByTagName("Root")[0] as XmlElement;
			XmlAttribute att = doc.CreateAttribute("uid");
			att.Value = Guid.NewGuid() + "";
			root.Attributes.Append(att);
			att = doc.CreateAttribute("time");
			att.Value = DateTime.Now + "";
			root.Attributes.Append(att);
			XmlElement descr = doc.CreateElement("ParametersDescription");
			root.AppendChild(descr);
			for (int i = 0; i < meas.Count; i++)
			{
				IMeasure m = meas[i] as IMeasure;
				XmlElement e = doc.CreateElement("ParameterDescription");
				descr.AppendChild(e);
				att = doc.CreateAttribute("id");
				att.Value = i + "";
				e.Attributes.Append(att);
				att = doc.CreateAttribute("name");
				att.Value = m.Name;
				e.Attributes.Append(att);
			}
			XmlElement results = doc.CreateElement("Results");
			root.AppendChild(results);
			for (int i = 0; i < r[0]; i++)
			{
				XmlElement result = doc.CreateElement("Result");
				results.AppendChild(result);
				for (int j = 0; j < meas.Count; j++)
				{
					IMeasure mea = meas[j] as IMeasure;
					XmlElement par = doc.CreateElement("Parameter");
					result.AppendChild(par);
					att = doc.CreateAttribute("id");
					att.Value = j + "";
					par.Attributes.Append(att);
					att = doc.CreateAttribute("value");
					object[] o = mea.Parameter() as object[];
					att.Value = o[i] + "";
					par.Attributes.Append(att);
				}
			}
			return doc;
		}

        private static void getAliases(IDataConsumer baseObject, IDataConsumer consumer, List<string> list)
        {
            IAssociatedObject ao = consumer as IAssociatedObject;
            PureObjectLabel.GetObjectAliases(ao, consumer, list);
            for (int i = 0; i < consumer.Count; i++)
            {
                object o = consumer[i];
                if (o is IDataConsumer)
                {
                    IDataConsumer c = o as IDataConsumer;
                    getAliases(consumer, c, list);
                }
                else
                {
                    PureObjectLabel.GetObjectAliases(ao, o, list);
                }
            }
        }



		/// <summary>
		/// Finds alias object
		/// </summary>
		/// <param name="c">Data consumer</param>
		/// <param name="alias">Full alias</param>
		/// <returns>Pair objec[]{object, alias}</returns>
		public static object[] findAlias(IDataConsumer baseObject, IDataConsumer consumer, string alias)
		{
			IAssociatedObject ao = baseObject as IAssociatedObject;
			INamedComponent nc = PureObjectLabel.PrefixComponent(ao, consumer, alias);
			if ((nc != null) & (consumer is IAlias))
			{
				return new object[]{consumer, PureObjectLabel.Suffix(alias)};
			}
			for (int i = 0; i < consumer.Count; i++)
			{
				object o = consumer[i];
				if (o is IDataConsumer)
				{
					IDataConsumer c = o as IDataConsumer;
					object[] r = findAlias(baseObject, c, alias);
					if (r != null)
					{
						return r;
					}
				}
				else
				{
					INamedComponent comp = PureObjectLabel.PrefixComponent(ao, o, alias);
					if ((comp != null) & (o is IAlias))
					{
						return new object[]{o, PureObjectLabel.Suffix(alias)};
					}
				}
			}
			return null;
		}

		/// <summary>
		/// Gets name of measure
		/// </summary>
		/// <param name="consumer">Data consumer</param>
		/// <param name="measure">Measure</param>
		/// <returns>The name</returns>
		public static string GetName(IDataConsumer consumer, IMeasure measure)
		{
			IAssociatedObject ass = consumer as IAssociatedObject;
			INamedComponent comp = ass.Object as INamedComponent;
			IDesktop d = comp.Desktop;
			for (int i = 0; i < consumer.Count; i++)
			{
				IMeasurements mea = consumer[i];
				for (int j = 0; j < mea.Count; j++)
				{
					IMeasure m = mea[j];
					if (m == measure)
					{
						IAssociatedObject ao = mea as IAssociatedObject;
						INamedComponent nc = ao.Object as INamedComponent;
						string name = PureObjectLabel.GetName(nc, d);
						return name + "." + m.Name;
					}
				}
			}
			return null;

		}

		/// <summary>
		/// Finds measure
		/// </summary>
		/// <param name="consumer">Data consumer</param>
		/// <param name="measure">Measure name</param>
		/// <returns>The measure</returns>
		public static IMeasure FindMeasure(IDataConsumer consumer, string measure)
		{
			int n = measure.LastIndexOf(".");
			string p = measure.Substring(0, n);
			string s = measure.Substring(n + 1);
			IAssociatedObject ass = consumer as IAssociatedObject;
			INamedComponent comp = ass.Object as INamedComponent;
			IDesktop d = comp.Desktop;
			for (int i = 0; i < consumer.Count; i++)
			{
				IMeasurements mea = consumer[i];
				IAssociatedObject ao = mea as IAssociatedObject;
				INamedComponent nc = ao.Object as INamedComponent;
				string name = PureObjectLabel.GetName(nc, d);
				if (!name.Equals(p))
				{
					continue;
				}
				for (int j = 0; j < mea.Count; j++)
				{
					IMeasure m = mea[j];
					if (s.Equals(m.Name))
					{
						return m;
					}
				}
			}
			return null;
		}



		/// <summary>
		/// Initialization
		/// </summary>
		private void initialize()
		{
			measurementsData = new List<IMeasurements>();
		}
	}


	[Serializable()]
	public class FourierSeriesLink : ICategoryArrow, ISerializable,
		IRemovableObject
	{

		/// <summary>
		/// The source of this arrow
		/// </summary>
		private FourierSeries source;

		/// <summary>
		/// The target of this arrow
		/// </summary>
		private Series target;
		
		/// <summary>
		/// Auxiliary field
		/// </summary>
		private int a = 0;
		
		/// <summary>
		/// Linked object
		/// </summary>
		protected object obj;

		
		/// <summary>
		/// Constuctor
		/// </summary>
		public FourierSeriesLink()
		{
		}
		
		/// <summary>
		/// Deserializetion contructor
		/// </summary>
		/// <param name="info">Serialization info</param>
		/// <param name="context">Streaming context</param>
		public FourierSeriesLink(SerializationInfo info, StreamingContext context)
		{
			a = (int)info.GetValue("A", typeof(int));
		}

		/// <summary>
		/// ISerializable interface implementation
		/// </summary>
		/// <param name="info">Serialization info</param>
		/// <param name="context">Streaming context</param>
		public void GetObjectData(SerializationInfo info, StreamingContext context)
		{
			info.AddValue("A", a);
		}

		/// <summary>
		/// Creates correspond xml
		/// </summary>
		/// <param name="doc">document to create element</param>
		/// <returns>The created element</returns>
		/*public XmlElement CreateXml(XmlDocument doc)
		{
			XmlElement el = doc.CreateElement("FourierSeriesLink");
			return el;
		}*/

		/// <summary>
		/// The source of this arrow
		/// </summary>
		public ICategoryObject Source
		{
			set
			{
				if (!(value is FourierSeries))
				{
					CategoryException.ThrowIllegalSourceException();
				}
				source = value as FourierSeries;
			}

			get
			{
				return source as ICategoryObject;
			}
		}
		

		/// <summary>
		/// The target of this arrow
		/// </summary>
		public ICategoryObject Target
		{
			get
			{
				return target as ICategoryObject;
			}
			set
			{
				if (!(value is Series))
				{
					CategoryException.ThrowIllegalTargetException();
				}
				target = value as Series;
				source.AddSeries(target);
			}
		}

		public bool IsMonomorphism
		{
			get
			{
				return false;
			}
		}

		public bool IsEpimorphism
		{
			get
			{
				return false;
			}
		}

		public bool IsIsomorphism
		{
			get
			{
				return false;
			}
		}


		/// <summary>
		/// Composes this arrow "f" with next arrow "g" 
		/// </summary>
		/// <param name="category"> The category of arrow</param>
		/// <param name="next"> The next arrow "g" </param>
		/// <returns>Composition "fg" </returns>
		public ICategoryArrow Compose(ICategory category, ICategoryArrow next)
		{                      
			return null;
		}

		/// <summary>
		/// Associated object
		/// </summary>
		public object Object
		{
			get
			{
				return obj;
			}
			set
			{
				obj = value;
			}
		}

		/// <summary>
		/// The post remove operation
		/// </summary>
		public void RemoveObject()
		{
			source.RemoveSeries(target);
		}
	}



	[Serializable()]
	public class SwitchLink : ICategoryArrow, ISerializable, IRemovableObject
	{
		private FormulaDataConsumer target;
		private ISwitched source;
		//private bool isUpdatable = false;
		/// <summary>
		/// Linked object
		/// </summary>
		protected object obj;
		int a;
		public SwitchLink()
		{
			a = 0;
		}
		public SwitchLink(SerializationInfo info, StreamingContext context)
		{
			a = (int)info.GetValue("A", typeof(int));
		}
		/// <summary>
		/// ISerializable interface implementation
		/// </summary>
		/// <param name="info">Serialization info</param>
		/// <param name="context">Streaming context</param>
		public void GetObjectData(SerializationInfo info, StreamingContext context)
		{
			info.AddValue("A", a);
		}

		/// <summary>
		/// Creates correspond xml
		/// </summary>
		/// <param name="doc">document to create element</param>
		/// <returns>The created element</returns>
		/*public XmlElement CreateXml(XmlDocument doc)
		{
			XmlElement el = doc.CreateElement("SwitchLink");
			return el;
		}*/



		/// <summary>
		/// Composes this arrow "f" with next arrow "g" 
		/// </summary>
		/// <param name="category"> The category of arrow</param>
		/// <param name="next"> The next arrow "g" </param>
		/// <returns>Composition "fg" </returns>
		public ICategoryArrow Compose(ICategory category, ICategoryArrow next)
		{
			return null;
		}
		
		/// <summary>
		/// The category of this object
		/// </summary>
		public ICategory Category
		{
			get
			{
				return null;
			}
		}

		/// <summary>
		/// Associated object
		/// </summary>
		public object Object
		{
			get
			{
				return obj;
			}
			set
			{
				obj = value;
			}
		}

		
		/// <summary>
		/// The post remove operation
		/// </summary>
		public void RemoveObject()
		{
			source.RemoveSwitch(this);
		}



		/// <summary>
		/// The source of this arrow
		/// </summary>
		public ICategoryObject Source
		{
			get
			{
				return source as ICategoryObject;
			}
			set
			{
				if (!(value is ISwitched))
				{
					CategoryException.ThrowIllegalSourceException();
				}
				source = value as ISwitched;
			}
		}
		
		/// <summary>
		/// The target of this arrow
		/// </summary>
		public ICategoryObject Target
		{
			get
			{
				return target;
			}
			set
			{
				if (source == null)
				{
					throw new Exception("Source object is missing");
				}
				if (source == value)
				{
					throw new Exception("Target of switch link should not concide with source");
				}
				if (!(value is FormulaDataConsumer))
				{
					CategoryException.ThrowIllegalTargetException();
				}
				target = value as FormulaDataConsumer;
				source.AddSwitch(this);
			}
		}

		public bool IsMonomorphism
		{
			get
			{
				return false;
			}
		}

		public bool IsEpimorphism
		{
			get
			{
				return false;
			}
		}

		public bool IsIsomorphism
		{
			get
			{
				return false;
			}
		}

	}

	[Serializable()]
	public class UnaryLink : ICategoryArrow, ISerializable, 
		IRemovableObject
	{
		private VectorFormulaConsumer source;
		
		private IObjectOperation target;

		/// <summary>
		/// Linked object
		/// </summary>
		protected object obj;
		
		int a;

		public UnaryLink()
		{
			a = 0;
		}

		public UnaryLink(SerializationInfo info, StreamingContext context)
		{
			a = (int)info.GetValue("A", typeof(int));
		}
		/// <summary>
		/// ISerializable interface implementation
		/// </summary>
		/// <param name="info">Serialization info</param>
		/// <param name="context">Streaming context</param>
		public void GetObjectData(SerializationInfo info, StreamingContext context)
		{
			info.AddValue("A", a);
		}

		/// <summary>
		/// Creates correspond xml
		/// </summary>
		/// <param name="doc">document to create element</param>
		/// <returns>The created element</returns>
		/*public XmlElement CreateXml(XmlDocument doc)
		{
			XmlElement el = doc.CreateElement("SeriesLink");
			return el;
		}*/



		/// <summary>
		/// Composes this arrow "f" with next arrow "g" 
		/// </summary>
		/// <param name="category"> The category of arrow</param>
		/// <param name="next"> The next arrow "g" </param>
		/// <returns>Composition "fg" </returns>
		public ICategoryArrow Compose(ICategory category, ICategoryArrow next)
		{
			return null;
		}
		
		/// <summary>
		/// The category of this object
		/// </summary>
		public ICategory Category
		{
			get
			{
				return null;
			}
		}

		/// <summary>
		/// Associated object
		/// </summary>
		public object Object
		{
			get
			{
				return obj;
			}
			set
			{
				obj = value;
			}
		}

		
		/// <summary>
		/// The post remove operation
		/// </summary>
		public void RemoveObject()
		{
			source.RemoveOperation(target);
		}



		/// <summary>
		/// The source of this arrow
		/// </summary>
		public ICategoryObject Source
		{
			get
			{
				return source;
			}
			set
			{
				if (!(value is VectorFormulaConsumer))
				{
					CategoryException.ThrowIllegalSourceException();
				}
				source = value as VectorFormulaConsumer;
			}
		}
		
		/// <summary>
		/// The target of this arrow
		/// </summary>
		public ICategoryObject Target
		{
			get
			{
				return target as ICategoryObject;
			}
			set
			{
				if (!(value is IObjectOperation))
				{
					CategoryException.ThrowIllegalTargetException();
				}
				target = value as IObjectOperation;
				source.AddOperation(target);
			}
		}

		public bool IsMonomorphism
		{
			get
			{
				return false;
			}
		}

		public bool IsEpimorphism
		{
			get
			{
				return false;
			}
		}

		public bool IsIsomorphism
		{
			get
			{
				return false;
			}
		}

	}



	[Serializable()]
	public class FormulaRegressionLink : ICategoryArrow, ISerializable, 
		IRemovableObject
	{
		/// <summary>
		/// The source
		/// </summary>
		private FormulaRegression source;

		/// <summary>
		/// The target
		/// </summary>
		private ICategoryObject target;

		/// <summary>
		/// Linked object
		/// </summary>
		protected object obj;
		int a;
		public FormulaRegressionLink()
		{
			a = 0;
		}
		public  FormulaRegressionLink(SerializationInfo info, StreamingContext context)
		{
			a = (int)info.GetValue("A", typeof(int));
		}
		/// <summary>
		/// ISerializable interface implementation
		/// </summary>
		/// <param name="info">Serialization info</param>
		/// <param name="context">Streaming context</param>
		public void GetObjectData(SerializationInfo info, StreamingContext context)
		{
			info.AddValue("A", a);
		}

		/// <summary>
		/// Creates correspond xml
		/// </summary>
		/// <param name="doc">document to create element</param>
		/// <returns>The created element</returns>
		/*public XmlElement CreateXml(XmlDocument doc)
		{
			XmlElement el = doc.CreateElement("FormulaRegressionLink");
			return el;
		}*/



		/// <summary>
		/// Composes this arrow "f" with next arrow "g" 
		/// </summary>
		/// <param name="category"> The category of arrow</param>
		/// <param name="next"> The next arrow "g" </param>
		/// <returns>Composition "fg" </returns>
		public ICategoryArrow Compose(ICategory category, ICategoryArrow next)
		{
			return null;
		}
		
		/// <summary>
		/// The category of this object
		/// </summary>
		public ICategory Category
		{
			get
			{
				return null;
			}
		}

		/// <summary>
		/// Associated object
		/// </summary>
		public object Object
		{
			get
			{
				return obj;
			}
			set
			{
				obj = value;
			}
		}


		/// <summary>
		/// The source of this arrow
		/// </summary>
		public ICategoryObject Source
		{
			get
			{
				return source;
			}
			set
			{
				if (!(value is FormulaRegression))
				{
					CategoryException.ThrowIllegalSourceException();
				}
				source = value as FormulaRegression;
			}
		}
		
		/// <summary>
		/// The target of this arrow
		/// </summary>
		public ICategoryObject Target
		{
			get
			{
				return target;
			}
			set
			{
				if (source == null)
				{
					throw new Exception("Source object is missing");
				}
				if (source == value)
				{
					throw new Exception("Target of switch link should not concide with source");
				}
				if (value is IArgumentSelection)
				{
					source.AddSelection(value as IArgumentSelection);
					target = value;
					return;
				}
				if (value is VectorFormulaConsumer)
				{
					source.Formula = value as VectorFormulaConsumer;
					target = value;
					return;
				}
				CategoryException.ThrowIllegalTargetException();
			}
		}

		public bool IsMonomorphism
		{
			get
			{
				return false;
			}
		}

		public bool IsEpimorphism
		{
			get
			{
				return false;
			}
		}

		public bool IsIsomorphism
		{
			get
			{
				return false;
			}
		}


		/// <summary>
		/// The post remove operation
		/// </summary>
		public void RemoveObject()
		{
			if (target is IArgumentSelection)
			{
				IArgumentSelection s = target as IArgumentSelection;
				source.RemoveSelection(s);
			}
		}


	}

	/// <summary>
	/// Selection with arguments
	/// </summary>
	public class ArgumentMultiSelection : IArgumentSelection
	{

		private ArrayList selections = new ArrayList();
		private ArrayList etalons = new ArrayList();
		//private int pointsCount;
		private int dim = 0;
		private string name = "";
		
		/// <summary>
		/// Count of points
		/// </summary>
		public int PointsCount
		{
			get
			{
				return first.PointsCount;		
			}
		}
		
		/// <summary>
		/// Free variables
		/// </summary>
		public string[] Variables
		{
			get
			{
				return first.Variables;
			}
		}
		/// <summary>
		/// Dimension of output vector
		/// </summary>
		public int VectorDimension
		{
			get
			{
				return dim;
			}
		}

		/// <summary>
		/// Gets value of variable
		/// </summary>
		public double this[int i, string str]
		{
			get
			{
				return first[i, str];
			}
		}

		/// <summary>
		/// Adds seletion
		/// </summary>
		/// <param name="sel">Selection to add</param>
		public void AddSelection(IArgumentSelection sel)
		{
			if (selections.Count == 0)
			{
				selections.Add(sel);
				etalons.Add(sel);
				dim += sel.VectorDimension;
				return;
			}
			string[] variables = first.Variables;
			string[] var = sel.Variables;
			if (var.Length != variables.Length)
			{
				throw new Exception("Illegal number of variables");
			}
			foreach (string s in var)
			{
				foreach (string s1 in variables)
				{
					if (s.Equals(s1))
					{
						goto m1;
					}
				}
				throw new Exception("Illegal variables");
			m1: continue;
			}
			dim += sel.VectorDimension;
			etalons.Add(sel);
			selections.Add(sel.SynchronizedSelection(selections[0] as IArgumentSelection));
		}

		/// <summary>
		/// Removes selection
		/// </summary>
		/// <param name="sel">Selection to remove</param>
		public void RemoveSelection(IArgumentSelection sel)
		{
			int n = etalons.IndexOf(sel);
			if (n >= 0)
			{
				etalons.RemoveAt(n);
				selections.RemoveAt(n);
				dim -= sel.VectorDimension;
			}
		}

		/// <summary>
		/// Component of i - th selection
		/// </summary>
		/// <param name="i">Selection number</param>
		/// <returns>The component</returns>
		public IObjectLabel GetComponent(int i)
		{
			ICategoryObject o = etalons[i] as ICategoryObject;
			return o.Object as IObjectLabel;
		}


		/// <summary>
		/// Dimension of data
		/// </summary>
		public int DataDimension
		{
			get
			{
				return PointsCount * VectorDimension;
			}
		}

		/// <summary>
		/// Access to n - th element
		/// </summary>
		public double? this[int n]
		{
			get
			{
				int m = n / dim;
				int k = n - dim * m;
				IArgumentSelection s = selections[k] as IArgumentSelection;
				return s[m];
			}
		}

		/// <summary>
		/// Weight of n - th element
		/// </summary>
		/// <param name="n">Element number</param>
		/// <returns>The weight</returns>
		public double GetWeight(int n)
		{
			return 1;
		}

		/// <summary>
		/// Aprior weight of n - th element
		/// </summary>
		/// <param name="n">Element number</param>
		/// <returns>The weight</returns>
		public double GetApriorWeight(int n)
		{
			return 0;
		}

		/// <summary>
		/// Tolerance of it - th element
		/// </summary>
		/// <param name="n">Element number</param>
		/// <returns>Tolerance</returns>
		public int GetTolerance(int n)
		{
			return 0;
		}

		/// <summary>
		/// Sets tolerance of n - th element
		/// </summary>
		/// <param name="n">Element number</param>
		/// <param name="tolerance">Tolerance to set</param>
		public void SetTolerance(int n, int tolerance)
		{
		}

		/// <summary>
		/// The "is fixed amount" sign
		/// </summary>
		public bool HasFixedAmount
		{
			get
			{
				foreach (IStructuredSelection s in selections)
				{
					if (!s.HasFixedAmount)
					{
						return false;
					}
				}
				return true;
			}
		}

		/// <summary>
		/// Selection name
		/// </summary>
		public string Name
		{
			get
			{
				return name;
			}
		}

		/// <summary>
		/// Calculates synchronized selection
		/// </summary>
		/// <param name="selection">The etalon selection</param>
		/// <returns>Synchronized selection</returns>
		public IArgumentSelection SynchronizedSelection(IArgumentSelection selection)
		{
			ArgumentMultiSelection sel = new ArgumentMultiSelection();
			for (int i = 0; i < selections.Count; i++)
			{
				IArgumentSelection s = selections[i] as IArgumentSelection;
				sel.AddSelection(s.SynchronizedSelection(selection));
			}
			return sel;
		}

		/// <summary>
		/// Gets i - th selection
		/// </summary>
		/// <param name="i">The selection nubmer</param>
		/// <returns>Choosen selection</returns>
		public IArgumentSelection GetSelection(int i)
		{
			return selections[i] as IArgumentSelection;
		}

		/// <summary>
		/// Count of selections
		/// </summary>
		public int SelectionCount
		{
			get
			{
				return selections.Count;
			}
		}

		/// <summary>
		/// First selection
		/// </summary>
		private IArgumentSelection first
		{
			get
			{
				if (selections.Count == 0)
				{
					return null;
				}
				return selections[0] as IArgumentSelection;
			}
		}

	}




	
	/// <summary>
	/// Switched object
	/// </summary>
	public interface ISwitched
	{
		/// <summary>
		/// Adds switch link
		/// </summary>
		/// <param name="link">Link to add</param>
		void AddSwitch(SwitchLink link);

		/// <summary>
		/// Removes switch link
		/// </summary>
		/// <param name="link">Link to remove</param>
		void RemoveSwitch(SwitchLink link);
	}


	/// <summary>
	/// ArrayCalculatorAccociated with formulas
	/// </summary>
	public class FormulaArrayCalculator
	{
		
		/// <summary>
		/// Number of calculator
		/// </summary>
		static private int staticNumber = 0;


		/// <summary>
		/// Global calculator
		/// </summary>
		//static public GlobalArrayCalculator GlobalCalculator = new  GlobalArrayCalculator(Calculate);

		
		/// <summary>
		/// Calculators
		/// </summary>
		static private Hashtable calculators = new Hashtable();
	
		/// <summary>
		/// Number of calculator
		/// </summary>
		private int number;
		
		/// <summary>
		/// Arguments
		/// </summary>
		private string[] arguments;

		/// <summary>
		/// Signal dimension
		/// </summary>
		private int dim;

		/// <summary>
		/// Formula consumer
		/// </summary>
		private VectorFormulaConsumer formulas;

		/// <summary>
		/// Diagram calculator
		/// </summary>
		private ArrayCalculator calculator;

		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="formulas">Formula consumer</param>
		public FormulaArrayCalculator(VectorFormulaConsumer formulas)
		{
			this.formulas = formulas;
			IMeasurements m = formulas;
			List<string> al = formulas.AliasNames;
			List<string> a = new List<string>();
            for (int i = 0; i < al.Count; i++)
            {
                a.Add(al[i]);
            }
			a.Sort();
			arguments = new string[al.Count];
			for (int i = 0; i < a.Count; i++)
			{
				arguments[i] = a[i] as string;
			}
			dim = formulas.Count;
			calculator = new ArrayCalculator(calculate);
			number = staticNumber;
			//AddCalculator(calculator);
		}


		/// <summary>
		/// Calculator
		/// </summary>
		/*public ArrayCalculator Calculator
		{
			get
			{
				return calculator;
			}
		}*/

		/// <summary>
		/// Destructor
		/// </summary>
		
		/*
		~FormulaArrayCalculator()
		{
			calculators[number] = null;
		}*/

		/// <summary>
		/// Calculates parameters of i - th calculator
		/// </summary>
		/// <param name="i">Calculator number</param>
		/// <param name="x">Input</param>
		/// <param name="data">Output</param>
/*		public static void Calculate(int i, int n, int m, double[] x, double [] data)
		{
			ArrayCalculator calc = calculators[i] as ArrayCalculator;
			calc(n, m, x, data);
		}*/


		/// <summary>
		/// Adds calculator
		/// </summary>
		/// <param name="calculator">Calculator to add</param>
		/*public static int AddCalculator(ArrayCalculator calculator)
		{
			calculators[staticNumber] = calculator;
			if (staticNumber == 0)
			{
				ArrayCalculatorWrapper.SetGlobalCalculator(GlobalCalculator);
			}
			staticNumber++;
			return staticNumber - 1;
		}*/

		/// <summary>
		/// Output dimension
		/// </summary>
		public int Dim
		{
			get
			{
				return dim;
			}
		}

		/// <summary>
		/// Formula calculator
		/// </summary>
		public ArrayCalculator Calculator
		{
			get
			{
				return calculator;
			}
		}

		/// <summary>
		/// Number of calculator
		/// </summary>
		public int Number
		{
			get
			{
				return number;
			}
		}

		/// <summary>
		/// Arguments of calculator
		/// </summary>
		public string[] Arguments
		{
			get
			{
				return arguments;
			}
		}


		/// <summary>
		/// Calculation
		/// </summary>
		/// <param name="x">Input</param>
		/// <param name="data">Output</param>
		private void calculate(int n, int m, double[] x, double [] data)
		{
			for (int i = 0; i < n; i++)
			{
				formulas[arguments[i]] = x[i];
			}
			IMeasurements mea = formulas;
			mea.UpdateMeasurements();
			for (int i = 0; i < m; i++)
			{
				data[i] = (double)mea[i].Parameter();
			}
		}
	}

	

	/// <summary>
	/// Vector formula data transformer
	/// </summary>
	[Serializable()]
	public class FourierSeries : DataConsumer, IMeasurements, ISerializable,
		IPostSetArrow, IAssociatedObject
	{
		/// <summary>
		/// Output measurements
		/// </summary>
		private IMeasure[] output = new IMeasure[2];

		/// <summary>
		/// Results of calculation
		/// </summary>
		private double[,] result = new double[2, 2];

		/// <summary>
		/// Arguments
		/// </summary>
		private string argument;

		/// <summary>
		/// Input measurements
		/// </summary>
		private IMeasure input;

		/// <summary>
		/// List of series
		/// </summary>
		private ArrayList seriesList = new ArrayList();

		/// <summary>
		/// Series
		/// </summary>
		private Series[] series = new Series[2];

		/// <summary>
		/// Names of unary
		/// </summary>
		private Hashtable seriesTable = new Hashtable();


		/// <summary>
		/// Constructor
		/// </summary>
		public FourierSeries() : base(65)
		{
			argument = "";
			for (int i = 0; i < 2; i++)
			{
				seriesTable[i] = "";
			}
			Double a = 0;
			output[0] = new MeasureDerivation(a, new MeasureParameter(getRe), new MeasureParameter(getReDerivation), "Real");
			output[1] = new MeasureDerivation(a, new MeasureParameter(getIm), new MeasureParameter(getImDerivation), "Image");
		}

		/// <summary>
		/// Constructor
		/// </summary>
		/// </summary>
		/// <param name="info">Serialization info</param>
		/// <param name="context">Streaming context</param>
		public FourierSeries(SerializationInfo info, StreamingContext context) : 
			base(65)
		{
			try
			{
				argument = (string)info.GetValue("Argument", typeof(string));
				seriesTable = info.GetValue("SeriesTable", typeof(Hashtable)) as Hashtable;
			}			
			catch (Exception)
			{
				seriesTable = new Hashtable();
				seriesTable[0] = "";
				seriesTable[1] = "";
			}
			if (seriesTable == null)
			{
			}
			Double a = 0;
			output[0] = new MeasureDerivation(a, new MeasureParameter(getRe), new MeasureParameter(getReDerivation), "Real");
			output[1] = new MeasureDerivation(a, new MeasureParameter(getIm), new MeasureParameter(getImDerivation), "Image");
		}

		/// <summary>
		/// ISerializable interface implementation
		/// </summary>
		/// <param name="info">Serialization info</param>
		/// <param name="context">Streaming context</param>
		new public void GetObjectData(SerializationInfo info, StreamingContext context)
		{
			info.AddValue("Argument", argument);
			info.AddValue("SeriesTable", seriesTable);
		}

		/// <summary>
		/// Creates correspond xml
		/// </summary>
		/// <param name="doc">document to create element</param>
		/// <returns>The created element</returns>
		/*new public XmlElement CreateXml(XmlDocument doc)
		{
			
			XmlElement el = doc.CreateElement("FourierSeries");
			return el;
		}*/

		/// <summary>
		/// Series table
		/// </summary>
		public Hashtable SeriesTable
		{
			get
			{
				return seriesTable;
			}
		}

		/// <summary>
		/// Table of series names
		/// </summary>
		/*	public Hashtable SeriesNames
			{
				get
				{
					return seriesNames;
				}
			}*/

		/// <summary>
		/// Adds series to list
		/// </summary>
		/// <param name="series">Series to remove</param>
		public void AddSeries(Series series)
		{
			if (seriesList.Count == 2)
			{
				throw new Exception("Too many series");
			}
			seriesList.Add(series);
		}


		/// <summary>
		/// Removes series
		/// </summary>
		/// <param name="series">Series to remove</param>
		public void RemoveSeries(Series series)
		{
			seriesList.Remove(series);
		}


		/// <summary>
		/// The count of measurements
		/// </summary>
		int IMeasurements.Count
		{
			get
			{
				return 2;
			}
		}

		/// <summary>
		/// Access to n - th measurement
		/// </summary>
		IMeasure IMeasurements.this[int n]
		{
			get
			{
				return output[n];
			}
		}

		/// <summary>
		/// Updates measurements data
		/// </summary>
		public void UpdateMeasurements()
		{
			if (IsUpdated)
			{
				return;
			}
			try
			{
				UpdateChildrenData();
				result[0, 0] = 0;
				result[1, 0] = 0;
				double x = (double)input.Parameter();
                IDerivation der = input as IDerivation;
				double d = (double)der.Derivation;
				for (int i = 0; i < series[0].Count; i++)
				{
					double om = series[0][i, 0];
					d *= om;
					double a = x * om;
					double s = Math.Sin(a);
					double c = Math.Cos(a);
					double re = series[0][i, 1] * c + series[1][i, 1] * s;
					double im = -series[0][i, 1] * s + series[1][i, 1] * c;
					result[0, 0] += re;
					result[1, 0] += im;
					result[0, 1] += d * im;
					result[1, 1] -= d * re;
				}
				isUpdated = true;
			}
			catch (Exception e)
			{
				PureDesktop.ThrowException(this, e);
			}
		}	

		/// <summary>
		/// The operation that performs after arrows setting
		/// </summary>
		public void PostSetArrow()
		{
			acceptArgument();
			AcceptSeries();
		}

		/// <summary>
		/// The name of measurements source
		/// </summary>
		public string SourceName
		{
			get
			{
				INamedComponent comp = obj as INamedComponent;
				return comp.Name;
			}
		}

		/// <summary>
		/// Argument
		/// </summary>
		public string Argument
		{
			get
			{
				return argument;
			}
			set
			{
				argument = value;
				acceptArgument();
			}
		}


		public DynamicalParameter Parameter
		{
			set
			{
				if (value.Variables.Length != 1)
				{
					throw new Exception("Fourier transform should have one parameter");
				}
				input = value['x'];
				argument = input.Name;
			}
		}

		/// <summary>
		/// Gets i - th unary
		/// </summary>
		/// <param name="i">Unary number</param>
		/// <returns>The i - th unary</returns>
		public IUnary GetUnary(int i)
		{
			return seriesList[i] as IUnary;
		}

		/// <summary>
		/// Count of unaries
		/// </summary>
		public int UnaryCount
		{
			get
			{
				return seriesList.Count;
			}
		}


		public void AcceptSeries()
		{
			if (seriesTable.Count != 2)
			{
				return;
			}
			for (int i = 0; i < 2; i++)
			{
				string sn = seriesTable[i] as string;
				foreach (Series s in seriesList)
				{
					//INamedComponent nc = s.Object as INamedComponent;
					if (sn.Equals(PureDesktop.GetRelativeName(this, s)))//nc.Name))
					{
						series[i] = s;
						continue;
					}
				}
			}
		}


		/// <summary>
		/// Accepts arguments
		/// </summary>
		private void acceptArgument()
		{
            foreach (IMeasurements measurements in measurementsData)
			{
				/*IAssociatedObject cont = measurements as IAssociatedObject;
				INamedComponent c = cont.Object as INamedComponent;*/
				string name = DataConsumer.GetName(this, measurements);//c.Name;
				for (int i = 0; i < measurements.Count; i++)
				{
					IMeasure measure = measurements[i];
					string p = name + "." + measure.Name;
					if (argument.Substring(4).Equals(p))
					{
						input = measure;
						break;
					}
				}
			}
			if (argument.Equals("Time"))
			{
				input = DataConsumer.TimeMeasure;
			}
		}







		/// <summary>
		/// Gets function value
		/// </summary>
		/// <returns>The value</returns>
		private object getRe()
		{
			return result[0, 0];
		}

		/// <summary>
		/// Gets function value
		/// </summary>
		/// <returns>The value</returns>
		private object getIm()
		{
			return result[1, 0];
		}

		/// <summary>
		/// Gets function derivation
		/// </summary>
		/// <returns>The derivation</returns>
		private object getReDerivation()
		{
			return result[0, 1];
		}

		/// <summary>
		/// Gets function derivation
		/// </summary>
		/// <returns>The derivation</returns>
		private object getImDerivation()
		{
			return result[1, 1];
		}
		
	}

	






	/// <summary>
	/// Processor for solving ordinary differential equations system 
	/// </summary>
	public abstract class DifferentialEquationProcessor
	{
		/// <summary>
		/// Processor
		/// </summary>
		static private DifferentialEquationProcessor processor;


		/// <summary>
		/// The is busy sign
		/// </summary>
		protected bool isBusy = false;
		
		/// <summary>
		/// Processor
		/// </summary>
		public static DifferentialEquationProcessor Object
		{
			get
			{
				return processor;
			}
			set
			{
				processor = value;
			}
		}
		
		
		/// <summary>
		/// Systems of equations
		/// </summary>
		protected ArrayList equations = new ArrayList();

		/// <summary>
		/// Children measurements
		/// </summary>
		protected ArrayList measurements = new ArrayList();

		/// <summary>
		/// Constructor
		/// </summary>
		protected DifferentialEquationProcessor()
		{
		}

		/// <summary>
		/// Sets root data consumers
		/// </summary>
		/// <param name="consumers">Consumers to set</param>
		public virtual void Set(ArrayList consumers)
		{
			equations.Clear();
			measurements.Clear();
			foreach (IDataConsumer c in consumers)
			{
				DataConsumer.GetMeasurements(c, measurements);
			}
			foreach (IMeasurements m in measurements)
			{
				if (m is IDifferentialEquationSolver)
				{
					equations.Add(m);
				}
			}
		}

		/// <summary>
		/// Count of equations system
		/// </summary>
		public int Count
		{
			get
			{
				return equations.Count;
			}
		}

		/// <summary>
		/// Access to i - th equations sistem
		/// </summary>
		public IDifferentialEquationSolver this[int i]
		{
			get
			{
				return equations[i] as IDifferentialEquationSolver;
			}
		}


		/// <summary>
		/// Resets "is updated" sign
		/// </summary>
		public void Reset()
		{
			foreach (IMeasurements m in measurements)
			{
				m.IsUpdated = false;
			}
		}

		/// <summary>
		/// Sets root data consumer
		/// </summary>
		/// <param name="consumer">The consumer to set</param>
		public void Set(IDataConsumer consumer)
		{
			ArrayList l = new ArrayList();
			l.Add(consumer);
			Set(l);
		}

		/// <summary>
		/// Dimension of state vector
		/// </summary>
		public int Dim
		{
			get
			{
				int n = 0;
				foreach (IMeasurements m in equations)
				{
					n += m.Count;
				}
				return n;
			}
		}

		public void UpdateMeasurements()
		{
			if (Dim > 0)
			{
				foreach (IMeasurements m in measurements)
				{
					m.UpdateMeasurements();
				}
			}
		}
		
		/// <summary>
		/// Performs step of integration
		/// </summary>
		/// <param name="t0">Step start</param>
		/// <param name="t2">Step finish</param>
		abstract public void Step(double t0, double t2);


		/// <summary>
		/// The "is busy" sign
		/// </summary>
		public bool IsBusy
		{
			get
			{
				return isBusy;
			}
		}

	}

	/// <summary>
	/// Runge processor for solving ordinary differential equations system 
	/// </summary>
	public class RungeProcessor : DifferentialEquationProcessor
	{
		/// <summary>
		/// Coefficients of method
		/// </summary>
		static readonly double[] a = {0.5, 0.5, 1.0, 1.0, 0.5};


		/// <summary>
		/// One divide by three
		/// </summary>
		//static readonly double one_to_three = 1.0 / 3.0;
 
		/// <summary>
		/// Auxiliary buffer variable
		/// </summary>
		private double[] z;
 
		/// <summary>
		/// Auxiliary buffer variable
		/// </summary>
		private double[] w;
 
		/// <summary>
		/// Auxiliary buffer variable
		/// </summary>
		private double[] f;

		/// <summary>
		/// Auxiliary buffer variable
		/// </summary>
		private double[,] k;


		/// <summary>
		/// Singleton
		/// </summary>
		static public readonly RungeProcessor Processor = new RungeProcessor(); 

		protected RungeProcessor()
		{
		}

		/// <summary>
		/// Performs step of integration
		/// </summary>
		/// <param name="t0">Step start</param>
		/// <param name="t2">Step finish</param>
		public override void Step(double t0, double t1)
		{
			isBusy = true;
			if (Dim == 0)
			{
				return;
			}
			double dt = t1 - t0;
			int i = 0;
			foreach (IMeasurements m in equations)
			{
				for (int j = 0; j < m.Count; j++)
				{
					w[i] = (double)m[j].Parameter();
					f[i] = w[i];
					++i;
				}
			}
			double t = t0;
			DataPerformerStrategy.Object.Time = t;
			UpdateMeasurements();
			Reset();
			i = 0;
			foreach (IMeasurements m in equations)
			{
				IDifferentialEquationSolver s = m as IDifferentialEquationSolver;

				s.CalculateDerivations();
				for (int j = 0; j < m.Count; j++)
				{
                    IDerivation der = m[j] as IDerivation;
					z[i] = der.Derivation;
					k[0, i] = z[i] * dt;
					w[i] = f[i] + 0.5 * k[0, i];
					++i;
				}
				s.SetVariables(i - m.Count, w);
			}
			t = t0 + 0.5 * dt;
			DataPerformerStrategy.Object.Time = t;
			UpdateMeasurements();
			Reset();
			i = 0;
			foreach (IMeasurements m in equations)
			{
				IDifferentialEquationSolver s = m as IDifferentialEquationSolver;
				s.CalculateDerivations();
				for (int j = 0; j < m.Count; j++)
				{
                    IDerivation der = m[j] as IDerivation;
					z[i] = der.Derivation;
					k[1, i] = z[i] * dt;
					w[i] = f[i] + 0.5 * k[1, i];
					++i;
				}
				s.SetVariables(i - m.Count, w);
			}
			t = t0 + 0.5 * dt;
			DataPerformerStrategy.Object.Time = t;
			UpdateMeasurements();
			Reset();
			i = 0;
			foreach (IMeasurements m in equations)
			{
				IDifferentialEquationSolver s = m as IDifferentialEquationSolver;
				s.CalculateDerivations();
				for (int j = 0; j < m.Count; j++)
				{
                    IDerivation der = m[j] as IDerivation;
					z[i] = der.Derivation;
					k[2, i] = z[i] * dt;
					w[i] = f[i] + k[2, i];
					++i;
				}
				s.SetVariables(i - m.Count, w);
			}
			t = t0 + dt;
			DataPerformerStrategy.Object.Time = t;
			UpdateMeasurements();
			Reset();
			i = 0;
			foreach (IMeasurements m in equations)
			{
				IDifferentialEquationSolver s = m as IDifferentialEquationSolver;
				s.CalculateDerivations();
				for (int j = 0; j < m.Count; j++)
				{
                    IDerivation der = m[j] as IDerivation;
					z[i] = der.Derivation;
					k[3, i] = z[i] * dt;
					++i;
				}
			}
			i = 0;
			foreach (IMeasurements m in equations)
			{
				IDifferentialEquationSolver s = m as IDifferentialEquationSolver;
				for (int j = 0; j < m.Count; j++)
				{
					f[i] += (k[0, i] + 2 * k[1, i] + 2 * k[2, i] + k[3, i]) / 6;
					++i;
				}
				s.SetVariables(i - m.Count, f);
			}
			isBusy = false;
		}

		/// <summary>
		/// Sets root data consumers
		/// </summary>
		/// <param name="consumers">Consumers to set</param>
		public override void Set(ArrayList consumers)
		{
			base.Set(consumers);
			int n = Dim;
			w = new double[n];
			z = new double[n];
			f = new double[n];
			k = new double[4, n];
		}
	}

	public class EulerProcessor: DifferentialEquationProcessor
	{
		/// <summary>
		/// Singleton
		/// </summary>
		static public readonly DifferentialEquationProcessor Processor = new EulerProcessor();

		/// <summary>
		/// Auxiliary variable
		/// </summary>
		private double[] w;

		/// <summary>
		/// Constructor
		/// </summary>
		private EulerProcessor()
		{
		}

		/// <summary>
		/// Performs step of integration
		/// </summary>
		/// <param name="t0">Step start</param>
		/// <param name="t2">Step finish</param>
		public override void Step(double t0, double t1)
		{
			isBusy = true;
			if (Dim == 0)
			{
				return;
			}
			double dt = t1 - t0;
			int i = 0;
			double t = t0;
			foreach (IMeasurements m in equations)
			{
				for (int j = 0; j < m.Count; j++)
				{
					w[i] = (double)m[j].Parameter();
					++i;
				}
			}
			DataPerformerStrategy.Object.Time = t;
			DataConsumer.ResetUpdatedMeasurements(DataConsumer.Desktop);
			UpdateMeasurements();
			i = 0;
			foreach (IMeasurements m in equations)
			{
				IDifferentialEquationSolver s = m as IDifferentialEquationSolver;
				s.CalculateDerivations();
				for (int j = 0; j < m.Count; j++)
				{
                    IDerivation der = m[j] as IDerivation;
					w[i] = w[i] + der.Derivation * dt;
					++i;
				}
				s.SetVariables(i - m.Count, w);
			}
			isBusy = false;
		}

		/// <summary>
		/// Sets root data consumers
		/// </summary>
		/// <param name="consumers">Consumers to set</param>
		public override void Set(ArrayList consumers)
		{
			base.Set(consumers);
			int n = Dim;
			w = new double[n];
		}
	}

		

	//Finished code!!! But it don't working right.
	public class AdamsProcessor: DifferentialEquationProcessor
	{

		/// <summary>
		/// Values of previous steps
		/// </summary>
		private double[,] prevDeri;

		/// <summary>
		/// Values of parameters in previous ptep
		/// </summary>
		private double[] prevStep;

		/// <summary>
		/// Values of old step
		/// </summary>
		private double[] oldStep;

		/// <summary>
		/// Counter of steps
		/// </summary>
		private int stepCount;

		/// <summary>
		/// Counter of parameters in equations
		/// </summary>
		private int paramCount;

		/// <summary>
		/// Additional Runge - Kutta processor
		/// </summary>
		private RungeProcessor runge = RungeProcessor.Processor;

		/// <summary>
		/// Singleton
		/// </summary>
		static public readonly AdamsProcessor Processor = new AdamsProcessor();
 
		/// <summary>
		/// The massive of coefficients
		/// </summary>
		private double[] prCoeff;

		/// <summary>
		/// Accurate coefficient
		/// </summary>
		private double[] aqCoeff;

		/// <summary>
		/// The order of precision
		/// </summary>
		private int order;

		protected AdamsProcessor()
		{
		}

		/// <summary>
		/// Order
		/// </summary>
		public int Order
		{
			set
			{
				order = value;
			}
		}

		public override void Set(ArrayList consumers)
		{
			base.Set(consumers);
			int n = Dim;
			stepCount = 0;
			prevStep = new double[n];
			oldStep = new Double[n];
			prevDeri = new double[n, order];
			prCoeff = new double[order];
			aqCoeff = new Double[order];
			RealPolynom pNom = new RealPolynom(1);
			RealPolynom mult = new RealPolynom(2);
			mult[0] = 0;
			mult[1] = 1;
			for (int i = 0; i < order; i++)
			{
				pNom = new RealPolynom(1);
				pNom[0] = 1;
				for (int j = 0; j < order; j++)
				{
					if (i != j)
					{
						mult[0] = j;
						pNom *= mult / (j - i);
					}
				}
				pNom = ~pNom;
				prCoeff[i] = pNom[(double)(1)];
				aqCoeff[i] = - pNom[(double)(-1)];
			}
			runge.Set(consumers);
		}
		
		public override void Step(double t0, double t1)
		{
			isBusy = true;
			paramCount = 0;
			if (stepCount < order)
			{
				runge.Step(t0, t1);
				foreach (IMeasurements m in equations)
				{
					runge.Step(t0, t1);
					IDifferentialEquationSolver s = m as IDifferentialEquationSolver;
					s.CalculateDerivations();
					for (int j = 0; j < m.Count; j++)
					{
                        IDerivation der = m[j] as IDerivation;
						prevDeri[paramCount, stepCount] = der.Derivation;
						prevStep[paramCount] = (double)m[j].Parameter();
						++paramCount;
					}
					s.SetVariables(paramCount - m.Count, prevStep);
					++stepCount;
				}
				paramCount = 0;
			}
			
			else
			{
				foreach (IMeasurements m in equations)
				{
					IDifferentialEquationSolver s = m as IDifferentialEquationSolver;
					s.CalculateDerivations();
					for (int j = 0; j < m.Count; j++)
					{
						prevStep[paramCount] = (double)m[j].Parameter();
						oldStep[paramCount] = prevStep[paramCount];
						for (int i = 0; i < order; i++)
						{
							prevStep[paramCount] +=  prevDeri[paramCount, i] * prCoeff[i] * (t1 - t0);
						}
						++paramCount;
					}
					s.SetVariables(paramCount - m.Count, prevStep);
				}
				
				paramCount = 0;
				foreach (IMeasurements m in equations)
				{
					for (int j = 0; j < m.Count; j++)
					{
						for (int i = 0; i < order - 1; i++)
						{
							prevDeri[paramCount, i] = prevDeri[paramCount, i + 1];
						}
						++paramCount;
					}
				}

				paramCount = 0;
				foreach (IMeasurements m in equations)
				{
					IDifferentialEquationSolver s = m as IDifferentialEquationSolver;
					s.CalculateDerivations();
					for(int j = 0; j < m.Count; j++)
					{
                        IDerivation der = m[j] as IDerivation;
						prevDeri[paramCount, order - 1] = der.Derivation;
						++paramCount;
					}
				}
				paramCount = 0;


				foreach (IMeasurements m in equations)
				{
					IDifferentialEquationSolver s = m as IDifferentialEquationSolver;
					for (int j = 0; j < m.Count; j++)
					{
						prevStep[paramCount] = oldStep[paramCount];
						for (int i = 0; i < order; i++)
						{
							prevStep[paramCount] += prevDeri[paramCount, i] * aqCoeff[i] * (t1 - t0);
						}
						++paramCount;
					}
					s.SetVariables(paramCount - m.Count, prevStep);
				}
				++stepCount;
			}
			isBusy = false;
		}
	}

	[Serializable()]
	public class TimeProvider : IDataConsumer, IMeasurements, ISerializable, ICategoryObject, IAlias,
		IPostSetArrow
	{
		
		/// <summary>
		/// The singleton
		/// </summary>
		public static readonly TimeProvider Singleton = new TimeProvider();
		
		private List<IMeasurements> measurementsData = new List<IMeasurements>();
		private string formulaString;
		private MathFormula formula;

		/// <summary>
		/// Trees
		/// </summary>
		private ObjectFormulaTree tree;

		/// <summary>
		/// Formula arguments
		/// </summary>
		private ElementaryObjectArgument arg;

		/// <summary>
		/// Input parameter
		/// </summary>
		private DynamicalParameter par;

		/// <summary>
		/// Input arguments
		/// </summary>
		private ArrayList arguments = new ArrayList();

		/// <summary>
		/// All variables
		/// </summary>
		private string allVariables;

		/// <summary>
		/// Parameters
		/// </summary>
		private Hashtable parameters = new Hashtable();

		/// <summary>
		/// Derivation trees
		/// </summary>
		//private Hashtable derivations;
		
		/// <summary>
		/// External unaries
		/// </summary>
		private ArrayList unary = new ArrayList();


		/// <summary>
		/// Names of unaries
		/// </summary>
		private Hashtable unaryNames = new Hashtable();

		/// <summary>
		/// The "is serialized" sign
		/// </summary>
		private bool isSerialized = false;

		
		/// <summary>
		/// Comments
		/// </summary>
		protected ArrayList comments = new ArrayList();

		private object obj;



		bool isActive = true;
		
		bool isUpdated;


		private TimeProvider()
		{
		}

		/// <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;
			}
		}


		#region ISerializable Members
		public TimeProvider(SerializationInfo info, StreamingContext context)
		{
			try
			{
				formulaString = (string)info.GetValue("Formulas", typeof(string));
				isSerialized = true;
				arguments = (ArrayList)info.GetValue("Arguments", typeof(ArrayList));
				parameters = (Hashtable)info.GetValue("Parameters", typeof(Hashtable));
				unaryNames = (Hashtable)info.GetValue("Unaries", typeof(Hashtable));
				comments = (ArrayList)info.GetValue("Comments", typeof(ArrayList));
			}
			catch (Exception)
			{
			}
		}

		public void GetObjectData(SerializationInfo info, StreamingContext context)
		{
			info.AddValue("Formulas", formulaString);
			info.AddValue("Arguments", arguments);
			info.AddValue("Parameters", parameters);
			info.AddValue("Unaries", unaryNames);
			info.AddValue("Comments", comments);
		}

		#endregion

		#region IDataConsumer Members

		public void Add(IMeasurements arrow)
		{
			measurementsData.Add(arrow);
		}

		public void Remove(IMeasurements arrow)
		{
			measurementsData.Remove(arrow);
		}

		public void UpdateChildrenData()
		{
			try
			{
				foreach (IMeasurements link in measurementsData)
				{
					link.UpdateMeasurements();
				}
			}
			catch (Exception e)
			{
				PureDesktop.ThrowException(this, e);
			}

		}

		public int Count
		{
			get
			{
				return measurementsData.Count;
			}
		}

		IMeasurements IDataConsumer.this[int n]
		{
			get
			{
				return measurementsData[n];
			}
		}

		public void Reset()
		{
			DataConsumer.Reset(this);
		}

		#endregion

		#region IMeasurements Members

		IMeasure IMeasurements.this[int n]
		{
			get
			{
				return DataConsumer.TimeMeasure;
			}
		}

		public void UpdateMeasurements()
		{
			if (!isActive)
			{
				return;
			}
			if (IsUpdated)
			{
				return;
			}
			try
			{
				if (par == null)
				{
					throw new Exception(DynamicalParameter.UndefinedParameters);
				}
				if (tree == null)
				{
					throw new Exception("Formula are not accepted");
				}
				UpdateChildrenData();
				par.Set(arg);
				DataPerformerStrategy.Object.Time = ElementaryIntegerOperation.ToDouble(tree.Result);
				isUpdated = true;
			}
			catch (Exception e)
			{
				PureDesktop.ThrowException(this, e);
			}

		}


		public string SourceName
		{
			get
			{
				return "Timer";
			}
		}

		public bool IsUpdated
		{
			get
			{
				return isUpdated;
			}
			set
			{
				isUpdated = value;
			}
		}

		#endregion

		public bool IsActive
		{
			get
			{
				return isActive;
			}
			set
			{
				isActive = value;
			}
		}




		#region ICategoryObject Members

		public ICategory Category
		{
			get
			{
				// TODO:  Add TimeProvider.Category getter implementation
				return null;
			}
		}

		public ICategoryArrow Id
		{
			get
			{
				// TODO:  Add TimeProvider.Id getter implementation
				return null;
			}
		}

		#endregion

		#region IAssociatedObject Members

		public object Object
		{
			get
			{
				return obj;
			}
			set
			{
				obj = value;
			}
		}

		#endregion

		#region IAlias Members

		public List<string> AliasNames
		{
			get
			{
				List<string> s = new List<string>();
				foreach (string str in parameters.Keys)
				{
					s.Add(str);
				}
				return s;
			}
		}

		object DiagramUI.IAlias.this[string alias]
		{
			get
			{
				return parameters[alias];
			}
			set
			{
				char c = alias[0];
				double a = (double)value;
				arg[c] = a;
				parameters[alias] = a;
				DataPerformerStrategy.Object.Time = ElementaryIntegerOperation.ToDouble(tree.Result);
			}
		}

        public object GetType(int n)
        {
            Double a = 0;
            return a;
        }


		#endregion


		/// <summary>
		/// The operation that performs after arrows setting
		/// </summary>
		public void PostSetArrow()
		{
			DynamicalParameter parameter = new DynamicalParameter();
            foreach (IMeasurements measurements in measurementsData)
			{
				IAssociatedObject cont = measurements as IAssociatedObject;
				INamedComponent nc = cont.Object as INamedComponent;
				string name = nc.Name;
				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);
						}
					}
				}
			}
			foreach (string s in arguments)
			{
				if (s.Substring(4).Equals("Time"))
				{
					parameter.Add(s[0], DataConsumer.TimeMeasure);
				}
			}
			Parameter = parameter;
			string argStr = AllVariables; 
			foreach (string key in parameters.Keys)
			{
				arg[key[0]] = parameters[key];
			}
			postSetUnary();
		}
		


		/// <summary>
		/// Comments
		/// </summary>
		public ArrayList Comments
		{
			get
			{
				return comments;
			}
			set
			{
				comments = value;
			}
		}

		/// <summary>
		/// String representation of formula
		/// </summary>
		public string Formula
		{
			get
			{
				return formulaString;
			}
			set
			{
				formulaString = value;
			}
		}

		/// <summary>
		/// Accepts formulas
		/// </summary>
		public void AcceptFormulas()
		{
			try
			{
				parameters.Clear();
				arguments.Clear();
				par = null;
				formula = MathFormula.FromString(MathSymbolFactory.Sizes, formulaString);
				allVariables = ElementaryObjectDetector.GetVariables(formula);
			}
			catch (Exception e)
			{
				PureDesktop.ThrowException(this, e);
			}
		}



		/// <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)
				{
				}
				return "";
			}
		}

		/// <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(VectorFormulaConsumer.VariablesShortage);
				m:
					b = b;
				}
				arguments = value;
			}
		}



		/// <summary>
		/// All formulas variables
		/// </summary>
		public string AllVariables
		{
			get
			{
				try
				{
					if (allVariables == null)
					{
						formula = MathFormula.FromString(MathSymbolFactory.Sizes, formulaString);
						allVariables = ElementaryObjectDetector.GetVariables(formula);
					}
					return allVariables;
				}
				catch (Exception)
				{
				}
				return "";
			}
		}

		
		/// <summary>
		/// Adds unary source
		/// </summary>
		/// <param name="u">The source to add</param>
		public void AddUnary(IUnary u)
		{
			unary.Add(u);
		}

		/// <summary>
		/// Count of external unaries
		/// </summary>
		public int UnaryCount
		{
			get
			{
				return unary.Count;
			}
		}

		/// <summary>
		/// Gets i - th external unary
		/// </summary>
		/// <param name="i">The index of unary</param>
		/// <returns>The i - th unary</returns>
		public IUnary GetUnary(int i)
		{
			return unary[i] as IUnary;
		}

		/// <summary>
		/// Table of unaries
		/// </summary>
		public Hashtable UnaryTable
		{
			set
			{
				setUnaryNames(value);
				setUnaryTrees(value);
			}
			get
			{
				if (tree != null)
				{
					return ElementaryUnaryOperation.GetUnaryTable(tree);
				}
				return new Hashtable();
			}
		}

		/// <summary>
		/// Names of external unatries
		/// </summary>
		public Hashtable UnaryNames
		{
			get
			{
				return unaryNames;
			}
		}

		

		/// <summary>
		/// Removes unary source
		/// </summary>
		/// <param name="u">The source to add</param>
		public void RemoveUnary(IUnary u)
		{
			unary.Remove(u);
		}

		/// <summary>
		/// List of outside unary functions
		/// </summary>
		public ArrayList UnaryList
		{
			get
			{
				return ElementaryUnaryOperation.GetUnaryIndexes(tree);
			}
		}

		/// <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>
		/// The input dynamical parameter
		/// </summary>
		public DynamicalParameter Parameter
		{
			set
			{
				par = value;
				if (!isSerialized)
				{
					arguments.Clear();
				}
				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;
				}
				foreach (char c in var)
				{
					IMeasure m = par[c];
					table[c] = m.Type;
				}
				IFormulaObjectCreator creator = new FormulaArrayObjectCreator(
					new ElementaryObjectsCreator(table));
				MathFormula f = formula.FullTransform;
				tree = new ObjectFormulaTree(f, creator);
				arg = new ElementaryObjectArgument();
				arg.Add(tree);
				string str = par.Variables;
				Hashtable unaryTable = ElementaryUnaryOperation.GetUnaryTable(tree);
			}
		}

		private void setUnaryNames(Hashtable table)
		{
			unaryNames.Clear();
			foreach (int i in table.Keys)
			{
				ICategoryObject o = table[i] as ICategoryObject;
				//IObjectLabel l = o.Object as IObjectLabel;
				unaryNames[i] = PureDesktop.GetRelativeName(this, o);//l.Name;
			}
		}

		private void setUnaryTrees(Hashtable table)
		{
			string str = Variables;
			ElementaryUnaryOperation.SetUnary(tree, table);
		}

		
		private void postSetUnary()
		{
			Hashtable t = new Hashtable();
			foreach (ICategoryObject o in unary)
			{
				//IObjectLabel l = o.Object as IObjectLabel;
				string name = PureDesktop.GetRelativeName(this, o);//l.Name;
				if (!unaryNames.ContainsValue(name))
				{
					continue;
				}
				foreach (int i in unaryNames.Keys)
				{
					if (name.Equals(unaryNames[i]))
					{
						t[i] = o;
						break;
					}
				}
			}
			setUnaryTrees(t);
		}

	}

	/// <summary>
	/// Solver of differential equations system
	/// </summary>
	public interface IDifferentialEquationSolver : IMeasurements
	{
		/// <summary>
		/// Calculates derivations
		/// </summary>
		void CalculateDerivations();

		/// <summary>
		/// Sets variables to array
		/// </summary>
		/// <param name="b">Offset</param>
		/// <param name="x">The array</param>
		void SetVariables(int b, double[] x);
	}

	/// <summary>
	/// The parametrized series
	/// </summary>
	public class ParametrizedSeries : Series
	{
		protected MeasureParameter x;
		protected MeasureParameter y;
		public ParametrizedSeries(MeasureParameter x, MeasureParameter y)
		{
			this.x = x;
			this.y = y;
		}
		public virtual void Step()
		{
			AddXY(ElementaryIntegerOperation.ToDouble(x()), ElementaryIntegerOperation.ToDouble(y()));
		}
	}


	public interface IDataPerformerStrategy
	{
		/// <summary>
		/// Updates all components
		/// </summary>
		/// <param name="d">Desktop</param>
		void UpdateAll(IDesktop d);

		/// <summary>
		/// Starts all components
		/// </summary>
		/// <param name="d">Desktop</param>
		void StartAll(IDesktop d);

		/// <summary>
		/// Preparation
		/// </summary>
		/// <param name="d">Desktop</param>
		void PrepareAll(IDesktop d);

		/// <summary>
		/// Clears all components
		/// </summary>
		void ClearAll();

		/// <summary>
		/// Time
		/// </summary>
		double Time
		{
			get;
			set;
		}
	}

	public class DataPerformerStrategy : IDataPerformerStrategy, IStep
	{

		protected ArrayList components = new ArrayList();
		protected ArrayList objects = new ArrayList();
		protected ArrayList arrows = new ArrayList();
		protected ArrayList updatable = new ArrayList();
		protected int step;
		protected ArrayList dynamical = new ArrayList();
		protected ArrayList measurements = new ArrayList();
		protected double time;
		static private DataPerformerStrategy strategy;


		public DataPerformerStrategy()
		{

		}

		#region IDataPerformerStrategy Members


		/// <summary>
		/// Updates all elements
		/// </summary>
		public virtual void UpdateAll(IDesktop d)
		{
			foreach (IUpdatableObject up in updatable)
			{
				up.UpdateObject();
			}
		}


		/// <summary>
		/// Starts all desktop elements
		/// </summary>
		public virtual void StartAll(IDesktop d)
		{
			ICollection components = d.AllComponents;
			foreach (INamedComponent c in components)
			{
				if (c is IObjectLabel)
				{
					IObjectLabel l = c as IObjectLabel;
					if (!(l.Object is IStarted))
					{
						continue;
					}
					IStarted s = l.Object as IStarted;
					s.Start();
					continue;
				}
				if (c is IArrowLabel)
				{
					IArrowLabel l = c as IArrowLabel;
					if (!(l.Arrow is IStarted))
					{
						continue;
					}
					IStarted s = l.Arrow as IStarted;
					s.Start();
					continue;
				}
			}

		}

		public virtual void PrepareAll(IDesktop d)
		{
			ClearAll();
			prepareAll(d);
			updatable.Clear();
			foreach (INamedComponent c in components)
			{
				object o = null;
				if (c is IObjectLabel)
				{
					IObjectLabel l = c as IObjectLabel;
					o = l.Object;
				}
				else if (c is IArrowLabel)
				{
					IArrowLabel l = c as IArrowLabel;
					o = l.Arrow;
				}
				if (o == null)
				{
					continue;
				}
				if (o is IDynamical)
				{
					continue;
				}
				if (!(o is IUpdatableObject))
				{
					continue;
				}
				IUpdatableObject up = o as IUpdatableObject;
				if (up.ShouldUpdate)
				{
					updatable.Add(up);
				}
			}
			foreach (INamedComponent comp in components)
			{
				IDynamical dyn = null;
				if (comp is IObjectLabel)
				{
					IObjectLabel label = comp as IObjectLabel;
					ICategoryObject obj = label.Object;
					if (!(obj is IDynamical))
					{
						continue;
					}
					dyn = obj as IDynamical;
				}
				else if (comp is IArrowLabel)
				{
					IArrowLabel label = comp as IArrowLabel;
					ICategoryArrow arr = label.Arrow;
					if (!(arr is IDynamical))
					{
						continue;
					}
					dyn = arr as IDynamical;
				}
				dynamical.Add(dyn);
			}
			foreach (INamedComponent comp in components)
			{
				if (!(comp is IObjectLabel))
				{
					continue;
				}
				IObjectLabel l = comp as IObjectLabel;
				object ob = l.Object;
				if (!(ob is IMeasurements))
				{
					continue;
				}
				IMeasurements m = ob as IMeasurements;
				measurements.Add(m);
			}
		}


		/// <summary>
		/// Clears all components
		/// </summary>
		public void ClearAll()
		{
			if (components != null)
			{
				components.Clear();
			}
			if (objects != null)
			{
				objects.Clear();
			}
			if (arrows != null)
			{
				arrows.Clear();
			}
			updatable.Clear();
			dynamical.Clear();
			measurements.Clear();
			GC.Collect();
		}

		public double Time
		{
			get
			{
				return time;
			}
			set
			{
				time = value;
				foreach (IDynamical dyn in dynamical)
				{
					dyn.Time = value;
				}
				UpdateAll(null);
				ResetUpdatedMeasurements();
			}
		}



		#endregion


		#region IStep Members

		public int Step
		{
			get
			{
				return step;
			}
			set
			{
				step = value;
				foreach (object c in components)
				{
					object o = null;
					if (c is IObjectLabel)
					{
						IObjectLabel l = c as IObjectLabel;
						o = l.Object;

					}
					if (c is IArrowLabel)
					{
						IArrowLabel l = c as IArrowLabel;
						o = l.Arrow;
					}
					if (!(o is IStep))
					{
						continue;
					}
					IStep s = o as IStep;
					s.Step = value;
				}
			}
		}

		public void ResetUpdatedMeasurements()
		{
			foreach (IMeasurements m in measurements)
			{
				m.IsUpdated = false;
			}
		}

		#endregion

		#region Specific Members

		
		public static DataPerformerStrategy Object
		{
			get
			{
				return strategy;
			}
			set
			{
				strategy = value;
			}
		}

	

		
		public ICollection Components
		{
			get
			{
				return components;
			}
		}

		private void prepareAll(IDesktop d)
		{
			ICollection comps = d.Components;
			foreach (INamedComponent c in comps)
			{
				components.Add(c);
				if (c is IArrowLabel)
				{
					arrows.Add(c);
					continue;
				}
				if (!(c is IObjectLabel))
				{
					continue;
				}
				objects.Add(c);
				IObjectLabel l = c as IObjectLabel;
				if (l.Object is ObjectContainer)
				{
					ObjectContainer cont = l.Object as ObjectContainer;
					prepareAll(cont.Desktop);
				}
			}
		}


		#endregion

	}



	public class ArraySelectionCollection : IStructuredSelectionCollection, IMeasurements
	{
		#region Fields

		private ArraySelection[] selections;

		#endregion

		#region Constructors

		protected ArraySelectionCollection()
		{
		}

		#endregion

		#region IStructuredSelectionCollection Members

		int IStructuredSelectionCollection.Count
		{
			get
			{
				return selections.Length;
			}
		}

		IStructuredSelection IStructuredSelectionCollection.this[int i]
		{
			get
			{
				return selections[i];
			}
		}

		#endregion

		#region IMeasurements Members

		int IMeasurements.Count
		{
			get
			{
				return selections.Length;
			}
		}



		IMeasure IMeasurements.this[int n]
		{
			get
			{
				return selections[n];
			}
		}

		public void UpdateMeasurements()
		{
		}

		public string SourceName
		{
			get
			{
				return "";
			}
		}

		public bool IsUpdated
		{
			get
			{
				return true;
			}
			set
			{
			}
		}

		#endregion

		#region Specific Members

		protected void Set(string[] names, double[][] data)
		{
			if (names.Length != data.Length)
			{
				throw new Exception("Names length does not coincides with data length");
			}
			selections = new ArraySelection[names.Length];
			for (int i = 0; i < selections.Length; i++)
			{
				selections[i] = new ArraySelection(names[i], data[i]);
			}
		}

		#endregion
	}

	/// <summary>
	/// Scale selector
	/// </summary>
	public interface IScaleSelector
	{
		/// <summary>
		/// Selects scale
		/// </summary>
		/// <param name="scale">Scale</param>
		/// <returns>Selected scale</returns>
		double SelectScale(double scale);
	}


	/// <summary>
	/// Power scale selector
	/// </summary>
	public class PowerScaleSelector : IScaleSelector
	{
		
		#region Fields

		double begin;

		double pow;

		double[] scales;

		#endregion

		#region Constructors

		public PowerScaleSelector(double begin, double pow, double[] scales)
		{
			this.begin = begin;
			this.pow = pow;
			this.scales = scales;
		}

		#endregion
		
		
		#region IScaleSelector Members

		public double SelectScale(double scale)
		{
			double log = Math.Floor(Math.Log(scale / (begin * scales[0])) / Math.Log(pow));
			double b = begin * Math.Exp(log * Math.Log(pow));
			for (int i = 0; i < scales.Length; i++)
			{
				if (b * scales[i] > scale)
				{
					return b * scales[i];
				}
			}
			return 1;
		}

		#endregion
	}

	/// <summary>
	/// Histogram
	/// </summary>
	public class Histogram
	{

		/// <summary>
		/// Gets histogram
		/// </summary>
		/// <param name="selection">Selection</param>
		/// <param name="scaleSelector">Scale selector</param>
		/// <param name="prefferedSize">Preffered size</param>
		/// <returns>The histogram</returns>
		public static double[,] GetHistogram(double[] selection, IScaleSelector scaleSelector, int prefferedSize)
		{
			ArrayList l = new ArrayList(selection);
			l.Sort();
			double min = (double) l[0];
			double max = (double) l[selection.Length - 1];
			double a = (max - min) / (prefferedSize + 1);
			double scale = a;
			if (scaleSelector != null)
			{
				scale = scaleSelector.SelectScale(a);
			}
			int nmin = (int) (Math.Floor(min) / scale);
			int nmax = (int) (Math.Ceiling(max) / scale);
			int diapCount = nmax - nmin;
			double[,] data = new double[diapCount, 2];
			double current = (double) (nmin * scale);
			int nSel = 0;
			for (int i = 0; i < diapCount; i++)
			{
				data[i, 0] = current;
				data[i, 1] = 0;
				if (nSel < l.Count)
				{
					while (true)
					{
						double x = (double) l[nSel];
						if (x > (current + scale))
						{
							break;
						}
						++data[i, 1];
						++nSel;
						if (nSel >= l.Count)
						{
							break;
						}
					}
				}
				current += scale;
			}
			return data;
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Architect
Russian Federation Russian Federation
Ph. D. Petr Ivankov worked as scientific researcher at Russian Mission Control Centre since 1978 up to 2000. Now he is engaged by Aviation training simulators http://dinamika-avia.com/ . His additional interests are:

1) Noncommutative geometry

http://front.math.ucdavis.edu/author/P.Ivankov

2) Literary work (Russian only)

http://zhurnal.lib.ru/editors/3/3d_m/

3) Scientific articles
http://arxiv.org/find/all/1/au:+Ivankov_Petr/0/1/0/all/0/1

Comments and Discussions