using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace Morcinek.Machine_Learning
{
#region Interfaces
public interface ITest // Ogólne nawet dla nominalnych i ciągłych
{
string AttributeName { get; set;}
int AttributeIndex { get; set;}
IList<int> Results { get;}
void AddResult(int result);
}
public interface ILeaf
{
int Category { get; set;} // Może tylko set zostawić?
int GetCategory(object[] attributes);
ShowedNode ShowTree(out string dotName);
IList<int> P { get; set;} // zbiór indeksów z etykietowanych przykładów dla danego liścia
}
public interface ITreeNode : ILeaf
{
ITest Test { get; set;}
IDictionary<int, ILeaf> DictOfNodes { get;}
void AddNode(int r, ILeaf node);
}
#endregion
#region Classes
public class NominalTest : ITest
{
#region Members
private string m_name;
private int m_id;
private List<int> m_results;
#endregion
#region Constructor
public NominalTest(string name, int id)
{
m_name = name;
m_id = id;
m_results = new List<int>();
}
#endregion
#region ITest Members
public IList<int> Results
{
get { return m_results; }
}
public string AttributeName
{
get
{
return m_name;
}
set
{
m_name = value;
}
}
public int AttributeIndex
{
get
{
return m_id;
}
set
{
m_id = value;
}
}
public void AddResult(int result)
{
if (!m_results.Contains(result))
m_results.Add(result);
}
#endregion
}
public class TermostatLeaf : ILeaf
{
#region Members
int m_category;
List<int> m_P;
#endregion
#region Constructor
public TermostatLeaf(int category, List<int> P)
{
m_category = category;
this.P = P;
}
#endregion
#region ILeaf Members
public int Category
{
get
{
return m_category;
}
set
{
m_category = value;
}
}
public int GetCategory(object[] attributes)
{
return m_category;
}
public ShowedNode ShowTree(out string dotName)
{
dotName = "";
ShowedNode node = new ShowedNode();
node.P = m_P.ToArray();
node.Category = this.Category;
return node;
}
public IList<int> P
{
get
{
return m_P;
}
set
{
m_P = new List<int>(value);
}
}
#endregion
}
public class TermostatNode : ITreeNode
{
#region Members
ITest m_test;
int m_temparature;
Dictionary<int, ILeaf> m_listOfLeaves = new Dictionary<int, ILeaf>();
List<int> m_P = null;
#endregion
#region Constructor
#endregion
#region INode Members
public ITest Test
{
get
{
return m_test;
}
set
{
m_test = value;
}
}
public IDictionary<int, ILeaf> DictOfNodes
{
get
{
return m_listOfLeaves;
}
}
public void AddNode(int r, ILeaf node)
{
if (!m_listOfLeaves.ContainsKey(r))
m_listOfLeaves.Add(r, node);
}
#endregion
#region ILeaf Members
public int Category
{
get
{
return m_temparature;
}
set
{
m_temparature = value;
}
}
public int GetCategory(object[] attributes)
{
int value = (int)attributes[m_test.AttributeIndex]; // Wartość atrybutu który testujemy
if (!m_test.Results.Contains(value)) // Jeśli R (rezultaty) nie zawiera wartości 'value'
return this.Category;
return m_listOfLeaves[value].GetCategory(attributes);
}
public IList<int> P
{
get
{
return m_P;
}
set
{
m_P = new List<int>(value);
}
}
public ShowedNode ShowTree(out string dotName)
{
dotName = "";
ShowedNode node = new ShowedNode();
node.P = m_P.ToArray();
node.TestName = m_test.AttributeName;
foreach (int key in m_listOfLeaves.Keys)
{
string temp;
node.Nodes.Add(key, m_listOfLeaves[key].ShowTree(out temp));
}
return node;
}
#endregion
}
/// <summary>
/// Klasa służy do pokazania sobie jak jest drzewo zbudowane
/// </summary>
public class ShowedNode
{
string m_testName;
int[] m_P;
Dictionary<int, ShowedNode> m_nodes = new Dictionary<int, ShowedNode>();
private int m_category;
private static int counter = 0;
public static StreamWriter sw;
public string TestName
{
get
{
return m_testName;
}
set
{
m_testName = value;
}
}
public int[] P
{
get
{
return m_P;
}
set
{
m_P = value;
}
}
public int Category
{
get
{
return m_category;
}
set
{
m_category = value;
}
}
public Dictionary<int, ShowedNode> Nodes
{
get
{
return m_nodes;
}
set
{
m_nodes = value;
}
}
public string GetGraphvizName(StreamWriter sw)
{
string nodeName;
string tempChildName;
if (m_nodes.Count == 0) // Tylko liść
{
nodeName = (++counter).ToString();
sw.WriteLine( nodeName + " [label=\"" + ((Thermostat)this.Category).ToString() + "\", shape = record];"); // A [label="1" , shape = record]
}
else
{
nodeName = (++counter).ToString();
sw.WriteLine( nodeName + " [label=\"" + this.TestName + "\", shape = ellipse];"); // A [label="1" , shape = record]
foreach (int key in m_nodes.Keys) // Dla wszystkich wyników testu
{
tempChildName = m_nodes[key].GetGraphvizName(sw); // Wywołanie dla potomnych
sw.WriteLine(nodeName + " -> " + tempChildName + "[ label = " + key + " ];"); // bieżący node -> nazwa którą dostałem
}
}
return nodeName;
}
}
/// <summary>
/// Klasa zagreguje wartości porządkowe dla atrybutu o indeksie m_attrIndex
/// </summary>
public class AttributChange
{
#region Members
int m_attrIndex;
List<int> m_list;
#endregion
#region Constructor
public AttributChange(List<int> tresholds, int attrIndex)
{
m_list = new List<int>(tresholds);
m_attrIndex = attrIndex;
}
#endregion
#region Public Methods
public void Change(object[][] learning)
{
foreach (object[] row in learning)
{
this.Change(row);
}
}
public void Change(object[] row)
{
int pastValue = (int) row[m_attrIndex];
for (int i = 0; i < m_list.Count; i++)
{
if (pastValue <= m_list[i])
{
row[m_attrIndex] = i;
return;
}
}
row[m_attrIndex] = m_list.Count;
}
public void WriteOldNewValues<T>(string AttrName, int maxValue, StreamWriter sw)
{
sw.WriteLine("Attribute name: " + AttrName);
sw.WriteLine("0");
int currValue=0;
for (int i = 0; i < maxValue; i++)
{
if (currValue < m_list.Count)
{
if (i <= m_list[currValue])
{
sw.WriteLine("\t" + ((T)(object)(i)).ToString());
}
else
{
sw.WriteLine((++currValue).ToString());
sw.WriteLine("\t" + ((T)(object)(i)).ToString());
}
}
else
sw.WriteLine("\t" + ((T)(object)(i)).ToString());
}
sw.WriteLine(sw.NewLine);
}
#endregion
}
/// <summary>
/// Klasa zarządza kolekcją AttributChange i automatycznie zmienia atrubuty dla całego vectora atrybutów
/// </summary>
public class AttrChangeCollection
{
#region Members
private Dictionary<int, AttributChange> m_attrChangeCollection;
#endregion
#region Constructor
public AttrChangeCollection()
{
m_attrChangeCollection = new Dictionary<int, AttributChange>();
}
#endregion
#region Public Methods
public void Add(List<int> tresholds, int attrIndex)
{
if (!m_attrChangeCollection.ContainsKey(attrIndex))
{
AttributChange attrChange = new AttributChange(tresholds,attrIndex);
m_attrChangeCollection[attrIndex] = attrChange;
}
else
throw new Exception("Atrybut już zmieniony");
}
public void Change(object[][] examples, int attrIndex)
{
if(m_attrChangeCollection.ContainsKey(attrIndex))
{
m_attrChangeCollection[attrIndex].Change(examples);
}
}
public void Change(object[][] examples)
{
foreach (AttributChange attrChange in m_attrChangeCollection.Values)
{
attrChange.Change(examples);
}
}
public void Change(object[] example)
{
foreach (AttributChange attrChange in m_attrChangeCollection.Values)
{
attrChange.Change(example);
}
}
public void WriteAggregateValues()
{
if (m_attrChangeCollection.Count > 0)
{
StreamWriter sw = new StreamWriter("Aggregate.txt", false);
m_attrChangeCollection[0].WriteOldNewValues<Days>("DaysOfWeek", 7, sw);
m_attrChangeCollection[1].WriteOldNewValues<int>("Hour", 24, sw);
m_attrChangeCollection[2].WriteOldNewValues<Month>("Month", 12, sw);
sw.Flush();
sw.Close();
}
}
#endregion
}
#endregion
}