private string toString(Codification <string> codebook, string outputColumn, CultureInfo cultureInfo) { var rulesArray = new DecisionRule[this.rules.Count]; rules.CopyTo(rulesArray); Array.Sort(rulesArray); StringBuilder sb = new StringBuilder(); if (codebook != null) { foreach (DecisionRule rule in rulesArray) { sb.AppendLine(rule.ToString(codebook, outputColumn, cultureInfo)); } } else { foreach (DecisionRule rule in rulesArray) { sb.AppendLine(rule.ToString(cultureInfo)); } } return(sb.ToString()); }
/// <summary> /// Determines whether the specified <see cref="DecisionRule"/> is equal to this instance. /// </summary> /// /// <param name="other">The <see cref="DecisionRule"/> to compare with this instance.</param> /// /// <returns> /// <c>true</c> if the specified <see cref="DecisionRule"/> /// is equal to this instance; otherwise, <c>false</c>. /// </returns> /// public bool Equals(DecisionRule other) { if ((object)other == null) { return(false); } return(this.Output == other.output && this.Antecedents.SetEquals(other.Antecedents)); }
/// <summary> /// Compares this instance to another <see cref="DecisionRule"/>. /// </summary> /// public int CompareTo(DecisionRule other) { int order = this.Output.CompareTo(other.Output); if (order == 0) { return(this.Antecedents.Count.CompareTo(other.Antecedents.Count)); } return(order); }
/// <summary> /// Determines whether the specified <see cref="DecisionRule"/> is equal to this instance. /// </summary> /// /// <param name="other">The <see cref="DecisionRule"/> to compare with this instance.</param> /// /// <returns> /// <c>true</c> if the specified <see cref="DecisionRule"/> /// is equal to this instance; otherwise, <c>false</c>. /// </returns> /// public bool Equals(DecisionRule other) { if (other == null) { return(false); } bool s = this.Antecedents.SetEquals(other.Antecedents); bool o = this.Output == other.output; return(s && o); }
/// <summary> /// Creates a new <see cref="DecisionSet"/> from a <see cref="DecisionTree"/>. /// </summary> /// /// <param name="tree">A <see cref="DecisionTree"/>.</param> /// /// <returns>A <see cref="DecisionSet"/> that is completely /// equivalent to the given <paramref name="tree"/></returns> /// public static DecisionSet FromDecisionTree(DecisionTree tree) { var rules = new List <DecisionRule>(); foreach (var node in tree) { if (node.IsLeaf && !node.IsRoot && node.Output.HasValue) { rules.Add(DecisionRule.FromNode(node)); } } return(new DecisionSet(rules) { NumberOfClasses = tree.NumberOfClasses, NumberOfOutputs = tree.NumberOfOutputs }); }
/// <summary> /// Gets whether this rule and another rule have /// the same antecedents but different outputs. /// </summary> /// /// <param name="rule"></param> /// /// <returns>True if the two rules are contradictory; /// false otherwise.</returns> /// public bool IsInconsistentWith(DecisionRule rule) { return(Antecedents.SetEquals(rule.Antecedents) && Output != rule.Output); }
/// <summary> /// Removes a given rule from the set. /// </summary> /// /// <param name="item">The <see cref="DecisionRule"/> to be removed.</param> /// /// <returns>True if the rule was removed; false otherwise.</returns> /// public bool Remove(DecisionRule item) { return(rules.Remove(item)); }
/// <summary> /// Adds a new <see cref="DecisionRule"/> to the set. /// </summary> /// /// <param name="item">The <see cref="DecisionRule"/> to be added.</param> /// public void Add(DecisionRule item) { rules.Add(item); }
/// <summary> /// Computes the reduction algorithm. /// </summary> /// /// <param name="inputs">A set of training inputs.</param> /// <param name="outputs">The outputs corresponding to each of the inputs.</param> /// /// <returns>The average error after the reduction.</returns> /// public double Compute(double[][] inputs, int[] outputs) { int samples = outputs.Length; bool[] actual = new bool[samples]; bool[] expected = new bool[samples]; DecisionRule[] list = decisionList.ToArray(); var antecedents = new HashSet <Antecedent>(); foreach (DecisionRule rule in list) { foreach (Antecedent antecedent in rule) { antecedents.Add(antecedent); } } // 1. Eliminate unnecessary antecedents for (int y = 0; y < decisionList.OutputClasses; y++) { for (int i = 0; i < outputs.Length; i++) { expected[i] = outputs[i] == y; } var unnecessary = new HashSet <Antecedent>(); /*foreach (var rule in list) * { * if (rule.Output != y) * continue; */ foreach (var antecedent in antecedents) { for (int i = 0; i < inputs.Length; i++) { actual[i] = antecedent.Match(inputs[i]); } if (CanEliminate(actual, expected)) { unnecessary.Add(antecedent); } } //} foreach (var antecedent in unnecessary) { foreach (var rule in list) { if (rule.Output == y) { rule.Antecedents.Remove(antecedent); } } } } bool[][] matches = new bool[list.Length][]; int[] counts = new int[list.Length]; for (int i = 0; i < matches.Length; i++) { DecisionRule rule = list[i]; matches[i] = new bool[outputs.Length]; for (int j = 0; j < inputs.Length; j++) { matches[i][j] = rule.Match(inputs[j]); if (matches[i][j]) { counts[i]++; } } } double start = computeError(inputs, outputs, list); for (int i = 0; i < list.Length; i++) { if (list[i] == null) { continue; } for (int j = 0; j < list.Length; j++) { if (list[i] == null) { break; } if (list[j] == null) { continue; } if (list[i].IsInconsistentWith(list[j])) { if (counts[i] > counts[j]) { list[j] = null; counts[j] = 0; } else { list[i] = null; counts[i] = 0; } } } } list = list.Distinct(allowNulls: false); List <DecisionRule> newList = new List <DecisionRule>(list); double middle = computeError(inputs, outputs, list); // 2. Eliminate redundant rules from the set for (int y = 0; y < decisionList.OutputClasses; y++) { for (int i = 0; i < outputs.Length; i++) { expected[i] = outputs[i] == y; } var unnecessary = new HashSet <DecisionRule>(); foreach (var rule in newList) { if (rule.Output != y) { continue; } for (int i = 0; i < inputs.Length; i++) { actual[i] = rule.Match(inputs[i]); } if (CanEliminate(actual, expected)) { unnecessary.Add(rule); } } foreach (var rule in unnecessary) { newList.Remove(rule); } } double final = computeError(inputs, outputs, newList); decisionList.Clear(); decisionList.AddRange(newList); // Compute new decision error double newError = ComputeError(inputs, outputs); return(newError); }