Exemple #1
0
    void ShowOptimalSolution()
    {
        if (currentInstanceMetadata == null)
        {
            return;
        }

        List <int> solution = new List <int>();

        string solutionFilePath = currentInstanceMetadata.ProblemFile.Replace(".vrp", ".opt");

        if (File.Exists(solutionFilePath))
        {
            StreamReader solutionFileStream = new StreamReader(solutionFilePath);
            solution = VRPModel.LoadSolutionFromStream(solutionFileStream);
        }
        else if (File.Exists(PROBLEM_SOURCE))
        {
            using (ZipArchive zip = ZipFile.Open(PROBLEM_SOURCE, ZipArchiveMode.Read))
            {
                string fileName = Path.GetFileName(solutionFilePath);
                foreach (ZipArchiveEntry entry in zip.Entries)
                {
                    if (entry.Name == fileName)
                    {
                        StreamReader solutionZipStream = new StreamReader(entry.Open());
                        solution = VRPModel.LoadSolutionFromStream(solutionZipStream);
                    }
                }
            }
        }

        var oldSolutionEdges = new List <GameObject>(instance.solutionEdges);

        foreach (var oldEdge in oldSolutionEdges)
        {
            instance.RemoveEdgeFromSolution(oldEdge);
            Remove(oldEdge);
        }

        for (int i = 1; i < solution.Count; i++)
        {
            var fromNode = solution[i - 1];
            var toNode   = solution[i];
            var edge     = CreateNewEdge(instance.points[fromNode], fromNode, toNode);
            instance.AddEdgeToSolution(edge);
        }

        optimalLoaded = true;
        RefreshStateAndUpdateDisplays();
        HighlightViolations();
    }
Exemple #2
0
    void ChooseNextLevel()
    {
        // Reset everything
        ClearGameObjects();
        Mouse.Clear();
        currentInstanceMetadata = null;
        instance            = null;
        truckFillBars       = new List <ProgressBar>();
        mouseDownPointIdx   = -1;
        mouseDownEdge       = null;
        activePointIdx      = -1;
        activePointObject   = null;
        dragEdges           = new List <GameObject>();
        blinkingObjects     = new List <GameObject>();
        originalColors      = new Dictionary <GameObject, Color>();
        pointToCircleObject = new Dictionary <Vector, GameObject>();

        //Mouse.Listen(MouseButton.Left, ButtonState.Pressed, MenuMousePressed, "Valitse kenttä");
        //TouchPanel.Listen(ButtonState.Released, OnTouchEvent, "Valitse kenttä");
        problemMenu.ViewSetSelect(problemInstanceMetadata, OnSetSelected);
    }
Exemple #3
0
    public void StartGame(string problemFilePath)
    {
        optimalLoaded = false;

        Mouse.Listen(MouseButton.Left, ButtonState.Pressed, MouseBtnGoesDown, "Tökkää piirtääksesi reittejä");
        Mouse.Listen(MouseButton.Left, ButtonState.Released, MouseBtnGoesUp, "");
        Mouse.ListenMovement(0.1, MouseMoves, "Rakenna reittejä venyttämällä");


        // UI
        trucksUsed    = new IntMeter(0);
        trucksDisplay = CreateMeterDisplay(
            trucksUsed,
            new Vector(-Screen.Width / 4, Screen.Top - TOP_MARGIN),
            LoadImage("truck"));

        distanceTraveled = new DoubleMeter(0.0);
        distanceDisplay  = CreateMeterDisplay(
            distanceTraveled,
            new Vector(0, Screen.Top - TOP_MARGIN),
            LoadImage("road"));

        ofBKS        = new IntMeter(99);
        ofBKSDisplay = CreateMeterDisplay(
            ofBKS,
            new Vector(Screen.Width / 4, Screen.Top - TOP_MARGIN),
            LoadImage("dash"));
        ofBKSDisplay.IntFormatString = "{0} %";
        UpdateDisplayIconPosition(ofBKSDisplay);
        ofBKSDisplay.IsVisible = false;
        // use "--" label until feasible
        ofBKSDisplayNA          = new Label("-- %");
        ofBKSDisplayNA.Position = ofBKSDisplay.Position;
        Add(ofBKSDisplayNA, 3);

        // Navigation buttons


        PushButton backButton = new PushButton(ofBKSDisplay.Width * 1.1, ofBKSDisplay.Height * 1.0, LoadImage("back_btn"));

        backButton.Clicked += () => ChooseNextLevel();
        backButton.Position = new Vector(-Screen.Width / 2 + ofBKSDisplay.Height * 1.5, ofBKSDisplay.Position.Y);
        Add(backButton);

        PushButton helpButton = new PushButton(ofBKSDisplay.Width * 1.1, ofBKSDisplay.Height * 1.0, LoadImage("help_btn"));

        helpButton.Clicked += () => ShowHelp();
        helpButton.Position = new Vector(Screen.Width / 2 - ofBKSDisplay.Height * 1.5, ofBKSDisplay.Position.Y);
        Add(helpButton);

        string problemName = Path.GetFileNameWithoutExtension(problemFilePath);

        if (File.Exists(problemFilePath))
        {
            StreamReader problemFileStream = new StreamReader(problemFilePath);
            // The problem
            instance = VRPModel.LoadProblemFromStream(problemFileStream, problemName,
                                                      Screen.Width - Screen.Width / SCREEN_MARGIN_WIDHT_RATIO,
                                                      Screen.Height - Screen.Height / SCREEN_MARGIN_WIDHT_RATIO
                                                      );
        }
        else if (File.Exists(PROBLEM_SOURCE))
        {
            using (ZipArchive zip = ZipFile.Open(PROBLEM_SOURCE, ZipArchiveMode.Read))
            {
                string fileName = Path.GetFileName(problemFilePath);
                foreach (ZipArchiveEntry entry in zip.Entries)
                {
                    if (entry.Name == fileName)
                    {
                        StreamReader problemZipStream = new StreamReader(entry.Open());
                        // The problem
                        instance = VRPModel.LoadProblemFromStream(problemZipStream, problemName,
                                                                  Screen.Width - Screen.Width / SCREEN_MARGIN_WIDHT_RATIO,
                                                                  Screen.Height - Screen.Height / SCREEN_MARGIN_WIDHT_RATIO
                                                                  );
                    }
                }
            }
        }


        // Determine the max size of a dot
        dotMaxSize = Math.Min(Screen.Width / DOT_MAX_SIZE_RATIO,
                              Screen.Height / DOT_MAX_SIZE_RATIO);
        for (int i = 1; i < instance.points.Count; i++)
        {
            for (int j = i + 1; j < instance.points.Count; j++)
            {
                double d = Vector.Distance(instance.points[i], instance.points[j]) * DOT_MIN_SIZE_MAX_ALLOWED_OVERLAP;
                if (d > DOT_MIN_SIZE_PX && d < dotMaxSize)
                {
                    dotMaxSize = d;
                }
            }
        }

        for (int i = 0; i < instance.points.Count; i++)
        {
            double hcd       = Math.Sqrt(Math.Max(0.5, instance.demands[i] / instance.capacity)) * dotMaxSize + BORDER_WIDTH * 2;
            var    hitCircle = new GameObject(hcd, hcd, Shape.Circle);
            hitCircle.IsVisible = false;
            hitCircle.Position  = instance.points[i];
            hitCircle.Tag       = i;
            Add(hitCircle);

            double d        = Math.Sqrt(instance.demands[i] / instance.capacity) * dotMaxSize;
            var    customer = new GameObject(d, d, Shape.Circle);
            if (i == 0)
            {
                customer.Color = DepotColor;
            }
            else
            {
                customer.Color = NotRoutedColor;
            }
            customer.Tag      = "customer";
            customer.Position = instance.points[i];
            Add(customer, -2);

            while (pointToCircleObject.ContainsKey(instance.points[i]))
            {
                instance.points[i] += new Vector(DOT_MIN_SIZE_PX, DOT_MIN_SIZE_PX);
            }
            pointToCircleObject.Add(instance.points[i], customer);

            var border = new GameObject(d + BORDER_WIDTH * 2, d + BORDER_WIDTH * 2, Shape.Circle);
            border.Color    = BorderColor;
            border.Position = instance.points[i];
            Add(border, -3);
        }
    }
Exemple #4
0
    static public VRPModel LoadProblemFromStream(StreamReader file, string problemName,
                                                 double displayWidth,
                                                 double displayHeight)
    {
        VRPModel model = new VRPModel();

        int               N            = 0;
        string            weightStyle  = "EUC_2D";
        string            weightFormat = "FULL_MATRIX";
        string            line;
        int               xDIdx = 0; int yDIdx = 0; // indexes for EXPLICIT matrix wts
        TSPLibReaderState state = TSPLibReaderState.Header;

        while ((line = file.ReadLine()) != null)
        {
            // Check for keywords
            // TODO: Name, EDGE_WEIGHT_TYPE, CAPACITY

            if (line.Contains("NODE_COORD_SECTION") || line.Contains("DISPLAY_DATA_SECTION"))
            {
                state = TSPLibReaderState.CoordSection;
                continue;
            }
            else if (line.Contains("DEMAND_SECTION"))
            {
                state = TSPLibReaderState.DemandSection;
                continue;
            }
            else if (line.Contains("DEPOT_SECTION"))
            {
                state = TSPLibReaderState.DepotSection;
                continue;
            }
            else if (line.Contains("EDGE_WEIGHT_SECTION"))
            {
                model.D = new double[N, N];
                state   = TSPLibReaderState.WeightSection;
                continue;
            }

            string[] parts;
            switch (state)
            {
            case TSPLibReaderState.Header:
                if (line.Contains("CAPACITY"))
                {
                    parts          = line.Split(':');
                    model.capacity = Double.Parse(parts[1], CultureInfo.InvariantCulture);
                }
                if (line.Contains("NAME"))
                {
                    parts             = line.Split(':');
                    model.problemName = parts[1].Trim();
                    model.BKS_k       = Int32.Parse(problemName.Split('-').Last().Replace('k', ' '));
                }
                if (line.Contains("BEST_KNOWN"))
                {
                    parts         = line.Split(':');
                    model.BKS_val = Double.Parse(parts[1], CultureInfo.InvariantCulture);
                }
                if (line.Contains("EDGE_WEIGHT_TYPE"))
                {
                    parts       = line.Split(':');
                    weightStyle = parts[1].Trim();
                }
                if (line.Contains("EDGE_WEIGHT_FORMAT"))
                {
                    parts        = line.Split(':');
                    weightFormat = parts[1].Trim();

                    if (weightFormat == "LOWER_ROW")
                    {
                        yDIdx = 1;
                    }
                    else if (weightFormat == "UPPER_ROW")
                    {
                        xDIdx = 1;
                    }
                }
                if (line.Contains("DIMENSION"))
                {
                    parts = line.Split(':');
                    N     = Int32.Parse(parts[1]);
                }
                break;

            case TSPLibReaderState.CoordSection:
                parts = line.Trim().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

                if (weightStyle == "GEO")
                {
                    // id pos-x pos-y
                    model.points.Add(new Vector(
                                         Double.Parse(parts[2], CultureInfo.InvariantCulture),
                                         Double.Parse(parts[1], CultureInfo.InvariantCulture)));
                }
                else
                {
                    // id pos-x pos-y
                    model.points.Add(new Vector(
                                         Double.Parse(parts[1], CultureInfo.InvariantCulture),
                                         Double.Parse(parts[2], CultureInfo.InvariantCulture)));
                }

                break;

            case TSPLibReaderState.DemandSection:
                parts = line.Split(' ');
                int id = Int32.Parse(parts[0]);
                // one based indexing. first is the depot.
                if (id == 1)
                {
                    model.demands.Add(model.capacity);
                }
                else
                {
                    model.demands.Add(Double.Parse(parts[1], CultureInfo.InvariantCulture));
                }
                break;

            case TSPLibReaderState.WeightSection:
                var distances = line.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
                foreach (var dstr in distances)
                {
                    if (dstr == "")
                    {
                        continue;
                    }

                    double d = Double.Parse(dstr, CultureInfo.InvariantCulture);
                    model.D[xDIdx, yDIdx] = d;
                    model.D[yDIdx, xDIdx] = d;

                    if (weightFormat == "LOWER_ROW")
                    {
                        xDIdx += 1;
                        if (xDIdx == yDIdx)
                        {
                            yDIdx++;
                            xDIdx = 0;
                        }
                    }
                    else if (weightFormat == "UPPER_ROW")
                    {
                        xDIdx++;
                        if (xDIdx == N)
                        {
                            yDIdx++;
                            xDIdx = yDIdx + 1;
                        }
                    }
                    else if (weightFormat == "FULL_MATRIX")
                    {
                        xDIdx++;
                        if (xDIdx == N)
                        {
                            yDIdx++;
                            xDIdx = 0;
                        }
                    }
                    else if (weightFormat == "LOWER_DIAG_ROW")
                    {
                        xDIdx++;
                        if (xDIdx == yDIdx + 1)
                        {
                            xDIdx = 0;
                            yDIdx++;
                        }
                    }
                    else if (weightFormat == "UPPER_DIAG_ROW")
                    {
                        xDIdx++;
                        if (xDIdx == N)
                        {
                            yDIdx++;
                            xDIdx = yDIdx;
                        }
                    }
                }
                break;

            default:
                break;
            }
        }

        // Calculate D (instance matrix) if needed
        if (model.D == null)
        {
            model.D = new double[model.points.Count, model.points.Count];
            for (int i = 0; i < model.points.Count; i++)
            {
                for (int j = i; j < model.points.Count; j++)
                {
                    if (i == j)
                    {
                        model.D[i, j] = 0.0;
                    }
                    else
                    {
                        double d = -1.0;
                        if (weightStyle == "EUC_2D")
                        {
                            d = Math.Round(Math.Sqrt(                                                // rounded to nearest integer!
                                               Math.Pow(model.points[i].X - model.points[j].X, 2) +  // dx^2
                                               Math.Pow(model.points[i].Y - model.points[j].Y, 2))); // dy^2
                        }
                        else if (weightStyle == "GEO")
                        {
                            /* from http://stackoverflow.com/questions/4913349/
                             * Calculate the great circle distance between two points
                             * on the earth (specified in decimal degrees)
                             * The distance should be within ~0.3% of the correct value.*/
                            // convert decimal degrees to radians
                            double lon1 = (Math.PI / 180) * model.points[i].X;
                            double lat1 = (Math.PI / 180) * model.points[i].Y;
                            double lon2 = (Math.PI / 180) * model.points[j].X;
                            double lat2 = (Math.PI / 180) * model.points[j].Y;
                            // haversine formula
                            double dlon = lon2 - lon1;
                            double dlat = lat2 - lat1;
                            double a    = Math.Pow(Math.Sin(dlat / 2), 2) +
                                          Math.Cos(lat1) * Math.Cos(lat2) *
                                          Math.Pow(Math.Sin(dlon / 2), 2);
                            double c  = 2 * Math.Asin(Math.Sqrt(a));
                            double km = 6367 * c;
                            d = km;
                        }
                        model.D[i, j] = d;
                        model.D[j, i] = d;
                    }
                }
            }
        }


        // Scale to fill the screen
        double minX = model.points.Min((p) => p.X);
        double maxX = model.points.Max((p) => p.X);
        double minY = model.points.Min((p) => p.Y);
        double maxY = model.points.Max((p) => p.Y);

        double scale             = Math.Min(displayWidth / (maxX - minX), displayHeight / (maxY - minY));
        double displayLeftOffset = (maxX - minX) * scale / 2;
        double displayTopOffset  = (maxY - minY) * scale / 2;

        for (int i = 0; i < model.points.Count; i++)
        {
            Vector oldpt = model.points[i];
            Vector newpt = new Vector(
                (oldpt.X - minX) * scale - displayLeftOffset,
                (oldpt.Y - minY) * scale - displayTopOffset
                );
            model.points[i] = newpt;
        }

        // Init current solution data structures
        model.neighbourEdges = new List <List <GameObject> >();
        foreach (var p in model.points)
        {
            model.neighbourEdges.Add(new List <GameObject>());
        }
        model.solutionEdges    = new List <GameObject>(model.points.Count);
        model.routeIdxForNodes = Enumerable.Repeat(-1, model.points.Count).ToArray();

        return(model);
    }