using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using System.Runtime.Serialization;
using CategoryTheory;
using DiagramUI;
using DiagramUI.Interfaces;
using RealMatrixProcessor;
using BaseTypes;
using DataPerformer;
using DataPerformer.Interfaces;
namespace Regression
{
/// <summary>
/// General linear method with iterator
/// </summary>
[Serializable()]
public class IteratorGLM : CategoryObject, ISerializable, IDataConsumer,
IIteratorConsumer, IPostSetArrow
{
#region Fields
/// <summary>
/// String representations of aliases
/// </summary>
protected List<string> sAliases = new List<string>();
/// <summary>
/// String representations of left borders
/// </summary>
protected List<string> sLeft = new List<string>();
/// <summary>
/// String representations of left borders
/// </summary>
protected List<string> sRight = new List<string>();
/// <summary>
/// Auxiliary variable
/// </summary>
protected List<List<string>> sR = new List<List<string>>();
/// <summary>
/// Array of finite differences for derivation calculation
/// </summary>
protected double[] dx;
/// <summary>
/// Additional matrix for stability
/// </summary>
protected double[,] d;
/// <summary>
/// Children iterators
/// </summary>
protected List<IIterator> iterators = new List<IIterator>();
/// <summary>
/// Aliases for estimation
/// </summary>
protected IAlias[] aliases;
/// <summary>
/// Keys
/// </summary>
protected string[] keys;
/// <summary>
/// Left border measurements
/// </summary>
protected IMeasure[] left;
/// <summary>
/// Right border measurements
/// </summary>
protected IMeasure[] right;
/// <summary>
/// Auxiliary variable
/// </summary>
protected double[,] ht;
/// <summary>
/// Auxiliary variable
/// </summary>
protected double[,] a;
/// <summary>
/// Auxiliary variable
/// </summary>
protected int[] indxa;
/// <summary>
/// Auxiliary variable
/// </summary>
protected double[] z;
/// <summary>
/// Auxiliary variable
/// </summary>
protected double[,] mr;
/// <summary>
/// Auxiliary variable
/// </summary>
protected double[,] mr1;
/// <summary>
/// Covariation matrix measurements
/// </summary>
protected IMeasure[,] r;
/// <summary>
/// Auxiliary variable
/// </summary>
protected double[] y;
/// <summary>
/// Auxiliary variable
/// </summary>
protected double[] y1;
/// <summary>
/// Auxiliary variable
/// </summary>
protected double[] yr;
/// <summary>
/// Auxiliary variable
/// </summary>
protected double[,] htr;
/// <summary>
/// Auxiliary variable
/// </summary>
protected double[,] ad;
/// <summary>
/// Correct shift
/// </summary>
protected double[] correct;
/// <summary>
/// Own iterators
/// </summary>
protected List<IIterator> ownIterators = new List<IIterator>();
/// <summary>
/// Linked object
/// </summary>
protected object obj;
/// <summary>
/// This object as data consumer
/// </summary>
protected IDataConsumer consumer;
List<IMeasurements> measurements = new List<IMeasurements>();
static private readonly ConstMeasure zero = new ConstMeasure(0);
static private readonly ConstMeasure unity = new ConstMeasure(1);
#endregion
#region Constuctors
/// <summary>
/// Default constructor
/// </summary>
public IteratorGLM()
{
consumer = this;
}
/// <summary>
/// Deserialization constructor
/// </summary>
/// <param name="info">Serialization info</param>
/// <param name="context">Streaming context</param>
protected IteratorGLM(SerializationInfo info, StreamingContext context)
: this()
{
sAliases = info.GetValue("Aliases", typeof(List<string>)) as List<string>;
sLeft = info.GetValue("Left", typeof(List<string>)) as List<string>;
sRight = info.GetValue("Right", typeof(List<string>)) as List<string>;
sR = info.GetValue("R", typeof(List<List<string>>)) as List<List<string>>;
dx = info.GetValue("Dx", typeof(double[])) as double[];
d = info.GetValue("D", typeof(double[,])) as double[,];
}
#endregion
#region ISerializable Members
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Aliases", sAliases, typeof(List<string>));
info.AddValue("Left", sLeft, typeof(List<string>));
info.AddValue("Right", sRight, typeof(List<string>));
info.AddValue("R", sR, typeof(List<List<string>>));
info.AddValue("Dx", dx, typeof(double[]));
info.AddValue("D", d, typeof(double[,]));
}
#endregion
#region IPostSetArrow Members
void IPostSetArrow.PostSetArrow()
{
createArrays();
setZeros();
Prepare();
}
#endregion
#region IDataConsumer Members
void IDataConsumer.Add(IMeasurements mea)
{
measurements.Add(mea);
}
void IDataConsumer.Remove(IMeasurements mea)
{
measurements.Remove(mea);
}
void IDataConsumer.UpdateChildrenData()
{
foreach (IMeasurements m in measurements)
{
m.UpdateMeasurements();
}
}
int IDataConsumer.Count
{
get { return measurements.Count; }
}
IMeasurements IDataConsumer.this[int n]
{
get { return measurements[n]; }
}
void IDataConsumer.Reset()
{
this.FullReset();
}
#endregion
#region IIteratorConsumer Members
void IIteratorConsumer.Add(IIterator iterator)
{
ownIterators.Add(iterator);
}
void IIteratorConsumer.Remove(IIterator iterator)
{
ownIterators.Remove(iterator);
}
#endregion
#region Specific Members
/// <summary>
/// Sets all data
/// </summary>
/// <param name="aliases">Aliases</param>
/// <param name="left">Left borders</param>
/// <param name="right">Right borders</param>
/// <param name="r">Covariation matrix calculation</param>
/// <param name="dx">Shift for derivation calculation</param>
/// <param name="d">Additional matrix for stability</param>
public void Set(List<string> aliases, List<string> left,
List<string> right, List<List<string>> r,
double[] dx, double[,] d)
{
this.sAliases = aliases;
this.sLeft = left;
this.sRight = right;
this.sR = r;
this.dx = dx;
this.d = d;
createArrays();
setZeros();
Prepare();
}
/// <summary>
/// Count of data
/// </summary>
public int DataCount
{
get
{
return sLeft.Count;
}
}
/// <summary>
/// Count of aliases
/// </summary>
public int AliasesCount
{
get
{
return sAliases.Count;
}
}
/// <summary>
/// All aliases of object
/// </summary>
public List<string> AllAliases
{
get
{
List<string> l = new List<string>();
this.GetAliases(l, null);
return l;
}
}
/// <summary>
/// Gets i - th alias name
/// </summary>
/// <param name="i">Alias number</param>
/// <returns>Name of alias</returns>
public string GetAliasName(int i)
{
return sAliases[i];
}
/// <summary>
/// Gets name of i-th left
/// </summary>
/// <param name="i">number</param>
/// <returns>Name of i-th left</returns>
public string GetLeftName(int i)
{
return sLeft[i];
}
/// <summary>
/// Gets name of i-th right
/// </summary>
/// <param name="i"></param>
/// <returns>name of i-th left</returns>
public string GetRightName(int i)
{
return sRight[i];
}
/// <summary>
/// All measurements of this object
/// </summary>
public List<string> AllMeasurements
{
get
{
IDataConsumer c = this;
List<string> list = new List<string>();
for (int i = 0; i < c.Count; i++)
{
IMeasurements m = c[i];
IAssociatedObject ao = m as IAssociatedObject;
string on = this.GetRelativeName(ao) + ".";
for (int j = 0; j < m.Count; j++)
{
string s = on + m[j].Name;
list.Add(s);
}
}
return list;
}
}
/// <summary>
/// Correction matrix
/// </summary>
public double[,] CorrectionMatrix
{
get
{
return d;
}
set
{
if (value == null)
{
throw new Exception();
}
int n = sAliases.Count;
if (value.GetLength(0) != n | value.GetLength(1) != n)
{
throw new Exception();
}
d = value;
}
}
/// <summary>
/// Performs iteration
/// </summary>
/// <returns>Residue</returns>
public double Iterate()
{
double sigma = 0;
List<IIterator> iterators;
if (ownIterators.Count != 0)
{
iterators = ownIterators;
}
else
{
iterators = this.iterators;
}
if (iterators.Count == 0)
{
return 1;
}
foreach (IIterator it in iterators)
{
it.Reset();
}
for (int i = 0; i < a.GetLength(0); i++)
{
for (int j = 0; j < a.GetLength(1); j++)
{
a[i, j] = d[i, j];
}
}
for (int i = 0; i < z.Length; i++)
{
z[i] = 0;
}
while (true)
{
consumer.Reset();
try
{
consumer.UpdateChildrenData();
}
catch (Exception ex)
{
ex.Log();
goto cycle;
}
for (int i = 0; i < y.Length; i++)
{
object o = left[i].Parameter();
if (o == null)
{
goto cycle;
}
y[i] = (double)o;
o = right[i].Parameter();
if (o == null | o is DBNull)
{
goto cycle;
}
double res = (double)o - y[i];
yr[i] = res;
sigma += res * res;
}
for (int i = 0; i < aliases.Length; i++)
{
IAlias a = aliases[i];
string key = keys[i];
double delta = dx[i];
setDelta(a, key, delta);
consumer.Reset();
consumer.UpdateChildrenData();
for (int j = 0; j < y.Length; j++)
{
object obj = left[j].Parameter();
if (obj == null)
{
setDelta(a, key, -delta);
goto cycle;
}
ht[i, j] = ((double)obj - y[j]) / delta;
}
setDelta(a, key, -delta);
}
for (int i = 0; i < y.Length; i++)
{
for (int j = 0; j <= i; j++)
{
mr[i, j] = (double)r[i, j].Parameter();
mr[j, i] = mr[i, j];
}
}
RealMatrix.Invert(mr, mr1);
RealMatrix.Multiply(ht, mr1, htr);
for (int i = 0; i < a.GetLength(0); i++)
{
for (int k = 0; k < htr.GetLength(1); k++)
{
z[i] += htr[i, k] * yr[k];
for (int j = 0; j < a.GetLength(1); j++)
{
a[i, j] += htr[i, k] * ht[j, k];
}
}
}
cycle:
foreach (IIterator it in iterators)
{
if (!it.Next())
{
goto m;
}
}
}
m:
RealMatrix.Solve(a, z, indxa);
for (int i = 0; i < z.Length; i++)
{
setDelta(aliases[i], keys[i], z[i]);
}
return sigma;
}
/// <summary>
/// Performs n iterations
/// </summary>
/// <param name="n">Number of itrerations</param>
/// <returns>Residue</returns>
public double Iterate(int n)
{
Dictionary<double, double[]> d = new Dictionary<double, double[]>();
double[] res = null;
double a = 0;
for (int i = 0; i < n; i++)
{
Iterate();
res = new double[z.Length];
for (int j = 0; j < res.Length; j++)
{
res[j] = getValue(aliases[j], keys[j]);
}
d[CalculatedSigma] = res;
}
List<double> l = new List<double>(d.Keys);
l.Sort();
a = l[0];
res = d[a];
for (int i = 0; i < res.Length; i++)
{
setValue(aliases[i], keys[i], res[i]);
}
double ss = CalculatedSigma;
return a;
}
/// <summary>
/// Tests itself
/// </summary>
/// <param name="desktop">Desktop</param>
/// <param name="n">Number of iteratios</param>
public static void Test(IDesktop desktop, int n)
{
IList<ICategoryObject> objs = desktop.CategoryObjects;
IList<IteratorGLM> l = new List<IteratorGLM>();
foreach (object o in objs)
{
if (o.GetType().FullName.Equals("DataPerformer.IteratorGLM"))
{
IteratorGLM it = o as IteratorGLM;
l.Add(it);
}
}
foreach (IteratorGLM it in l)
{
for (int i = 0; i < n; i++)
{
it.Iterate();
}
}
l = null;
GC.Collect();
}
/// <summary>
/// Calculates Sigma
/// </summary>
public double CalculatedSigma
{
get
{
double sigma = 0;
List<IIterator> iterators;
if (ownIterators.Count != 0)
{
iterators = ownIterators;
}
else
{
iterators = this.iterators;
}
if (iterators.Count == 0)
{
return 1;
}
foreach (IIterator it in iterators)
{
it.Reset();
}
while (true)
{
consumer.Reset();
try
{
consumer.UpdateChildrenData();
}
catch (Exception ex)
{
ex.Log();
goto cycle;
}
for (int i = 0; i < y.Length; i++)
{
object o = left[i].Parameter();
if (o == null)
{
goto cycle;
}
y[i] = (double)o;
o = right[i].Parameter();
if (o == null | o is DBNull)
{
goto cycle;
}
double res = (double)o - y[i];
yr[i] = res;
sigma += res * res;
}
cycle:
foreach (IIterator it in iterators)
{
if (!it.Next())
{
goto m;
}
}
}
m:
return sigma;
}
}
void setDelta(IAlias a, string s, double delta)
{
double x = (double)a[s];
a[s] = x + delta;
}
void setValue(IAlias a, string s, double val)
{
a[s] = val;
}
double getValue(IAlias a, string s)
{
return (double)a[s];
}
void setZeros()
{
if (left != null)
{
for (int i = 0; i < left.Length; i++)
{
left[i] = zero;
right[i] = zero;
}
}
if (r != null)
{
for (int i = 0; i < r.GetLength(0); i++)
{
for (int j = 0; j < r.GetLength(1); j++)
{
r[i, j] = (i == j) ? unity : zero;
}
}
}
return;
/*for (int i = 0; i < sAliases.Count; i++)
{
for (int j = 0; j < sAliases.Count; j++)
{
d[i, j] = 0;
}
}
for (int i = 0; i < sAliases.Count; i++)
{
dx[i] = 0.000001;
}*/
}
/// <summary>
/// Prepares itself
/// </summary>
protected void Prepare()
{
this.GetIterators(iterators);
setZeros();
aliases = new IAlias[sAliases.Count];
keys = new string[sAliases.Count];
for (int i = 0; i < sAliases.Count; i++)
{
object[] o = this.FindAlias(sAliases[i]);
aliases[i] = o[0] as IAlias;
keys[i] = o[1] + "";
}
z = new double[sAliases.Count];
indxa = new int[sAliases.Count];
a = new double[sAliases.Count, sAliases.Count];
for (int i = 0; i < sLeft.Count; i++)
{
IMeasure m = find(sLeft[i]);
left[i] = m;
}
for (int i = 0; i < sRight.Count; i++)
{
IMeasure m = find(sRight[i]);
right[i] = m;
}
int n = sR.Count;
int k = sLeft.Count;
mr = new double[k, k];
mr1 = new double[k, k];
y = new double[k];
y1 = new double[k];
yr = new double[k];
for (int i = 0; i < n; i++)
{
for (int j = 0; j <= i; j++)
{
string sr = sR[i][j];
IMeasure mea = find(sr);
if (mea != null)
{
r[i, j] = mea;
}
}
}
}
private IMeasure find(string name)
{
int n = name.LastIndexOf(".");
if (n < 0)
{
return null;
}
string cn = name.Substring(0, n);
string suff = name.Substring(n + 1);
for (int i = 0; i < measurements.Count; i++)
{
IMeasurements mea = measurements[i];
IAssociatedObject ao = mea as IAssociatedObject;
string na = this.GetRelativeName(ao);
if (cn.Equals(na))
{
for (int j = 0; j < mea.Count; j++)
{
IMeasure m = mea[j];
if (suff.Equals(m.Name))
{
return m;
}
}
}
}
return null;
}
private void createArrays()
{
if (dx != null)
{
if (dx.Length > 0)
{
a = new double[dx.Length, dx.Length];
indxa = new int[dx.Length];
}
}
if (sLeft.Count > 0)
{
left = new IMeasure[sLeft.Count];
right = new IMeasure[sLeft.Count];
r = new IMeasure[left.Length, left.Length];
if (sAliases.Count > 0)
{
ht = new double[sAliases.Count, sLeft.Count];
htr = new double[sAliases.Count, sLeft.Count];
}
}
}
#endregion
#region ConstMeasure
class ConstMeasure : IMeasure, IDerivation
{
const Double t = 0;
private double c;
const double z = 0;
Func<object> par;
Func<object> der;
public ConstMeasure(double c)
{
this.c = c;
par = getP;
der = getD;
}
#region IMeasure Members
Func<object> IMeasure.Parameter
{
get { return par; }
}
string IMeasure.Name
{
get { return "const" + c; }
}
object IMeasure.Type
{
get { return t; }
}
#endregion
object getP()
{
return c;
}
object getD()
{
return z;
}
#region IDerivation Members
IMeasure IDerivation.Derivation
{
get { return DataPerformer.ConstantMeasure.Zero; }
}
#endregion
}
#endregion
}
}