Click here to Skip to main content
15,891,868 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
{
	[Serializable()]
	public class Series : ISerializable, ICategoryObject, 
		IArgumentSelection, IMeasure, IMeasurements, IStructuredSelectionCollection,
		IUnary, IObjectOperation, IOperationAcceptor, IComments
	{
		
		#region Fields

		private static readonly Double a = 0;
		private readonly string[] var = {"x"};
		private readonly double eps = 1e-9;
		static public readonly string[] HasEqualStepString = new string[] {"This series has equal steps",
																			  "This series has no equal steps"};
		protected List<double[]> points = new List<double[]>();
		protected string x = "";
		protected string y = "";
		public double[] parameter = new double[2];
		private object obj;
		private double step = 0;
		protected int[] pointStart = new int[2];
		protected int[] pointFinish = new int[2];
		private ArrayList comments = new ArrayList();
		private object type = new object[] {a, a};
		private object[] meaX = new object[2];
		private object[] meaY = new object[2];
		private DataPerformer.MeasureParameter[] measureParameter = new MeasureParameter[2];
		private IMeasure measureY;
		private IStructuredSelection[] selections;

		#endregion

		#region Constructors

		public Series()
		{
			initialize();
			selections = new IStructuredSelection[]{new XSelection(this), this};
		}

		/// <summary>
		/// Deserialization constructor
		/// </summary>
		/// <param name="info">Serialization info</param>
		/// <param name="context">Streaming context</param>
		protected Series(SerializationInfo info, StreamingContext context)
		{
            try
            {
                points = info.GetValue("Points", typeof(List<double[]>)) as List<double[]>;
            }
            catch (Exception)
            {
                ArrayList p = info.GetValue("Points", typeof(ArrayList)) as ArrayList;
                for (int i = 0; i < p.Count; i++)
                {
                    double[] d = p[i] as double[];
                    points.Add(d);
                }
            }
            try
            {
                comments = (ArrayList)info.GetValue("Comments", typeof(ArrayList));
            }
            catch (Exception)
            {
            }

            Post();
		}

		#endregion

		#region ISerializable Members

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

		#endregion

		#region IStructuredSelectionCollection Members

		int IStructuredSelectionCollection.Count
		{
			get
			{
				return 2;
			}
		}

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

		#endregion

		#region IMeasurements Members

		IMeasure DataPerformer.IMeasurements.this[int n]
		{
			get
			{
				if (n == 0)
				{
					return this;
				}
				return measureY;
			}
		}

		public void UpdateMeasurements()
		{
		}

		public string SourceName
		{
			get
			{
				IObjectLabel l = obj as IObjectLabel;
				return l.Name;
			}
		}

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

		int IMeasurements.Count
		{
			get
			{
				return 2;
			}
		}


		#endregion

		#region IMeasure Members

		public DataPerformer.MeasureParameter Parameter
		{
			get
			{
				return measureParameter[0];
			}
		}

		public DataPerformer.MeasureParameter Derivation
		{
			get
			{
				return null;
			}
		}

		public string Name
		{
			get
			{
				return "X";
			}
		}



		public double Factor
		{
			get
			{
				return 1;
			}
		}

		public object Type
		{
			get
			{
				initMea();
				return type;
			}
		}

		#endregion

		#region IXmlCreator Members
		
		/// <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("Plot");
			XmlAttribute nx = doc.CreateAttribute("X");
			nx.Value = X;
			el.Attributes.Append(nx);
			XmlAttribute ny = doc.CreateAttribute("Y");
			ny.Value = Y;
			el.Attributes.Append(ny);
			foreach(double[] p in points)
			{
				XmlElement ep = doc.CreateElement("PlotPoint");
				XmlAttribute ax = doc.CreateAttribute("PlotX");
				ax.Value = "" + p[0];
				ep.Attributes.Append(ax);
				XmlAttribute ay = doc.CreateAttribute("PlotY");
				ay.Value = "" + p[1];
				ep.Attributes.Append(ay);
				el.AppendChild(ep);
			}
			return el;
		}

		#endregion

		#region ICategoryObject members
		/// <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;
			}
		}

		#endregion

		#region IAssociatedObject members

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

		#endregion

		#region IObjectOperation Members

		object IObjectOperation.this[object[] x]
		{
			get
			{
				double a = (double) x[0];
				return GetValue(a);
			}
		}

		public object ReturnType
		{
			get
			{
				return a;
			}
		}

		public int Arity
		{
			get
			{
				return 1;
			}
		}

		public bool IsPowered
		{
			get
			{
				return true;
			}
		}

		#endregion

		#region IOperationAcceptor Members

		public IObjectOperation Accept(object type)
		{
			if (type.Equals(a))
			{
				return this;
			}
			return null;
		}

		#endregion

		#region IUnary Members

		/// <summary>
		/// Gets value of function
		/// </summary>
		/// <param name="x">Argument</param>
		/// <returns></returns>
		public double GetValue(double x)
		{
			return this[x][0];
		}

		/// <summary>
		/// Gets derivation of function
		/// </summary>
		/// <param name="x">Argument</param>
		/// <returns></returns>
		public double GetDerivation(double x)
		{
			return this[x][1];
		}

		#endregion


        public List<double[]> Points
        {
            get { return points; }
        }


        protected void Post()
        {
            measureParameter[0] = new DataPerformer.MeasureParameter(parX);
            measureParameter[1] = new DataPerformer.MeasureParameter(parY);
            measureY = YMeasure.getMeasure(this);
            selections = new IStructuredSelection[] { new XSelection(this), this };
            checkEqualStep();

        }


		/// <summary>
		/// Calculates synchronized selection
		/// </summary>
		/// <param name="selection">The etalon selection</param>
		/// <returns>Synchronized selection</returns>
		public IArgumentSelection SynchronizedSelection(IArgumentSelection selection)
		{
			if (!(selection is Series))
			{
				throw new Exception("Incompatible selections");
			}
			Series etalon = selection as Series;
			Series s = new Series();
			for (int i = 0; i < etalon.PointsCount; i++)
			{
				double x = etalon[i, 0];
				double a = this[0, 0];
				if (x < a)
				{
					s.AddXY(x, this[0, 1]);
					continue;
				}
				double b = this[PointsCount - 1, 0];
				if (x > b)
				{
					s.AddXY(x, this[PointsCount - 1, 1]);
					continue;
				}
				s.AddXY(x, this[x][1]);
			}
			return s;
		}

		public string HasEqualSteps
		{
			get
			{
				if (step == 0)
				{
					return PureDesktop.GetResourceString(HasEqualStepString[1]);
				}
				return PureDesktop.GetResourceString(HasEqualStepString[0]);
			}
		}


		#region IStructuredSelection Members

		/// <summary>
		/// Dimension of data
		/// </summary>
		public int DataDimension
		{
			get
			{
				return points.Count;
			}
		}

		/// <summary>
		/// Access to n - th element
		/// </summary>
		double? IStructuredSelection.this[int n]
		{
			get
			{
				return this[n, 1];
			}
		}

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

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

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

		string IStructuredSelection.Name
		{
			get
			{
				return "Y";
			}
		}



		/// <summary>
		/// Count of points
		/// </summary>
		public int PointsCount
		{
			get
			{
				return points.Count;
			}
		}
		
		/// <summary>
		/// Free variables
		/// </summary>
		public string[] Variables
		{
			get
			{
				return var;
			}
		}
		/// <summary>
		/// Dimension of output vector
		/// </summary>
		public int VectorDimension
		{
			get
			{
				return 1;
			}
		}

		#endregion


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

		#region Specific Members

		/// <summary>
		/// Copies from another series
		/// </summary>
		/// <param name="s">Pattern series</param>
		public void CopyFrom(Series s)
		{
			points.Clear();
			for (int i = 0; i < s.Count; i++)
			{
				AddXY(s[i, 0], s[i, 1]);
			}
			step = 0;
			checkEqualStep();
		}

		/// <summary>
		/// Gets or sets comments
		/// </summary>
		public ArrayList Comments
		{
			get
			{
				return comments;
			}
			set
			{
				if (value != null)
				{
					comments.Clear();
					foreach (ICloneable c in value)
						comments.Add(c.Clone());
				}
			}
		}


		/// <summary>
		/// Adds point
		/// </summary>
		/// <param name="x">x - coordinate</param>
		/// <param name="y">y - coordinate</param>
		public void AddXY(double x, double y)
		{
			points.Add(new double[]{x, y});
		}

		/// <summary>
		/// Access to i - th point (j = 0 access to x - coordinate, j = 1 access to y coordinate)
		/// </summary>
		public double this[int i, int j]
		{
			get
			{ 
				double[] x = points[i] as double[];
				return x[j];
			}
		}

		/// <summary>
		/// Clears itself
		/// </summary>
		public virtual void Clear()
		{
			points.Clear();
		}

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

		/// <summary>
		/// Size of this series
		/// </summary>
		public double[,] Size
		{
			get
			{
				double[,] size = new double[2, 2];
				for (int i = 0; i < points.Count; i++)
				{
					double[] x = (double[])points[i];
					if (i == 0)
					{
						size[0, 0] = x[0];
						size[0, 1] = x[1];
						size[1, 0] = x[0];
						size[1, 1] = x[1];
						continue;
					}
					for (int j = 0; j < 2; j++)
					{
						if (x[j] < size[0, j])
						{
							size[0, j] = x[j];
						}
						if (x[j] > size[1, j])
						{
							size[1, j] = x[j];
						}
					}
				}
				return size;
			}
		}

		/// <summary>
		/// Creates correspond xml
		/// </summary>
		/// <param name="doc">document to create element</param>
		/// <returns>The created element</returns>
		public XmlElement CreateXmlPoint(int n, XmlDocument doc)
		{
			XmlElement el = doc.CreateElement("CommonPlotPoint");
			XmlAttribute nx = doc.CreateAttribute("NX");
			nx.Value = X;
			el.Attributes.Append(nx);
			XmlAttribute ny = doc.CreateAttribute("NY");
			ny.Value = Y;
			el.Attributes.Append(ny);
			double[] p = points[n] as double[];
			XmlAttribute x = doc.CreateAttribute("X");
			x.Value = p[0] + "";
			el.Attributes.Append(x);
			XmlAttribute y = doc.CreateAttribute("Y");
			y.Value = p[1] + "";
			el.Attributes.Append(y);
			return el;
		}






		/// <summary>
		/// Access to value of function and its derivation
		/// </summary>
		public double[] this[double x]
		{
			get
			{
				if (this[0, 0] > x)
				{
					//throw new Exception("Argument too small");
					parameter[0] = this[0, 1];
					parameter[1] = 0;
					return parameter;
				}
				if (this[Count - 1, 0] < x)
				{
					//throw new Exception("Argument too large");
					parameter[0] = this[Count - 1, 1];
					parameter[1] = 0;
					return parameter;
				}
				if (step != 0)
				{
					int i = (int)(Math.Floor((x - this[0, 0]) / step));
					if (i == Count - 1)
					{
						--i;
					}
					double x1 = this[i, 0];
					double x2 = this[i + 1, 0];
					double y1 = this[i, 1];
					double y2 = this[i + 1, 1];
					parameter[1] = (y2 - y1) / (x2 - x1);
					parameter[0] = y1 + parameter[1] * (x - x1);
					return parameter;
				}
				for (int i = 1; i < Count; i++)
				{
					double x2 = this[i, 0];
					if (x2 > x)
					{
						double x1 = this[i - 1, 0];
						double y1 = this[i - 1, 1];
						double y2 = this[i, 1];
						parameter[1] = (y2 - y1) / (x2 - x1);
						parameter[0] = y1 + parameter[1] * (x - x1);
						break;
					}
				}
				return parameter;
			}
		}




		public string X
		{
			get
			{
				return x;
			}
			set
			{
				x = value;
			}
		}

		public string Y
		{
			get
			{
				return y;
			}
			set
			{
				y = value;
			}
		}

		private object parX()
		{
			initMea();
			return meaX;
		}

		private object parY()
		{
			initMea();
			return meaY;
		}

		private void initMea()
		{
			if (meaX.Length == points.Count)
			{
				return;
			}
			meaX = new object[points.Count];
			meaY = new object[meaX.Length];
			type = new object[meaX.Length];
			for (int i = 0; i < meaX.Length; i++)
			{
				meaX[i] = this[i, 0];
				meaY[i] = this[i, 1];
			}
            Double a = 0;
            type = new ArrayReturnType(a, new int[] { points.Count });

		}



		/// <summary>
		/// Checks whether series has equal step
		/// </summary>
		private void checkEqualStep()
		{
			if (points.Count < 2)
			{
				return;
			}
			double s =  0;
			double t = 0;
			for (int i = 0; i < points.Count; i++)
			{
				double[] p = points[i] as double[];
				if (i == 1)
				{
					s = p[0] - t;
				}
				if (i > 1)
				{
					if (Math.Abs(s - (p[0] - t)) > (eps * Math.Abs(s)))
					{
						return;
					}
				}
				t = p[0];
			}
			step = s;
		}

		/// <summary>
		/// Initialization
		/// </summary>
		private void initialize()
		{
			measureParameter[0] = new DataPerformer.MeasureParameter(parX);
			measureParameter[1] = new DataPerformer.MeasureParameter(parY);
			measureY = YMeasure.getMeasure(this);
			points = new List<double[]>();
			pointStart = new int[2];
			pointFinish = new int[2];
		}

		#endregion

		class YMeasure : IMeasure
		{
			private Series s;

			public static IMeasure getMeasure(Series s)
			{
				return new YMeasure(s);
			}

			YMeasure(Series s)
			{
				this.s = s;
			}
			#region IMeasure Members

			public DataPerformer.MeasureParameter Parameter
			{
				get
				{
					return s.measureParameter[1];
				}
			}

			public DataPerformer.MeasureParameter Derivation
			{
				get
				{
					return null;
				}
			}

			public string Name
			{
				get
				{
					return "Y";
				}
			}

			public double Factor
			{
				get
				{
					return 1;
				}
			}

			public object Type
			{
				get
				{
					return s.Type;
				}
			}

			#endregion
		}

		class XSelection : IStructuredSelection
		{
			private Series s;

			#region IStructuredSelection Members

			public XSelection(Series s)
			{
				this.s = s;
			}

			/// <summary>
			/// Dimension of data
			/// </summary>
			public int DataDimension
			{
				get
				{
					return s.points.Count;
				}
			}

			/// <summary>
			/// Access to n - th element
			/// </summary>
			double? IStructuredSelection.this[int n]
			{
				get
				{
					return s[n, 0];
				}
			}

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

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

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

			/// <summary>
			/// Count of points
			/// </summary>
			public int PointsCount
			{
				get
				{
					return s.points.Count;
				}
			}
		
			/// <summary>
			/// Free variables
			/// </summary>
			public string[] Variables
			{
				get
				{
					return s.var;
				}
			}
			/// <summary>
			/// Dimension of output vector
			/// </summary>
			public int VectorDimension
			{
				get
				{
					return 1;
				}
			}

			/// <summary>
			/// Gets value of variable
			/// </summary>
			/*double IArgumentSelection.this[int i, string str]
			{
				get
				{
					return this[i, 0];
				}
			}*/




			public string Name
			{
				get
				{
					return "X";
				}
			}

			#endregion
		}
	}

}

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