public List <List <TLayout> > GetClusters(List <TLayout> layouts, GetDistanceDelegate <TLayout> getDistance, double stopDistance)
        {
            var layoutToIntMapping    = layouts.CreateIntMapping();
            var layoutDistanceMatrix  = GetLayoutDistanceMatrix(layoutToIntMapping, getDistance);
            var clusters              = GetInitialClusters(layoutToIntMapping);
            var clusterDistanceMatrix = layoutDistanceMatrix.Select(x => x.ToArray()).ToArray(); // Copy layoutDistanceMatrix array

            // Compute clusters
            while (clusters.Count > 10)
            {
                var minDistance = double.MaxValue;
                var minCluster1 = -1;
                var minCluster2 = -1;

                foreach (var cluster1 in clusters.Keys)
                {
                    foreach (var cluster2 in clusters.Keys)
                    {
                        if (cluster1 != cluster2)
                        {
                            var distance = clusterDistanceMatrix[cluster1][cluster2];

                            if (distance < minDistance)
                            {
                                minDistance = distance;
                                minCluster1 = cluster1;
                                minCluster2 = cluster2;
                            }
                        }
                    }
                }

                if (minDistance > stopDistance)
                {
                    break;
                }

                MergeClusters(minCluster1, minCluster2, clusters, clusterDistanceMatrix, layoutDistanceMatrix);
            }

            // Prepare output
            var output = clusters
                         .Values
                         .OrderByDescending(x => x.Count)
                         .Select(x => x.Select(y => layoutToIntMapping.GetByValue(y)).ToList())
                         .ToList();

            return(output);
        }
        private double[][] GetLayoutDistanceMatrix(TwoWayDictionary <TLayout, int> layouts, GetDistanceDelegate <TLayout> getDistance)
        {
            var distanceMatrix = new double[layouts.Count][];

            for (int i = 0; i < layouts.Count; i++)
            {
                distanceMatrix[i] = new double[layouts.Count];
            }

            for (int i = 0; i < layouts.Count - 1; i++)
            {
                for (int j = i + 1; j < layouts.Count; j++)
                {
                    var distance = getDistance(layouts.GetByValue(i), layouts.GetByValue(j));
                    distanceMatrix[i][j] = distance;
                    distanceMatrix[j][i] = distance;
                }
            }

            return(distanceMatrix);
        }
Esempio n. 3
0
        protected override void CalculateDistancesFromAPlayer(GameState gameState, PlayerType player, HashSet <CellState> reachableCells)
        {
            int nextDistance                  = 0;
            int numberOfCellsReachable        = 0;
            int totalDegreesOfCellsReachable  = 0;
            HashSet <CellState> cellsToExpand = new HashSet <CellState>();

            DijkstraStatus dijkstraStatus           = DijkstraStatus.NotCalculated;
            bool           isPartiallyCalculated    = false;
            int            upToDateDijkstraDistance = 0;
            CellState      playersCell;

            CompartmentStatus   compartmentStatus;
            GetDistanceDelegate getDistance = null;
            SetDistanceDelegate setDistance = null;

            switch (player)
            {
            case PlayerType.You:
                compartmentStatus        = CompartmentStatus.InYourCompartment;
                getDistance              = GetDistanceFromYou;
                setDistance              = SetDistanceFromYou;
                dijkstraStatus           = gameState.YourDijkstraStatus;
                upToDateDijkstraDistance = gameState.YourUpToDateDijkstraDistance;
                playersCell              = gameState.YourCell;
                break;

            case PlayerType.Opponent:
                compartmentStatus        = CompartmentStatus.InOpponentsCompartment;
                getDistance              = GetDistanceFromOpponent;
                setDistance              = SetDistanceFromOpponent;
                dijkstraStatus           = gameState.OpponentsDijkstraStatus;
                upToDateDijkstraDistance = gameState.OpponentsUpToDateDijkstraDistance;
                playersCell              = gameState.OpponentsCell;
                break;

            default:
                throw new ApplicationException("The player must be specified when calculating distances");
            }

            if (dijkstraStatus != DijkstraStatus.FullyCalculated)
            {
                if (player == PlayerType.You)
                {
                    gameState.OpponentIsInSameCompartment = false;
                }

                isPartiallyCalculated = (dijkstraStatus == DijkstraStatus.PartiallyCalculated && upToDateDijkstraDistance > 0);

                if (isPartiallyCalculated)
                {
                    nextDistance = upToDateDijkstraDistance;
                    foreach (CellState cellState in gameState.GetAllCellStates())
                    {
                        int distance = getDistance(cellState);
                        if ((cellState.OccupationStatus == OccupationStatus.Clear) &&
                            (cellState.CompartmentStatus == compartmentStatus || cellState.CompartmentStatus == CompartmentStatus.InSharedCompartment) &&
                            (distance <= upToDateDijkstraDistance))
                        {
                            if (reachableCells != null)
                            {
                                reachableCells.Add(cellState);
                            }
                            numberOfCellsReachable++;
                            totalDegreesOfCellsReachable += cellState.DegreeOfVertex;
                            if (distance == upToDateDijkstraDistance)
                            {
                                cellsToExpand.Add(cellState);
                            }
                        }
                        else
                        {
                            cellState.ClearDijkstraStateForPlayer(player);
                        }
                    }
                }
                else
                {
                    gameState.ClearDijkstraPropertiesForPlayer(player);
                    cellsToExpand.Add(playersCell);
                }

                while (cellsToExpand.Any())
                {
                    nextDistance++;
                    HashSet <CellState> nextLevelOfCells = new HashSet <CellState>();
                    foreach (CellState sourceCell in cellsToExpand)
                    {
                        CellState[] adjacentCells = sourceCell.GetAdjacentCellStates();
                        foreach (CellState adjacentCell in adjacentCells)
                        {
                            switch (adjacentCell.OccupationStatus)
                            {
                            case OccupationStatus.Opponent:
                                if (player == PlayerType.You)
                                {
                                    gameState.OpponentIsInSameCompartment = true;
                                }
                                break;

                            case OccupationStatus.Clear:
                                adjacentCell.CompartmentStatus |= compartmentStatus;
                                int existingDistance = getDistance(adjacentCell);
                                if (nextDistance < existingDistance)
                                {
                                    setDistance(adjacentCell, nextDistance);

                                    // HashSets automatically filter out duplicates, so no need to check:
                                    nextLevelOfCells.Add(adjacentCell);
                                    if (reachableCells != null)
                                    {
                                        reachableCells.Add(adjacentCell);
                                    }
                                }
                                break;
                            }
                        }
                        numberOfCellsReachable++;
                        totalDegreesOfCellsReachable += sourceCell.DegreeOfVertex;
                    }
                    cellsToExpand = nextLevelOfCells;
                }

                switch (player)
                {
                case PlayerType.You:
                    gameState.NumberOfCellsReachableByYou       = numberOfCellsReachable;
                    gameState.TotalDegreesOfCellsReachableByYou = totalDegreesOfCellsReachable;
                    break;

                case PlayerType.Opponent:
                    gameState.NumberOfCellsReachableByOpponent       = numberOfCellsReachable;
                    gameState.TotalDegreesOfCellsReachableByOpponent = totalDegreesOfCellsReachable;
                    break;
                }

                switch (player)
                {
                case PlayerType.You:
                    gameState.YourDijkstraStatus           = DijkstraStatus.FullyCalculated;
                    gameState.YourUpToDateDijkstraDistance = int.MaxValue;
                    break;

                case PlayerType.Opponent:
                    gameState.OpponentsDijkstraStatus           = DijkstraStatus.FullyCalculated;
                    gameState.OpponentsUpToDateDijkstraDistance = int.MaxValue;
                    break;
                }
            }
            else
            {
                // Fix ClosestPlayer:
                foreach (CellState cellState in gameState.GetAllCellStates())
                {
                    if (cellState.ClosestPlayer == PlayerType.Unknown)
                    {
                        switch (cellState.CompartmentStatus)
                        {
                        case CompartmentStatus.InYourCompartment:
                            cellState.ClosestPlayer = PlayerType.You;
                            break;

                        case CompartmentStatus.InOpponentsCompartment:
                            cellState.ClosestPlayer = PlayerType.Opponent;
                            break;

                        case CompartmentStatus.InSharedCompartment:
                            if (cellState.DistanceFromYou > cellState.DistanceFromOpponent)
                            {
                                cellState.ClosestPlayer = PlayerType.You;
                            }
                            else
                            if (cellState.DistanceFromOpponent > cellState.DistanceFromYou)
                            {
                                cellState.ClosestPlayer = PlayerType.Opponent;
                            }
                            else
                            {
                                cellState.ClosestPlayer = gameState.PlayerToMoveNext;
                            }
                            break;
                        }
                    }
                }

                gameState.YourCell.ClosestPlayer      = PlayerType.You;
                gameState.OpponentsCell.ClosestPlayer = PlayerType.Opponent;
            }
        }
Esempio n. 4
0
        public static string KNN <T>(
            List <T> trainFeatures,
            List <string> trainLabels,
            T testFeature,
            GetDistanceDelegate <T> getDistance,
            int K = 4)
        {
            Dictionary <string, double> classSize = new Dictionary <string, double>();

            foreach (var label in trainLabels)
            {
                if (classSize.ContainsKey(label))
                {
                    classSize[label]++;
                }
                else
                {
                    classSize[label] = 0.0;
                }
            }

            string predictLabel = "";
            List <Tuple <double, int> > distAndIndexes = new List <Tuple <double, int> >();

            for (int i = 0; i < trainFeatures.Count; i++)
            {
                distAndIndexes.Add(null);
            }

            Parallel.For(0, trainFeatures.Count, (i) =>
            {
                distAndIndexes[i] = Tuple.Create(getDistance(trainFeatures[i], testFeature), i);
            });
            distAndIndexes.Sort();

            Dictionary <string, int> dict = new Dictionary <string, int>();

            for (int i = 0; i < K; i++)
            {
                string label = trainLabels[distAndIndexes[i].Item2];

                if (dict.ContainsKey(label))
                {
                    dict[label]++;
                }
                else
                {
                    dict[label] = 1;
                }
            }

            double max = -1;

            foreach (var item in dict)
            {
                string label = item.Key;
                int    num   = item.Value;
                double ratio = num / classSize[label];

                if (ratio > max)
                {
                    predictLabel = label;
                    max          = ratio;
                }
            }

            return(predictLabel);
        }