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