Network Capacity and Routing Optimization Implementation

Algorithm Implementation: executeAlgorithm

This method executes the core network optimization algorithm, setting up the problem, defining constraints, and applying the resulting routing and capacity plan to the NetPlan object.

Method Signature

public String executeAlgorithm(NetPlan netPlan, Map<String, String> algorithmParameters, Map<String, String> net2planParameters)
{

Parameter Initialization

The algorithm first parses the required input parameters, defining key constraints and costs:

final double maximumLinkCapacity = Double.parseDouble(algorithmParameters.get("maximumLinkCapacity")); 
final double capacityModule = Double.parseDouble(algorithmParameters.get("capacityModule")); 
final double costPerGbps = Double.parseDouble(algorithmParameters.get("costPerGbps")); 
final double costPerKm = Double.parseDouble(algorithmParameters.get("costPerKm")); 

netPlan.removeAllLinks();
netPlan.setRoutingType(RoutingType.SOURCE_ROUTING);

Network Setup: Full Mesh Creation

A full mesh of potential links is created between all nodes, initially with zero capacity. This ensures all possible connections are considered by the optimization solver.

/* Create a full-mesh of links between all nodes, of capacity 0 */
for (Node n1 : netPlan.getNodes())
    for (Node n2 : netPlan.getNodes())
        if (n1 != n2)
            netPlan.addLink(n1, n2, 0, netPlan.getNodePairEuclideanDistance(n1, n2), 200000, null);

final int D = netPlan.getNumberOfDemands();
final int Efm = netPlan.getNumberOfLinks();

Optimization Problem Definition

An OptimizationProblem object is instantiated to define the Mixed Integer Linear Program (MILP) structure.

OptimizationProblem op = new OptimizationProblem();

Decision Variables

Three sets of decision variables are defined:

  • x_de: Continuous variable representing the traffic flow of demand d carried over link e.
  • a_e: Integer variable representing the number of capacity modules installed on link e.
  • z_e: Binary variable indicating if link e is active (has capacity installed).
op.addDecisionVariable("x_de", false, new int[] {D, Efm}, 0, Double.MAX_VALUE);
op.addDecisionVariable("a_e", true, new int[] {1, Efm}, 0, maximumLinkCapacity / capacityModule);
op.addDecisionVariable("z_e", true, new int[] {1, Efm}, 0, 1);

Input Parameters and Objective Function

Input parameters are set, including link lengths and cost factors. The objective is to minimize total cost, which includes both distance-based costs (for active links) and capacity installation costs.

op.setInputParameter("d_e", netPlan.getVectorLinkLengthInKm(), "row");
op.setInputParameter("c_km", costPerKm);
op.setInputParameter("c_Gbps", costPerGbps);
op.setInputParameter("C", capacityModule);
op.setInputParameter("U", maximumLinkCapacity);

op.setObjectiveFunction("minimize", "c_km * d_e * z_e' + c_Gbps * C * sum(a_e)");

Constraints

Capacity Activation Constraint

Ensures that capacity C * a_e(e) is only installed if the link is active (z_e(e) = 1), bounded by the maximum capacity U.

for (Link e : netPlan.getLinks())
{
    op.setInputParameter("e", e.getIndex());
    op.addConstraint("C * a_e(e) <= U * z_e(e)");
}
Flow Conservation Constraints

Standard flow conservation constraints applied per node and per demand:

for (Node n : netPlan.getNodes())
{
    op.setInputParameter("deltaPlus", NetPlan.getIndexes(n.getOutgoingLinks()), "row");
    op.setInputParameter("deltaMinus", NetPlan.getIndexes(n.getIncomingLinks()), "row");
    
    for (Demand d : netPlan.getDemands())
    {
        op.setInputParameter("d", d.getIndex());
        op.setInputParameter("h_d", d.getOfferedTraffic());
        
        if (n == d.getIngressNode())
            op.addConstraint("sum(x_de(d,deltaPlus)) - sum(x_de(d,deltaMinus)) == h_d");
        else if (n == d.getEgressNode())
            op.addConstraint("sum(x_de(d,deltaPlus)) - sum(x_de(d,deltaMinus)) == -h_d");
        else
            op.addConstraint("sum(x_de(d,deltaPlus)) - sum(x_de(d,deltaMinus)) == 0");
    }
}
Link Capacity Constraint

The total traffic carried over link e must not exceed the installed capacity (which is a multiple of capacityModule).

for (Link e : netPlan.getLinks())
{
    op.setInputParameter("e", e.getIndex());
    op.addConstraint("sum(x_de(all,e)) <= C * a_e(e)");
}

Solving and Applying the Solution

The optimization problem is solved using GLPK with a maximum time limit of 10 seconds. If a feasible solution is found, the results are applied to the NetPlan.

op.solve("glpk", "maxSolverTimeInSeconds", 10);

if (!op.solutionIsFeasible()) 
    throw new Net2PlanException("A feasible solution was not found");

// Apply routing
final DoubleMatrix2D x_de = op.getPrimalSolution("x_de").view2D();
netPlan.setRoutingFromDemandLinkCarriedTraffic(x_de, false, false);

// Apply capacity
final double[] a_e = op.getPrimalSolution("a_e").to1DArray();
for (Link e : netPlan.getLinks())
    e.setCapacity(capacityModule * a_e[e.getIndex()]);

// Cleanup unused links
netPlan.removeAllLinksUnused(0.01);

return "Ok! Optimal solution found: " + op.solutionIsOptimal() + ", Number of links " + netPlan.getNumberOfLinks() + ", total capacity installed: " + netPlan.getVectorLinkCapacity().zSum(); 
}

Algorithm Metadata

Description

Returns a description message that will be shown in the graphical user interface.

@Override
public String getDescription()
{
    return "";
}

Input Parameters Definition

This method defines the list of input parameters required by the algorithm, including their names, default values, and descriptions.

/** Returns the list of input parameters of the algorithm. For each parameter, you should return a Triple with its name, default value, and a description. */
@Override
public List<Triple<String, String, String>> getParameters()
{
    final List<Triple<String, String, String>> param = new LinkedList<Triple<String, String, String>>();
    
    param.add(Triple.of("maximumLinkCapacity", "1000", "The maximum capacity allowed for a link between two nodes."));
    param.add(Triple.of("capacityModule", "10", "The capacity of one capacity module (link capacities have to be a multiple of this)."));
    param.add(Triple.of("costPerGbps", "1", "The cost per Gbps of capacity in any link."));
    param.add(Triple.of("costPerKm", "1", "The cost per km in any link."));
    
    return param;
}
}