Show / Hide Table of Contents

    Business Objects & Instantiation

    Node (Business Object)

    For convenience we use an implementation with nodes and edges even if the nodes only have a name.
    Node.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace NDP
    {
        /// <summary>
        /// A node of the network
        /// </summary>
        public class Node : INode
        {
            /// <summary>
            /// Initializes a new instance of the <see cref="Node"/> class, representing a node of the network
            /// </summary>
            /// <param name="name">
            /// Name of the node
            /// </param>
            /// <param name="demand">
            /// The demand of this node. A negative demand is supply. 
            /// </param>
            public Node(string name, double demand)
            {
                this.Name = name;
                this.Demand = demand;
            }
    
            /// <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 and has a set distance.
    Edge.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace NDP
    {
        /// <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>
            /// <param name="designCost">
            /// The design cost, applied if the edge is used at all.
            /// </param>
            public Edge(INode fromNode, INode toNode, double? capacity, double costPerFlowUnit, double designCost)
            {
                // set the parameter information
                this.FromNode = fromNode;
                this.ToNode = toNode;
                this.Capacity = capacity;
                this.CostPerFlowUnit = costPerFlowUnit;
                this.DesignCost = designCost;
            }
    
            /// <summary>
            /// Gets the design cost of this edge, which are applied if the edge is used at all. 
            /// </summary>
            public double DesignCost { get; }
    
            /// <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;
    using OPTANO.Modeling.Optimization.Solver.Gurobi810;
    
    namespace NDP
    {
        using OPTANO.Modeling.Common;
        using OPTANO.Modeling.Optimization;
        using OPTANO.Modeling.Optimization.Configuration;
        using OPTANO.Modeling.Optimization.Solver.Gurobi810;
    
        /// <summary>
        /// Demo program solving a network design problem
        /// </summary>
        class Program
        {
            /// <summary>
            /// The main method
            /// </summary>
            /// <param name="args">
            /// no arguments required
            /// </param>
            static void Main(string[] args)
            {
    
                // create example Nodes
                INode pb = new Node("Paderborn", 50);
                INode ny = new Node("New York", -100);
                INode b = new Node("Beijing", 50);
                INode sp = new Node("São Paulo", 50);
                INode sf = new Node("San Francisco", -50);
                // assign these nodes to a list of INodes
                var nodes = new List<INode> { pb, ny, b, sp, sf };
    
                // create example Edges
                IEdge one = new Edge(ny, pb, null, 3, 6100);
                IEdge two = new Edge(b, ny, null, 2, 11000);
                IEdge three = new Edge(sp, b, 75, 1, 17600);
                IEdge four = new Edge(sf, sp, null, 4, 10500);
                IEdge five = new Edge(sp, pb, null, 5, 9900);
                IEdge six = new Edge(pb, b, 50, 1, 7600);
    
                // assign these edges to a list of IEdges
                var edges = new List<IEdge> { one, two, three, four, five, six };
    
                // 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 designModel = new NetworkDesignModel(nodes, edges);
    
                    // Get a solver instance, change your solver
                    using (var solver = new GurobiSolver())
                    {
                        // solve the model
                        var solution = solver.Solve(designModel.Model);
    
                        // import the results back into the model 
                        designModel.Model.VariableCollections.ForEach(vc => vc.SetVariableValues(solution.VariableValues));
    
                        // print objective and variable decisions
                        Console.WriteLine($"{solution.ObjectiveValues.Single()}");
                        designModel.x.Variables.ForEach(x => Console.WriteLine($"{x.ToString().PadRight(36)}: {x.Value}"));
                        designModel.y.Variables.ForEach(y => Console.WriteLine($"{y.ToString().PadRight(36)}: {y.Value}"));
    
                        designModel.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