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 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 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 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 m_results; #endregion #region Constructor public NominalTest(string name, int id) { m_name = name; m_id = id; m_results = new List(); } #endregion #region ITest Members public IList 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 m_P; #endregion #region Constructor public TermostatLeaf(int category, List 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 P { get { return m_P; } set { m_P = new List(value); } } #endregion } public class TermostatNode : ITreeNode { #region Members ITest m_test; int m_temparature; Dictionary m_listOfLeaves = new Dictionary(); List m_P = null; #endregion #region Constructor #endregion #region INode Members public ITest Test { get { return m_test; } set { m_test = value; } } public IDictionary 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 P { get { return m_P; } set { m_P = new List(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 } /// /// Klasa służy do pokazania sobie jak jest drzewo zbudowane /// public class ShowedNode { string m_testName; int[] m_P; Dictionary m_nodes = new Dictionary(); 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 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; } } /// /// Klasa zagreguje wartości porządkowe dla atrybutu o indeksie m_attrIndex /// public class AttributChange { #region Members int m_attrIndex; List m_list; #endregion #region Constructor public AttributChange(List tresholds, int attrIndex) { m_list = new List(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(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 } /// /// Klasa zarządza kolekcją AttributChange i automatycznie zmienia atrubuty dla całego vectora atrybutów /// public class AttrChangeCollection { #region Members private Dictionary m_attrChangeCollection; #endregion #region Constructor public AttrChangeCollection() { m_attrChangeCollection = new Dictionary(); } #endregion #region Public Methods public void Add(List 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("DaysOfWeek", 7, sw); m_attrChangeCollection[1].WriteOldNewValues("Hour", 24, sw); m_attrChangeCollection[2].WriteOldNewValues("Month", 12, sw); sw.Flush(); sw.Close(); } } #endregion } #endregion }