private double DeltaAdd(ClopeCluster cluster, Transaction transaction, double r) { if (cluster == null) { return(transaction.ArrayValues.Count / Math.Pow(transaction.UniqueParameters, r)); } double squareNew = cluster.Square + transaction.ArrayValues.Count; double widthNew = cluster.Width; for (int i = 0; i < transaction.ArrayValues.Count; i++) { if (!cluster.Occ.ContainsKey(transaction.ArrayValues[i])) { widthNew++; } } var res = squareNew * (cluster.TransCount + 1) / Math.Pow(widthNew, r) - cluster.Square * cluster.TransCount / Math.Pow(cluster.Width, r); return(res); }
private double DeltaRemove(ClopeCluster cluster, Transaction transaction, double r) { // Удаление посленей транзакции из кластера равносильно // добавлению транзакции в новый (пустой) кластер только с другим знаком if (cluster.TransCount == 1) { return(-cluster.Square / Math.Pow(cluster.Width, r)); } double squareNew = cluster.Square - transaction.ArrayValues.Count; double widthNew = cluster.Width; for (int i = 0; i < transaction.ArrayValues.Count; i++) { if (cluster.Occ[transaction.ArrayValues[i]] == 1) { widthNew--; } } return(squareNew * (cluster.TransCount - 1) / Math.Pow(widthNew, r) - cluster.Square * cluster.TransCount / Math.Pow(cluster.Width, r)); }
public CalculationResult Initialise() { //StreamReader sr = new StreamReader(filePath); // Максимальное добавление - опорное значение double maxDelta; // Текущее добавление либо к пустому либо к существующему кластеру // Сравнивается с опорным double delta; // Получили самую первую транзакцию if (_dsProvider.MoveNext()) { Transaction firstTransaction = (Transaction)_dsProvider.Current; // Кладем самую первую транзакцию в самый первый кластер firstTransaction.ClusterNumber = 1; var firstCluster = new ClopeCluster(); firstCluster.AddTransaction(firstTransaction); //Транзакция лежит в коллеции своего кластера clusterDict.Add(1, firstCluster); // Первый кластер лежит в словаре под номером 1 transactionsTable.Add(firstTransaction); // Транзакции из файла хранятся в коллекции } // Теперь пошли циклом по остальным транзакциям while (_dsProvider.MoveNext()) { Transaction currentTransaction = (Transaction)_dsProvider.Current; //Создаем новый пустой кластер-приемник. определим, каким он будет var clustNew = new ClopeCluster(); //Считаем цену добавления транз в новый(пустой) кластер //Это значение - отправная точка для нас maxDelta = DeltaAdd(null, currentTransaction, repulsCoeff); var currentClustersCount = clusterDict.Count; for (int i = 0; i < currentClustersCount; i++) { delta = DeltaAdd(clusterDict[i + 1], currentTransaction, repulsCoeff); if (delta > maxDelta) { maxDelta = delta; clustNew = clusterDict[i + 1]; //Пока кластер-приемник у нас будет этот текущий //Отметили принадлежность транзакции к существующему кластеру currentTransaction.ClusterNumber = i + 1; } } //Если все таки положить в пустой кластер оказалось выгоднее, кладем туда if (clustNew.TransCount == 0) { var newClustNumb = clusterDict.Keys.Max() + 1; //У нового кластера - новый номер по порядку currentTransaction.ClusterNumber = newClustNumb; //Транзакция пока принадлежит этому кластеру clustNew.AddTransaction(currentTransaction); //Кладем в новый кластер очередную транзакцию clusterDict.Add(newClustNumb, clustNew); //Положили кластер в общий словарик } else { //Если же это один из существующих кластеров clustNew.AddTransaction(currentTransaction); //Добавляем в него транзакцию clusterDict[currentTransaction.ClusterNumber] = clustNew; //Обновляем в словаре этот кластер } //Транзакцию кладем в наш кэш-лист для второй итерации transactionsTable.Add(currentTransaction); } return(new CalculationResult { ClustersTable = clusterDict, TransactionsTable = transactionsTable }); }
public CalculationResult Iterate() { int countIteration = 0; bool moved = true; while (moved) // цикл по итерациям { countIteration++; moved = false; foreach (Transaction tr in transactionsTable) { // Цена добавления транзакции в новый кластер. Отправная точка сравнения double maxDelta = DeltaAdd(null, tr, repulsCoeff); // Запоминаем номер старого кластера, в котором лежала транзакция var oldClusterNumber = tr.ClusterNumber; var newClusterNumber = -1; // Узнаем цену удаления транзакции из ее текущего кластера double removeDelta = DeltaRemove(clusterDict[oldClusterNumber], tr, repulsCoeff); //Теперь перебираем все кластеры, кроме того, где лежала наша транзакция //и узнаем стоимость запиха транзакции туда var arrayWithoutCurrentCluster = clusterDict.Where(kvp => kvp.Key != tr.ClusterNumber).ToArray(); foreach (KeyValuePair <int, ClopeCluster> pair in arrayWithoutCurrentCluster) { double addDelta = DeltaAdd(pair.Value, tr, repulsCoeff); // Если стоимость от добавления транзакции в существующий кластер больше, чем в новый // предварительно решаем положить транзакцию в этот существующий кластер if (addDelta > maxDelta) { maxDelta = addDelta; // Запомнили новый кластер у транзакции newClusterNumber = pair.Key; } } // Окончательное решение, куда выгоднее положить транзакцию if (maxDelta + removeDelta > 0) { //Если не нашлось подходящих существующих кластеров if (newClusterNumber == -1) { var clast = new ClopeCluster(); clusterDict[oldClusterNumber].RemoveTransaction(tr); newClusterNumber = clusterDict.Count + 1; tr.ClusterNumber = newClusterNumber; clusterDict.Add(newClusterNumber, clast); clusterDict[newClusterNumber].AddTransaction(tr); } // Если имеющийся кластер нашелся else { clusterDict[oldClusterNumber].RemoveTransaction(tr); clusterDict[newClusterNumber].AddTransaction(tr); tr.ClusterNumber = newClusterNumber; } // В любом случае перестановка имела место, вторая итерация будет moved = true; } } } var clusterDictNew = clusterDict.Where(kvp => kvp.Value.TransCount != 0).ToDictionary(k => k.Key, k => k.Value); return(new CalculationResult { ClustersTable = clusterDictNew, TransactionsTable = transactionsTable, IterationCount = countIteration }); }