public List <DecisionColumn> CalculateDecisions() { DecisionColumns = new List <DecisionColumn>(); for (int i = 0; i < DecisionRows.First().Length - 1; i++) { var decisionColumn = new DecisionColumn(); var uniqueValues = DecisionRows.Select(value => value[i]).Distinct().ToList(); foreach (var uniqueValue in uniqueValues) { var decisionAttributeOccurence = new DecisionAttributeOccurence(uniqueValue); for (int j = 0; j < DecisionRows.Count; j++) { if (DecisionRows[j][i] == uniqueValue) { var lastColumnDecision = LastRowOccurences.Where(occurence => occurence.RowNumbers.Contains(j + 1)).Select(occurence => occurence.Decision).First(); if (lastColumnDecision == DecisionType.Positive) { decisionAttributeOccurence.PositiveRowNumbers.Add(j + 1); } else { decisionAttributeOccurence.NegativeRowNumbers.Add(j + 1); } } } decisionColumn.Attributes.Add(decisionAttributeOccurence); } DecisionColumns.Add(decisionColumn); } CalculateColumnsEntropies(); CalculateColumnInformationGain(); var rejectedList = DecisionColumns.Where(column => AlreadyUsedIndexes.Contains((int)column.ColumnIndex)); var bestOne = DecisionColumns.Except(rejectedList).MaxBy(column => column.InformationGain); //Nieużyta z największym przyrostem informacji var indexes = new List <int> { (int)bestOne.ColumnIndex }; DoUnknownThing(indexes, null); return(DecisionColumns); }
private void DoUnknownThing(List <int> bestOneIndexes, List <List <int> > fullHierarchy) { var index = -1; var selectedIndexesForNextRound = new List <int>(); var newHierarchy = new List <List <int> >(); var locallyUsedColumnIndexes = new List <int>(); var localAttributeValue = string.Empty; foreach (var bestOneIndex in bestOneIndexes) { index++; var bestOne = DecisionColumns.First(col => col.ColumnIndex == bestOneIndex); bestOne.ColumnIndex = bestOneIndex; var rejectedList = DecisionColumns.Where(column => AlreadyUsedIndexes.Contains((int)column.ColumnIndex)); AlreadyUsedIndexes.Add((int)bestOne.ColumnIndex); //Dodajemy ja do listy na przyszlosc Console.WriteLine($"Columnd index {bestOne.ColumnIndex}"); foreach (var attribute in bestOne.Attributes) // i dla kazdego atrybutu najlepszej kolumny czyli np. dla pogody iterujemy sie po: sloecznie, pochmurno, itd. { var attributeRows = attribute.NegativeRowNumbers.Concat(attribute.PositiveRowNumbers) .ToList(); // bierzemy wszystkie indeksy wierszy w jakich wystepuja rejectedList = DecisionColumns.Where(column => AlreadyUsedIndexes.Contains((int)column.ColumnIndex)); var tempList = DecisionColumns.Except(rejectedList); foreach (var decisionColumn in tempList ) // i iterujemy sie po wszystkich niewykorzystanych kolumnach { decisionColumn.ColumnIndex = DecisionColumns.IndexOf(decisionColumn); var innerAttributes = decisionColumn.Attributes .Where(innerAttribute => innerAttribute.PositiveRowNumbers.Intersect(attributeRows).Any() || innerAttribute.NegativeRowNumbers.Intersect(attributeRows).Any()).ToList(); //to sa te atrybuty, ktory wystepuja w wierszach 'attribute' decisionColumn.CaseEntropy = 0; var allNegatives = innerAttributes.SelectMany(innerAttr => innerAttr.NegativeRowNumbers) .ToList(); if (allNegatives.Count(neg => attributeRows.Contains(neg)) > 0) { foreach (var innerAttribute in innerAttributes) { var innerRows = innerAttribute.NegativeRowNumbers .Concat(innerAttribute.PositiveRowNumbers) .ToList(); var innerPositiveRows = innerAttribute.PositiveRowNumbers .Where(inner => attributeRows.Contains(inner)).ToList(); var innerNegativeRows = innerAttribute.NegativeRowNumbers .Where(inner => attributeRows.Contains(inner)).ToList(); var positiveEntropy = innerPositiveRows.Count != 0 ? MathExtension.GetBinaryLogaritm(innerPositiveRows.Count, innerNegativeRows.Count + innerPositiveRows.Count) : 0d; var negativeEntropy = innerNegativeRows.Count != 0 ? MathExtension.GetBinaryLogaritm(innerNegativeRows.Count, innerNegativeRows.Count + innerPositiveRows.Count) : 0d; decisionColumn.CaseEntropy += (double)(innerNegativeRows.Count + innerPositiveRows.Count) / attributeRows.Count * (-positiveEntropy - negativeEntropy); } } else { decisionColumn.CaseEntropy = -1; } locallyUsedColumnIndexes.Add(Convert.ToInt32(decisionColumn.ColumnIndex)); } Console.WriteLine("Nazwa atrybutu" + attribute.Value); localAttributeValue = attribute.Value; if (tempList.Any()) { var x = tempList.MinBy(column => column.CaseEntropy); if (attribute.PositiveRowNumbers.Count == 0 && attribute.NegativeRowNumbers.Count > 0) { Console.WriteLine("NOPE NOPE NOPE"); } else if (x.CaseEntropy > -1) { Console.WriteLine("Index kolumny >>>> " + x.ColumnIndex); selectedIndexesForNextRound.Add(Convert.ToInt32(x.ColumnIndex)); } else { if (attribute.PositiveRowNumbers.Count == 0 && attribute.NegativeRowNumbers.Count > 0) { Console.WriteLine("Nie"); } if (attribute.PositiveRowNumbers.Count > 0 && attribute.NegativeRowNumbers.Count == 0) { Console.WriteLine("Tak"); } } var currentBranchHierarchy = new List <int>(); if (fullHierarchy?[index] != null) { currentBranchHierarchy.AddRange(fullHierarchy[index]); } else { currentBranchHierarchy.Add(bestOneIndexes.First()); } if (localAttributeValue != "-1" && x.CaseEntropy > -1) { var upperColumn = DecisionColumns[bestOneIndexes[index]]; currentBranchHierarchy.Add(upperColumn.Attributes.FindIndex(atr => atr.Value == localAttributeValue)); currentBranchHierarchy.Add(selectedIndexesForNextRound[index]); newHierarchy.Add(currentBranchHierarchy); } } else { var newThing = GetRowsFromPath(fullHierarchy[index]); var positiveRows = attribute.PositiveRowNumbers.Intersect(newThing.PositiveRowNumbers).ToList(); var negativeRows = attribute.NegativeRowNumbers.Intersect(newThing.NegativeRowNumbers).ToList(); var x = attribute.NegativeRowNumbers.Count; var y = attribute.PositiveRowNumbers.Count; if (positiveRows.Count == 0 && negativeRows.Count > 0) { Console.WriteLine("Nie!"); } else if (positiveRows.Count > 0 && negativeRows.Count == 0) { Console.WriteLine("Tak!"); } } } //Sprzatanie tutaj? Console.WriteLine("----------------------"); } AlreadyUsedIndexes.AddRange(locallyUsedColumnIndexes); if (selectedIndexesForNextRound.Count > 1) { DoUnknownThing(selectedIndexesForNextRound, newHierarchy); } }