public void Run()
    {
        var api = new ApiHelper <Ns3.SolveRequest, Ns3.SolutionResponse>("ns3-tbfvuwtge2iq", configFile);

        // so here we're going to build the model
        var m = new Ns3.Model();

        m.Dimensions = ns3helper.make_distance_time_user_dimensions("weight");

        var productionNodes = data.Where(q => q.quanity == -1).ToList();
        var warehouseNodes  = data.Where(q => q.quanity == -2).ToList();
        var demandNodes     = data.Where(q => q.quanity > 0).ToList();

        var p_nodes = ns3helper.make_nodes(productionNodes);
        var w_nodes = ns3helper.make_nodes(warehouseNodes);
        var d_nodes = ns3helper.make_nodes(demandNodes);

        // lets assume we can go factory-direct or through a warehouse!
        var sources = data.Where(q => q.quanity < 0).Select(t => t.id).ToList();


        // lets continue to make some alterations.
        // we know that demand nodes require us to fulfill the demand at the node.
        // lets assume we have no production constraints

        // we have a reasonably even demand profile - something tells us this data-set is not real! :-)
        // demandNodes$demand %>% hist
        // in order to specify which demands we should satisfy, lets place a flow requirement at each node.
        for (int i = 0; i < d_nodes.Count; i++)
        {
            // each demand node must have the quantity demand[i] delivered, so the range here
            // is actually [demand[i], demand[i]].
            // Not meeting this range incurs a large penalty cost.
            d_nodes[i].Consumptions.Add(
                new Ns3.Node.ProductFlow
            {
                productId       = "Beer",
                dimensionRanges = { ns3helper.make_dimension_range("weight", demandNodes[i].quanity, demandNodes[i].quanity) }
            }
                );
            d_nodes[i].allowableSources.AddRange(sources); // all sources are allowable
        }

        for (int i = 0; i < p_nodes.Count; i++)
        {
            // the production node has no limit on the amount that can be produced.
            // so we can simply set the upper bound to the sum of all demand, i.e. [0, sum(demands)]
            // this way we know that the facility can produce enough to satisfy all the demand
            p_nodes[i].Productions.Add(
                new Ns3.Node.ProductFlow
            {
                productId       = "Beer",
                dimensionRanges = { ns3helper.make_dimension_range("weight", 0, demandNodes.Sum(t => t.quanity)) }
            }
                );
            p_nodes[i].Productions[0].dimensionRanges[0].flowPenalty = 0;
        }

        m.Nodes.AddRange(p_nodes);
        m.Nodes.AddRange(w_nodes);
        m.Nodes.AddRange(d_nodes);

        // so  Guiness Storehouse -> Limerick
        // and Guinnes Storehouse -> Galway
        // each costed at 0.1 monetary units per km.
        m.laneRates.Add(ns3helper.make_lane_rate_distance(sources[0], sources[1], 0.1f));
        m.laneRates.Add(ns3helper.make_lane_rate_distance(sources[0], sources[2], 0.1f));

        m.productGroups.Add(ns3helper.make_single_product_group("Beer"));

        for (int i = 0; i < sources.Count; i++)
        {
            m.costModels.Add(ns3helper.make_cost_model_distance(sources[i], 0.2f));
        }

        Ns3.SolveRequest sr = new Ns3.SolveRequest
        {
            Model          = m,
            geometryOutput = Ns3.SolveRequest.GeometryOutput.Aggregate,
            solveType      = Ns3.SolveRequest.SolveType.Optimise
        };


        // 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)

        ns3helper.printSolution(Solution, sr);

        // for nice visualisations see the R/python notebook for the same example.
        return;
    }
示例#2
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);
    }