Show / Hide Table of Contents

    Business Objects & Instantiation

    Visualization

    The image below visualizes the data created below. In this example we have six cities and nine edges.
    We want to open a cost optimal set of warehouses, while serving all customers cost optimal.

    Node (Business Object)

    Each node holds information about its name, demand/supply as well as its creation cost.
    Node.cs

    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace WLP
    {
        /// <summary>
        /// A node of the Warehouse Location Problem
        /// </summary>
        public class Node : INode
        {
            /// <summary>
            /// Initializes a new instance of the <see cref="Node"/> class, 
            /// representing a node of the Warehouse Location Problem
            /// </summary>
            /// <param name="name">
            /// Name of the node
            /// </param>
            /// <param name="demand">
            /// The demand of this node. A negative demand is supply. 
            /// </param>
            /// <param name="creationCost">
            /// The cost for opening this facility
            /// </param>
            public Node(string name, double demand, double creationCost)
            {
                this.Name = name;
                this.Demand = demand;
                this.CreationCost = creationCost;
            }
    
            /// <summary>
            /// Gets the creationCost of this node. 0 means it is not a facility.
            /// </summary>
            public double CreationCost { get; }
            /// <summary>
            /// Gets the demand of this node. A negative demand is supply. 
            /// </summary>
            public double Demand { get; }
    
            /// <summary>
            /// Gets the name of the node
            /// </summary>
            public string Name { get; }
    
            /// <summary>
            /// Name of the node
            /// </summary>
            /// <returns>
            /// The name of this node (<see cref="string"/>).
            /// </returns>
            public override string ToString() => this.Name;
    
        }
    }
    

    Edge (Business Object)

    Each edge connects exactly two nodes. It holds information about its maximum capacity and transportation cost.
    Edge.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace WLP
    {
        /// <summary>
        /// An edge between two nodes of the network. 
        /// </summary>
        public class Edge : IEdge
        {
            /// <summary>
            /// Initializes a new instance of the <see cref="Edge"/> class.
            /// </summary>
            /// <param name="fromNode">
            /// The departing node
            /// </param>
            /// <param name="toNode">
            /// The arrival node
            /// </param>
            /// <param name="capacity">
            /// The capacity of the edge
            /// </param>
            /// <param name="costPerFlowUnit">
            /// The cost per flow unit
            /// </param>
            public Edge(INode fromNode, INode toNode, double capacity, double costPerFlowUnit)
            {
                // set the parameter information
                this.FromNode = fromNode;
                this.ToNode = toNode;
                this.Capacity = capacity;
                this.CostPerFlowUnit = costPerFlowUnit;
            }
    
            /// <summary>
            /// Gets the cost per flow unit on this edge
            /// </summary>
            public double CostPerFlowUnit { get; }
    
            /// <summary>
            /// Gets the capacity of the edge
            /// </summary>
            public double Capacity { get; }
    
            /// <summary>
            /// Gets the end node of the edge
            /// </summary>
            public INode ToNode { get; }
    
            /// <summary>
            /// Gets the start node of the edge
            /// </summary>
            public INode FromNode { get; }
    
            /// <summary>
            /// Gets or sets a value indicating whether the edge is used in the solution
            /// </summary>
            public bool IsUsed { get; set; }
    
            /// <summary>
            /// Gets or sets the flow of the optimal solution
            /// </summary>
            public double Flow { get; set; }
    
            /// <summary>
            /// Name of the edge
            /// </summary>
            /// <returns>
            /// The <see cref="string"/>.
            /// </returns>
            public override string ToString() => $"Edge {this.FromNode} to {this.ToNode}";
           
        }
    }
    

    Program instance

    Instantiation of the different Nodes and Edges, the Model, as well as the Solver and an empty Solution.
    Program.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace WLP
    {
        using OPTANO.Modeling.Common;
        using OPTANO.Modeling.Optimization;
        using OPTANO.Modeling.Optimization.Configuration;
        using OPTANO.Modeling.Optimization.Solver.Gurobi810;
    
        /// <summary>
        /// Demo program solving a Warehouse Location Problem
        /// </summary>
        class Program
        {
            /// <summary>
            /// The main method
            /// </summary>
            /// <param name="args">
            /// no arguments required
            /// </param>
            static void Main(string[] args)
            {
    
                INode pb = new Node("Paderborn", -100, 1000000);
                INode ny = new Node("New York", -200, 1750000);
                INode b = new Node("Beijing", -100, 750000);
                INode sp = new Node("São Paulo", 100, 0);
                INode sf = new Node("San Francisco", 100, 0);
                INode mo = new Node("Moscow", 100, 0);
                var nodes = new List<INode> { pb, ny, b, sp, sf, mo };
    
                var edges = new List<IEdge>
                                {
                                    new Edge(pb, sp, 100, 9900),
                                    new Edge(pb, sf, 100, 9500),
                                    new Edge(pb, mo, 100, 1900),
                                    new Edge(ny, sp, 100, 7600),
                                    new Edge(ny, sf, 100, 4100),
                                    new Edge(ny, mo, 100, 7500),
                                    new Edge(b, sp, 100, 17500),
                                    new Edge(b, sf, 100, 9500),
                                    new Edge(b, mo, 100, 5800)
                                };
    
                // Use long names for easier debugging/model understanding.
                var config = new Configuration();
                config.NameHandling = NameHandlingStyle.UniqueLongNames;
                config.ComputeRemovedVariables = true;
                using (var scope = new ModelScope(config))
                {
                    // create a model, based on given data and the model scope
                    var warehouseModel = new WarehouseLocationModel(nodes, edges);
    
                    // Get a solver instance, change your solver
                    using (var solver = new GurobiSolver())
                    {
                        // solve the model
                        var solution = solver.Solve(warehouseModel.Model);
    
                        // import the results back into the model 
                        warehouseModel.Model.VariableCollections.ForEach(vc => vc.SetVariableValues(solution.VariableValues));
    
                        // print objective and variable decisions
                        Console.WriteLine($"{solution.ObjectiveValues.Single()}");
                        warehouseModel.x.Variables.ForEach(x => Console.WriteLine($"{x.ToString().PadRight(36)}: {x.Value}"));
                        warehouseModel.y.Variables.ForEach(y => Console.WriteLine($"{y.ToString().PadRight(36)}: {y.Value}"));
    
                        warehouseModel.Model.VariableStatistics.WriteCSV(AppDomain.CurrentDomain.BaseDirectory);
                        Console.ReadLine();
                    }
                }
            }
        }
    }
    

    Next Step

    • Creating the Model
    Back to top Copyright © OPTANO GmbH generated with DocFX
    Privacy Policy | Impressum – Legal Notice