Exemplo n.º 1
0
    public void Run()
    {
        var api = new ApiHelper <Tsp.SolveRequest, Tsp.SolutionResponse>("tsp-mcvfz472gty6", configFile);

        // so here we're going to build the model

        // create a solve request
        Tsp.SolveRequest sr = new Tsp.SolveRequest();

        sr.Model = new Tsp.Tsp(); // initialise the model container

        // add points to the tsp model
        foreach (var d in data)
        {
            sr.Model.Points.Add(new Tsp.Geocode
            {
                Id = d.id,
                X  = d.X,
                Y  = d.Y
            });
        }

        // configure the distance metric (although road network is the default)
        sr.Model.Distancetype = Tsp.Tsp.eDistanceType.RoadNetwork;

        string requestId = api.Post(sr); // send the model to the api

        Solution = api.Get(requestId);   // get the response (which it typed, so that's cool)

        // lets pull out the total distance
        lineString ls            = new lineString();
        double     totalDistance = 0.0;

        foreach (var e in Solution.Edges)
        {
            totalDistance += e.Distance;
            foreach (var g in e.Geometries)
            {
                ls.Add(new double[2] {
                    g.X, g.Y
                });
            }
        }
        System.Console.WriteLine(string.Format("Total distance: {0:0.00} km\t Stops: " + Solution.Tours.Count, totalDistance));

        // just for fun - you wouldn't ever plot things this way - but it is nice to see the line segments
        new consolePlot(new List <lineString> {
            ls
        });

        return;
    }
Exemplo n.º 2
0
    public void Run()
    {
        var api = new ApiHelper <Cvrptw.SolveRequest, Cvrptw.SolutionResponse>("cvrptw-acyas3nzweqb", configFile);

        // so here we're going to build the model

        // create a solve request
        Cvrptw.SolveRequest sr = new Cvrptw.SolveRequest();

        sr.Model = new Cvrptw.Cvrptw(); // initialise the model container

        // add the depot (first point) in the model
        for (int i = 0; i < data.Count; i++)
        {
            if (i == 0)
            {
                sr.Model.Depot = new Cvrptw.Geocode
                {
                    Id       = data[i].id,
                    X        = (float)data[i].X,
                    Y        = (float)data[i].Y,
                    Quantity = (float)0.0
                }; // this adds the depot to the model
            }
            else
            {
                // add the points as demand points. Assume that each point has a demand quantity of 20
                // lets randomly split the windows into "morning" and "afternoon" windows
                // note that the windows are measured in minutes in this schema.

                sr.Model.Points.Add(new Cvrptw.Geocode
                {
                    Id          = data[i].id,
                    X           = (float)data[i].X,
                    Y           = (float)data[i].Y,
                    windowStart = i % 2 == 0 ? (float)(8 * 60) : (float)(12 * 60),
                    windowEnd   = i % 2 == 0 ? (float)(12 * 60) : (float)(16 * 60),
                    Quantity    = (float)20
                });
            }
        }

        // configure the distance metric (although road network is the default)
        sr.Model.Distancetype     = Cvrptw.Cvrptw.eDistanceType.RoadNetwork;
        sr.Model.VehicleCapacity  = 100; // set a vehicle capacity of 100
        sr.Model.NumberOfVehicles = 3;   // allow the use of at-most, three vehicles


        string requestId = api.Post(sr); // send the model to the api

        Solution = api.Get(requestId);   // get the response (which it typed, so that's cool)

        // lets pull out the total distance
        lineString ls            = new lineString();
        double     totalDistance = 0.0;
        int        stopCount     = 0;

        foreach (var r in Solution.Routes)
        {
            stopCount += r.Sequences.Count;
            foreach (var e in r.Edges)
            {
                totalDistance += e.Distance;
            }
        }
        Console.WriteLine(string.Format("Total Cost: {0:0.00} \t ", Solution.Objective));
        Console.WriteLine(string.Format("Total distance: {0:0.00} km\t Stops: " + stopCount, totalDistance));

        foreach (var r in Solution.Routes)
        {
            if (r.Sequences.Count > 0)
            {
                Console.WriteLine("Route: ");
                int    stopc = 1;
                double vCap  = 0.0;
                for (int i = 0; i < r.Sequences.Count; i++)
                {
                    vCap += r.visitCapacities[i];
                    Console.WriteLine("  stop " + stopc + ": " + (int)(vCap) + ", " + r.Sequences[i] + ", " + r.arrivalTimes[i]);
                    stopc++;
                }
            }
        }
        // the cumulative quantity assigned to each route is <= 100.

        return;
    }
Exemplo n.º 3
0
    public static void printSolution(Ns3.SolutionResponse resp, Ns3.SolveRequest sr)
    {
        // we're just going to show the first 5 items from each table that one can construct here.
        // we also give an illustration of how to construct the geometries in this context.

        //assignment table.
        int[] maxchar = new int[] { "Lane Rate".Length, "Cost Model".Length, "Source".Length,
                                    "Destination".Length, "Product".Length, "Amount".Length, "Cost".Length, "Distance".Length, "Duration".Length };
        foreach (var a in resp.Assignments)
        {
            maxchar[0] = Math.Max(maxchar[0], a.laneRateId.Length);
            maxchar[1] = Math.Max(maxchar[1], a.costModelId.Length);
            maxchar[2] = Math.Max(maxchar[2], a.Source.Length);
            maxchar[3] = Math.Max(maxchar[3], a.Destination.Length);
            maxchar[4] = Math.Max(maxchar[4], a.productId.Length);
            //a.Amount
            //a.Cost
            //a.Distance
            //a.Duration
        }
        Console.WriteLine("Assignments:");
        string formatLine = "|{0,-" + maxchar[0] + "}|{1,-" + maxchar[1] + "}|{2,-" + maxchar[2] + "}|{3,-" +
                            maxchar[3] + "}|{4,-" + maxchar[4] + "}|{5,10}|{6,10}|{7,10}|{8,10}|";

        Console.WriteLine(String.Format(formatLine, "Lane Rate", "Cost Model", "Source", "Destination", "Product", "Amount", "Cost", "Distance", "Duration"));
        int maxprint = 0;

        foreach (var a in resp.Assignments)
        {
            Console.WriteLine(String.Format(formatLine, a.laneRateId, a.costModelId, a.Source, a.Destination, a.productId,
                                            string.Format("{0:0.00}", a.Amount),
                                            string.Format("{0:0.00}", a.Cost),
                                            string.Format("{0:0.00}", a.Distance),
                                            string.Format("{0:0.00}", a.Duration)));
            maxprint++;
            if (maxprint > 10)
            {
                Console.WriteLine("table truncated...");
                maxprint = 0;
                break;
            }
        }
        Console.WriteLine("");

        Console.WriteLine("Node Flow:");
        maxchar[0] = "NodeId".Length;

        foreach (var nf in resp.nodeFlows)
        {
            maxchar[0] = Math.Max(maxchar[0], nf.nodeId.Length);
        }

        formatLine = "|{0,-" + maxchar[0] + "}|{1,10}|{2,10}|{3,10}|{4,10}|{5," + "ProductFixedCost".Length + "}|{6," +
                     "ProductFlowCost".Length + "}|{7,10}|{8,10}|{9,10}|{10,10}|{11,10}|{12,10}|";
        Console.WriteLine(String.Format(formatLine, "NodeId", "InFlow", "OutFlow", "FixedCost", "FlowCost",
                                        "ProductFixedCost", "ProductFlowCost", "P-Amount", "P-Cost", "P-Penalty", "C-Amount", "C-Cost", "C-Penalty"));

        foreach (var nf in resp.nodeFlows)
        {
            Console.WriteLine(String.Format(formatLine, nf.nodeId,
                                            string.Format("{0:0.00}", nf.inFlow),
                                            string.Format("{0:0.00}", nf.outFlow),
                                            string.Format("{0:0.00}", nf.fixedCost),
                                            string.Format("{0:0.00}", nf.flowCost),
                                            string.Format("{0:0.00}", nf.productFixedCost),
                                            string.Format("{0:0.00}", nf.productFlowCost),
                                            string.Format("{0:0.00}", nf.productionAmount),
                                            string.Format("{0:0.00}", nf.productionCost),
                                            string.Format("{0:0.00}", nf.productionPenalty),
                                            string.Format("{0:0.00}", nf.consumptionAmount),
                                            string.Format("{0:0.00}", nf.consumptionCost),
                                            string.Format("{0:0.00}", nf.consumptionPenalty)));
            maxprint++;
            if (maxprint > 10)
            {
                Console.WriteLine("table truncated...");
                maxprint = 0;
                break;
            }
        }
        Console.WriteLine("");

        Console.WriteLine("Node Product Flow:");
        maxchar[0] = "NodeId".Length;
        maxchar[1] = "ProductId".Length;

        foreach (var nf in resp.nodeFlows)
        {
            maxchar[0] = Math.Max(maxchar[0], nf.nodeId.Length);
        }

        formatLine = "|{0,-" + maxchar[0] + "}|{1,-" + maxchar[1] + "}|{2,10}|{3,10}|{4,10}|{5,10}|{6,10}|{7,10}|{8,10}|{9,10}|{10,10}|{11,10}|";
        Console.WriteLine(String.Format(formatLine, "NodeId", "ProductId", "InFlow", "OutFlow", "FixedCost", "FlowCost",
                                        "P-Amount", "P-Cost", "P-Penalty", "C-Amount", "C-Cost", "C-Penalty"));

        foreach (var nf in resp.nodeProductFlows)
        {
            Console.WriteLine(String.Format(formatLine, nf.nodeId, nf.productId,
                                            string.Format("{0:0.00}", nf.inFlow),
                                            string.Format("{0:0.00}", nf.outFlow),
                                            string.Format("{0:0.00}", nf.fixedCost),
                                            string.Format("{0:0.00}", nf.flowCost),
                                            string.Format("{0:0.00}", nf.productionAmount),
                                            string.Format("{0:0.00}", nf.productionCost),
                                            string.Format("{0:0.00}", nf.productionPenalty),
                                            string.Format("{0:0.00}", nf.consumptionAmount),
                                            string.Format("{0:0.00}", nf.consumptionCost),
                                            string.Format("{0:0.00}", nf.consumptionPenalty)));
            maxprint++;
            if (maxprint > 10)
            {
                Console.WriteLine("table truncated...");
                maxprint = 0;
                break;
            }
        }


        // lets unpack the geometries for each of the "routes"
        List <lineString> routeData = new List <lineString>();

        foreach (var r in resp.Routes)
        {
            lineString ls = new lineString();
            foreach (var i in r.geometrySequences)
            {
                for (int j = 0; j < resp.geometrySequences[i].X.Length; j++)
                {
                    ls.Add(new double[2] {
                        resp.geometrySequences[i].X[j], resp.geometrySequences[i].Y[j]
                    });
                }
            }
            routeData.Add(ls);
        }
        var cplot = new consolePlot(routeData);
    }
Exemplo n.º 4
0
    public void Run()
    {
        var api = new ApiHelper <Tsptw.SolveRequest, Tsptw.SolutionResponse>("tsptw-kcxbievqo879", configFile);

        // so here we're going to build the model

        // create a solve request
        Tsptw.SolveRequest sr = new Tsptw.SolveRequest();

        sr.Model = new Tsptw.Tsp(); // initialise the model container

        Random rand = new Random();

        // add points to the tsp model
        foreach (var d in data)
        {
            // lets randomly create a window here.
            double rupper = 2500;
            double ws     = rand.NextDouble() * rupper;
            double we     = ws + rupper; //we don't accept backwards windows, so we'll just set these to some positive width upper amount.
            sr.Model.Points.Add(new Tsptw.Geocode
            {
                Id          = d.id,
                X           = d.X,
                Y           = d.Y,
                windowStart = (float)ws,
                windowEnd   = (float)we,
            });
        }

        // configure the distance metric (although road network is the default)
        sr.Model.Distancetype = Tsptw.Tsp.eDistanceType.RoadNetwork;

        string requestId = api.Post(sr); // send the model to the api

        Solution = api.Get(requestId);   // get the response (which it typed, so that's cool)

        // lets pull out the total distance
        lineString ls            = new lineString();
        double     totalDistance = 0.0;

        foreach (var e in Solution.Edges)
        {
            totalDistance += e.Distance;
            foreach (var g in e.Geometries)
            {
                ls.Add(new double[2] {
                    g.X, g.Y
                });
            }
        }
        Console.WriteLine(string.Format("Total distance: {0:0.00} km\t Stops: " + Solution.Tours.Count, totalDistance));
        int maxchar = 0;

        foreach (var d in data)
        {
            maxchar = Math.Max(d.id.Length, maxchar); // so that the table displays nicely in the console :-)
        }
        string formatLine = "|{0,-" + maxchar + "}|{1,11}|";

        Console.WriteLine(String.Format(formatLine, "Location", "ArrivalTime"));
        for (int i = 0; i < Solution.arrivalTimes.Length; i++)
        {
            Console.WriteLine(String.Format(formatLine, Solution.Tours[i], Solution.arrivalTimes[i]));
        }
        // just for fun - you wouldn't ever plot things this way - but it is nice to "see" the line segments
        Console.WriteLine("Approximate Tour Map:");
        new consolePlot(new List <lineString> {
            ls
        });

        return;
    }
Exemplo n.º 5
0
    public void Run()
    {
        var api = new ApiHelper <Ivr7.SolveRequest, Ivr7.SolutionResponse>("ivr7-kt461v8eoaif", configFile);

        // so here we're going to build the model

        // create a solve request
        Ivr7.SolveRequest sr = new Ivr7.SolveRequest();

        sr.Model = new Ivr7.Model(); // initialise the model container

        // the first decision we have to make is which dimensional quantities to model in this example.
        // we're going to model the distance, time, and capacity of the vehicle.
        ivr7helper.makeDistanceTimeCapDims(sr.Model); // adds distance, time & capacity

        // lets pretend the first point is where vehicles are going to begin and end each day.
        // unlike the tsp/cvrp/pdp models, the ivr7 requires that you specify the unique locations
        // that are going to be used in the model as a separate entity. The reason for this is that you
        // can then specify the locations once, and reference those locations by id for other entities (such and vehicles/jobs/tasks)
        ivr7helper.makeLocations(sr.Model, data); // adds all the locations to the model

        // so we've constructed some jobs with pickups and dropoffs, loading and offload times, as well as the
        // contribution to the capacity dimension. In this example, we're pickup up all orders at the guiness storehouse
        // and delivering at the list of customers. 'make_job_time_cap' is just a simple function to create this
        // particular style of request, but you can make your own.
        ivr7helper.makeJobTimeCap(sr.Model, data, ivr7helper.Rep(0, data.Count - 1), ivr7helper.Seq(1, data.Count));


        // we're going to do the vehicle-configuration now.
        // we need to specify the cost classes available, the vehicle classes available, and then the individual vehicles.
        // we're going to create one of each to keep things simple.
        sr.Model.vehicleCostClasses.Add(ivr7helper.makeVccSimple("vcc1", 1000, 0.01f, 0.01f, 0.01f, 1, 3));


        // lets make the vehicle class. A vehicle class describes how the vehicle MOVES through the network.
        // so in other words, we can use the standard network travel speeds, or we could make the vehicle
        // move slower/faster relative to the road network. We could also attach transit rules here which are
        // great for modelling lunch breaks, refueling stops etc. (i.e. conditional triggers on the cumul values
        // of the dimension). Covered in an advanced section.
        sr.Model.vehicleClasses.Add(ivr7helper.makeVcSimple("vc1", 1, 1, 1, 1));

        // now we can just specify the vehicles.
        // lets provide 2 x 2 ton vehicles. Although this is probably more than we need.
        // the reason for this is that we're modelling a full-blown pickup+dropoff model, so if there's
        // time to reload, a vehicle can return to the depot and grab more goodies!
        for (int i = 0; i < 2; i++)
        {
            sr.Model.Vehicles.Add(ivr7helper.makeVehicleCap("vehicle_" + i, // unique id for the vehicle.
                                                            "vc1",          // the vehicle class
                                                            "vcc1",         // the vehicle cost class
                                                            2000,           // the capacity of the vehicle
                                                            data[0].id,     // start location for the vehicle
                                                            data[0].id,     // end location for the vehicle
                                                            7 * 60,         // start time: 7 AM
                                                            18 * 60         // end time: 6 PM
                                                            ));
        }

        sr.solveType = Ivr7.SolveRequest.SolveType.Optimise; // Optimise the solve request.

        // now it's just sending the model to the api

        string requestId = api.Post(sr); // send the model to the api

        Solution = api.Get(requestId);   // get the response (which it typed, so that's cool)

        // lets pull out the total distance
        lineString ls            = new lineString();
        double     totalDistance = 0.0;
        int        stopCount     = 0;

        foreach (var r in Solution.Routes)
        {
            foreach (var e in r.interStops)
            {
                foreach (var a in e.Attributes)
                {
                    if (a.dimId == "distance")
                    {
                        totalDistance += (a.endValue - a.startValue); // the difference between the start and end value
                    }
                }
                foreach (var g in e.routeSegments)
                {
                    ls.Add(new double[] { g.Longitude, g.Latitude }); // these are the road-network edges if you want to visualise the route in
                                                                      //leaflet or on a map.
                }
            }
        }
        Console.WriteLine(string.Format("Total Cost: {0:0.00} \t ", Solution.Objective));
        Console.WriteLine(string.Format("Total distance: {0:0.00} km\t Stops: " + stopCount, totalDistance));

        ivr7helper.printSolution(Solution);
        // the maximum quantity assigned to each vehicle is <= 2000 (the capacity dimension).
        // the majority of the cost is coming in the distance dimension (because of the way we've configured the vehicle cost class)

        // for visualisations see the R/python notebook for plots on the same example.

        return;
    }
Exemplo n.º 6
0
    public void Run()
    {
        var api = new ApiHelper <Ivr7.SolveRequest, Ivr7.SolutionResponse>("ivr7-kt461v8eoaif", configFile);

        // so here we're going to build the model

        // create a solve request
        Ivr7.SolveRequest sr = new Ivr7.SolveRequest();

        sr.Model = new Ivr7.Model(); // initialise the model container

        // we're going to reuse the helpers described in the ivr7basic example. Please see that for a reference.

        ivr7helper.makeDistanceTimeCapDims(sr.Model); // adds distance, time & capacity
        ivr7helper.makeLocations(sr.Model, data);     // adds all the locations to the model

        // we're going to add time windows to the locations. 08:00 - 14:00
        foreach (var l in sr.Model.Locations)
        {
            var a = new Ivr7.Location.Attribute()
            {
                dimensionId    = "time",
                arrivalWindows = { new Ivr7.Window {
                                       Start = 8 * 60,
                                       End   = 14 * 60
                                   } }
            };
            l.Attributes.Add(a);
        }

        ivr7helper.makeJobTimeCap(sr.Model, data, ivr7helper.Rep(0, data.Count - 1), ivr7helper.Seq(1, data.Count));
        // Two vehicle cost classes, one which is cheaper on time, one which is cheaper on distance, one
        // which is more expensive if used (1000 vs 1200).
        sr.Model.vehicleCostClasses.Add(ivr7helper.makeVccSimple("vcc1", 1000, 0.01f, 0.01f, 0.01f, 1, 3));
        sr.Model.vehicleCostClasses.Add(ivr7helper.makeVccSimple("vcc2", 1200, 0.1f, 0.1f, 0.1f, 0.6f, 2.5f));

        sr.Model.vehicleClasses.Add(ivr7helper.makeVcSimple("vc1", 1, 1, 1, 1));

        // now we can just specify the vehicles.
        // lets provide 2 x 2 ton vehicles and 2 x 3 ton vehicles. Although this is probably more than we need.
        // the reason for this is that we're modelling a full-blown pickup+dropoff model, so if there's
        // time to reload, a vehicle can return to the depot and grab more goodies!

        for (int i = 0; i < 4; i++)
        {
            string vcc = "vcc1";
            float  cap = 2000;
            if (i > 1)
            {
                vcc = "vcc2";
                cap = 3000;
            }
            sr.Model.Vehicles.Add(ivr7helper.makeVehicleCap("vehicle_" + i, // unique id for the vehicle.
                                                            "vc1",          // the vehicle class
                                                            vcc,            // the vehicle cost class
                                                            cap,            // the capacity of the vehicle
                                                            data[0].id,     // start location for the vehicle
                                                            data[0].id,     // end location for the vehicle
                                                            7 * 60,         // start time: 7 AM
                                                            18 * 60         // end time: 6 PM
                                                            ));
        }

        // Lunch breaks.
        // so this is a touch more complex, we want to link our transit-rule to the time
        // dimension, and when a certain amount has accumulated on the dimension, we trigger the rule.
        sr.Model.transitRules.Add(ivr7helper.makeLunchBreakRule("lunch_break_rule", "lunchy_munchy_", 12 * 60, 60));

        // now link the transit rule to the vehicle classes
        sr.Model.vehicleClasses[0].transitRuleIds.Add("lunch_break_rule");

        sr.solveType = Ivr7.SolveRequest.SolveType.Optimise; // Optimise the solve request.

        // now it's just sending the model to the api

        string requestId = api.Post(sr); // send the model to the api

        Solution = api.Get(requestId);   // get the response (which it typed, so that's cool)

        // lets pull out the total distance
        lineString ls            = new lineString();
        double     totalDistance = 0.0;
        int        stopCount     = 0;

        foreach (var r in Solution.Routes)
        {
            foreach (var e in r.interStops)
            {
                foreach (var a in e.Attributes)
                {
                    if (a.dimId == "distance")
                    {
                        totalDistance += (a.endValue - a.startValue); // the difference between the start and end value
                    }
                }
                foreach (var g in e.routeSegments)
                {
                    ls.Add(new double[] { g.Longitude, g.Latitude }); // these are the road-network edges if you want to visualise the route in
                                                                      //leaflet or on a map.
                }
            }
        }
        Console.WriteLine(string.Format("Total Cost: {0:0.00} \t ", Solution.Objective));
        Console.WriteLine(string.Format("Total distance: {0:0.00} km\t Stops: " + stopCount, totalDistance));

        ivr7helper.printSolution(Solution);
        // the maximum quantity assigned to each vehicle is <= 2000 (the capacity dimension).
        // the majority of the cost is coming in the distance dimension (because of the way we've configured the vehicle cost class)

        // for visualisations see the R/python notebook for plots on the same example.

        return;
    }