/** The lightpath request origin node * @return see above */ public WNode getA () { return new WNode (getNe().getIngressNode()); } /** The lightpath request destination node
/** * Constructor to generate a new {@code LightpathAdd} object. * @param demand Demand * @param lineRateGbps Line rate in Gbps */ public LightpathAdd(Demand demand, double lineRateGbps) { this.demand = demand; this.primaryRSA = null; this.lineRateGbps = lineRateGbps; this.backupRSA = null; this.ingressNode = demand.getIngressNode(); this.egressNode = demand.getEgressNode(); this.layer = demand.getLayer(); }
/** * Constructor to generate a new {@code LightpathAdd} object. * @param demand Demand the lighptath belongs to * @param primaryRSA the RSA of the primary (create as a Route) * @param backupRSA the RSA of the backup (create as a protection segment) * @param lineRateGbps line rate of the lightpath */ public LightpathAdd(Demand demand, RSA primaryRSA , RSA backupRSA , double lineRateGbps) { this.demand = demand; this.primaryRSA = primaryRSA; this.lineRateGbps = lineRateGbps; this.backupRSA = backupRSA ; this.ingressNode = demand.getIngressNode(); this.egressNode = demand.getEgressNode(); this.layer = demand.getLayer(); }
/** * Constructor to generate a new {@code LightpathAdd} object. * @param demand Demand * @param rsa The lightpath RSA of the primary (no backup) * @param lineRateGbps Line rate in Gbps */ public LightpathAdd(Demand demand, RSA rsa , double lineRateGbps) { this.demand = demand; this.primaryRSA = rsa; this.lineRateGbps = lineRateGbps; this.backupRSA = null; this.ingressNode = demand.getIngressNode(); this.egressNode = demand.getEgressNode(); this.layer = demand.getLayer(); }
public static boolean isGravityModelApplicableWithLinkMonitoringInfo (NetworkLayer layer , Date date) { final NetPlan np = layer.getNetPlan(); final List<Link> links = np.getLinks(layer); final List<Demand> demands = np.getDemands(layer); if (links.isEmpty()) return false; if (np.hasMulticastDemands(layer)) return false; final SortedSet<Node> demandEndNodes = demands.stream().map(d->d.getEndNodes()).flatMap(d->d.stream()).collect(Collectors.toCollection(TreeSet::new)); final SortedSet<Link> linksWeNeedToHaveFullInOutInfo = new TreeSet<> (); if (demands.stream().map(d->d.getIngressNode()).anyMatch(n->n.getOutgoingLinks(layer).isEmpty())) return false; if (demands.stream().map(d->d.getEgressNode()).anyMatch(n->n.getIncomingLinks(layer).isEmpty())) return false; demandEndNodes.forEach(n->linksWeNeedToHaveFullInOutInfo.addAll(n.getOutgoingLinks(layer))); demandEndNodes.forEach(n->linksWeNeedToHaveFullInOutInfo.addAll(n.getIncomingLinks(layer))); return linksWeNeedToHaveFullInOutInfo.stream().allMatch(ee->ee.getMonitoredOrForecastedCarriedTraffic().hasValue (date)); } public static SortedSet<Date> getDatesWhereGravityModelCanBeApplied (NetworkLayer layer)
public static SortedSet<Date> getDatesWhereGravityModelCanBeApplied (NetworkLayer layer) { final NetPlan np = layer.getNetPlan(); final List<Link> links = np.getLinks(layer); final List<Demand> demands = np.getDemands(layer); if (links.isEmpty()) return new TreeSet<> (); if (np.hasMulticastDemands(layer)) return new TreeSet<> (); final SortedSet<Node> demandEndNodes = demands.stream().map(d->d.getEndNodes()).flatMap(d->d.stream()).collect(Collectors.toCollection(TreeSet::new)); final SortedSet<Link> linksWeNeedToHaveFullInOutInfo = new TreeSet<> (); if (demands.stream().map(d->d.getIngressNode()).anyMatch(n->n.getOutgoingLinks(layer).isEmpty())) return new TreeSet<> (); if (demands.stream().map(d->d.getEgressNode()).anyMatch(n->n.getIncomingLinks(layer).isEmpty())) return new TreeSet<> (); demandEndNodes.forEach(n->linksWeNeedToHaveFullInOutInfo.addAll(n.getOutgoingLinks(layer))); demandEndNodes.forEach(n->linksWeNeedToHaveFullInOutInfo.addAll(n.getIncomingLinks(layer))); final SortedSet<Date> datesWithEnoughInformationFromGM = new TreeSet<> (); for (Date dateFirstLink : linksWeNeedToHaveFullInOutInfo.first().getMonitoredOrForecastedCarriedTraffic().getDatesWithValue()) if (linksWeNeedToHaveFullInOutInfo.stream().allMatch(ee->ee.getMonitoredOrForecastedCarriedTraffic().hasValue (dateFirstLink))) datesWithEnoughInformationFromGM.add(dateFirstLink); return datesWithEnoughInformationFromGM; } public static SortedMap<Demand,Double> getGravityModelEstimationFromMonitorTraffic (NetworkLayer layer , Date date)
private double computeHdFromPrices (Demand d) { /* compute the demand price as weighted sum in the routes of route prices */ final int index_ad = d.getIngressNode().getIndex (); final int index_d = d.getIndex (); final double demandInitialNodeQueueSize = this.routing_numTrafficUnitsOfOnePacket.getDouble() * ((double) this.ctlNumPacketsQueue_nd [index_ad][index_d]) * this.routing_gradient_gammaStep.getDouble(); /* compute the new h_d */ final double new_hd = Math.max(this.cc_control_minHd.getDouble() , Math.min(this.cc_control_maxHd.getDouble(), Math.pow(demandInitialNodeQueueSize, -1/this.cc_control_fairnessFactor.getDouble()))); return new_hd; }
private List<Link> computeValidPathNewRoute (Demand demand , double occupiedLinkCapacity) { final List<List<Link>> paths = cpl.get(Pair.of(demand.getIngressNode() , demand.getEgressNode())); /* If load sharing */ if (isLoadSharing) { final int randomChosenIndex = rng.nextInt(paths.size()); final List<Link> seqLinks = cpl.get(Pair.of(demand.getIngressNode() , demand.getEgressNode())).get(randomChosenIndex); if (isValidPath(seqLinks, occupiedLinkCapacity).getFirst()) return seqLinks; else return new LinkedList<Link> (); } /* If alternate or LCR */ List<Link> lcrSoFar = null; double lcrIdleCapacitySoFar = -Double.MAX_VALUE; for (List<Link> seqLinks : paths) { Pair<Boolean,Double> isValid = isValidPath(seqLinks, occupiedLinkCapacity); if (isValid.getFirst()) { if (isAlternateRouting) return seqLinks; if (isValid.getSecond() > lcrIdleCapacitySoFar) { lcrIdleCapacitySoFar = isValid.getSecond(); lcrSoFar = seqLinks; } } } return (isAlternateRouting || (lcrSoFar == null))? new LinkedList<Link> () : lcrSoFar; }
private void createCandidateRoutes (NetPlan netPlan , double [] c0) { if (useExistingRoutes.getBoolean()) { for (Demand d : netPlan.getDemands()) if (d.getRoutes().isEmpty()) throw new Net2PlanException ("There are no paths available for the demand " + d + ", from: " + d.getIngressNode() + " to " + d.getEgressNode()); } else { netPlan.removeAllRoutes(); Map<Link,Double> linkCostMap = new HashMap<Link,Double> (); for (Link e : netPlan.getLinks()) linkCostMap.put(e , c0 [e.getIndex()]); for (Demand d : netPlan.getDemands()) { List<List<Link>> shortestPaths = GraphUtils.getKLooplessShortestPaths(netPlan.getNodes (), netPlan.getLinks(), d.getIngressNode(), d.getEgressNode(), linkCostMap, numberOfRoutesPerDemand.getInt(), -1, -1, -1, -1, -1, -1); if (shortestPaths.isEmpty()) throw new Net2PlanException ("There are no paths available for the demand " + d + ", from: " + d.getIngressNode() + " to " + d.getEgressNode()); for (List<Link> path : shortestPaths) netPlan.addRoute(d, 0, 0, path, null); } } } }
private void drawDemand(Graphics2D g2d) { final FontMetrics fontMetrics = g2d.getFontMetrics(); final int regularInterlineSpacePixels = fontMetrics.getHeight(); final Demand demand = forwardingRule.getFirst(); final Node demandIngress = demand.getIngressNode(); final Node demandEgress = demand.getEgressNode(); final DrawNode ingressNode = new DrawNode(demandIngress, demand.getLayer(), maxIconSize); final DrawNode egressNode = new DrawNode(demandEgress, demand.getLayer(), maxIconSize); textRow = addIconJump(iconRow); textRow = addLineJump(textRow); textRow = addLineJump(textRow); iconRow = addLineJump(textRow); int topCoordinateLineNodes = maxIconSize + (generalMessage.size() * regularInterlineSpacePixels) + (maxNumberOfTagsPerNodeNorResource * regularInterlineSpacePixels) * iconRow; Point initialDnTopLeftPosition = new Point(maxIconSize, topCoordinateLineNodes); int xSeparationDnCenters = maxIconSize * 3; g2d.setFont(headerFont); g2d.drawString("Demand " + demand.getIndex(), maxIconSize, maxIconSize + (regularInterlineSpacePixels * (textRow))); g2d.setFont(plainFont); DrawNode.addNodeToGraphics(g2d, ingressNode, initialDnTopLeftPosition, fontMetrics, regularInterlineSpacePixels, null); DrawNode.addNodeToGraphics(g2d, egressNode, new Point(initialDnTopLeftPosition.x + xSeparationDnCenters, initialDnTopLeftPosition.y), fontMetrics, regularInterlineSpacePixels, null); drawnNodes.add(ingressNode); drawnNodes.add(egressNode); final DrawLine demandDL = new DrawLine(ingressNode, egressNode, ingressNode.posEast(), egressNode.posWest()); DrawLine.addLineToGraphics(g2d, demandDL, fontMetrics, regularInterlineSpacePixels, lineStroke); }
private Pair<List<Link>,List<Link>> computeValid11PathPairNewRoute (Demand demand , double occupiedLinkCapacity) { final List<Pair<List<Link>,List<Link>>> pathPairs = cpl11.get(Pair.of(demand.getIngressNode() , demand.getEgressNode())); /* If load sharing */ if (isLoadSharing) { final int randomChosenIndex = pathPairs.isEmpty()? 0 : rng.nextInt(pathPairs.size()); final Pair<List<Link>,List<Link>> pathPair = pathPairs.get(randomChosenIndex); if (isValidPath(pathPair.getFirst(), occupiedLinkCapacity).getFirst() && isValidPath(pathPair.getSecond(), occupiedLinkCapacity).getFirst ()) return pathPair; else return null; } Pair<List<Link>,List<Link>> lcrSoFar = null; double lcrIdleCapacitySoFar= -Double.MAX_VALUE; for (Pair<List<Link>,List<Link>> pathPair : this.cpl11.get(Pair.of(demand.getIngressNode() , demand.getEgressNode()))) { Pair<Boolean,Double> validityFirstPath = isValidPath(pathPair.getFirst(), occupiedLinkCapacity); if (!validityFirstPath.getFirst()) continue; Pair<Boolean,Double> validitySecondPath = isValidPath(pathPair.getSecond(), occupiedLinkCapacity); if (!validitySecondPath.getFirst()) continue; if (isAlternateRouting) return pathPair; final double thisPairIdleCapacity = Math.min(validityFirstPath.getSecond(), validitySecondPath.getSecond()); if (thisPairIdleCapacity > lcrIdleCapacitySoFar) { lcrIdleCapacitySoFar = thisPairIdleCapacity; lcrSoFar = pathPair; } } return lcrSoFar; //if alternate, this is null also }
/** * <p>Adds multiples routes for each demand of the given layer, using the paths in an input Candidate Path List. * The paths should use the links of the same layer</p> * * @param cpl {@code SortedMap} where the keys are the node pairs and the values a list of sequence of links (each sequence is a route) * @param optionalLayer the layer (optional) */ public void addRoutesFromCandidatePathList(SortedMap<Pair<Node, Node>, List<List<Link>>> cpl, NetworkLayer... optionalLayer) { checkIsModifiable(); NetworkLayer layer = checkInThisNetPlanOptionalLayerParameter(optionalLayer); List<Route> routes = new LinkedList<Route>(); try { for (Demand d : getDemands(layer)) for (List<Link> path : cpl.get(Pair.of(d.getIngressNode(), d.getEgressNode()))) routes.add(this.addRoute(d, 0, 0, path, null)); } catch (Exception e) { for (Route r : routes) r.remove(); throw e; } if (ErrorHandling.isDebugEnabled()) this.checkCachesConsistency(); }
WServiceChainRequest(Demand sc) { super(sc); this.sc = sc; assert sc.getLayer().getIndex() == 1; assert new WNode (sc.getIngressNode()).isVirtualNode(); assert new WNode (sc.getEgressNode()).isVirtualNode(); }
@Override public List<AjtColumnInfo<Demand>> getNonBasicUserDefinedColumnsVisibleOrNot() { final List<AjtColumnInfo<Demand>> res = new LinkedList<> (); res.add(new AjtColumnInfo<Demand>(this , Node.class, null , "A", "Ingress node", null , d->d.getIngressNode() , AGTYPE.NOAGGREGATION , null)); res.add(new AjtColumnInfo<Demand>(this , Node.class, null , "B", "Egress node", null , d->d.getEgressNode() , AGTYPE.NOAGGREGATION , null)); res.add(new AjtColumnInfo<Demand>(this , Demand.class, null , "Bidirectional pair", "If the demand is bidirectional, provides its bidirectional pair", null , d->d.getBidirectionalPair() , AGTYPE.NOAGGREGATION, null)); res.add(new AjtColumnInfo<Demand>(this , Link.class, null , "Link coupled", "The link that this demand is coupled to (in this or other layer)", null , d->d.getCoupledLink() , AGTYPE.NOAGGREGATION , null)); res.add(new AjtColumnInfo<Demand>(this , Double.class, null , "Offered traffic (" + getTableNetworkLayer().getLinkCapacityUnits() + ")", "Offered traffic by the demand", (d,val)->d.setOfferedTraffic((Double) val), d->d.getOfferedTraffic() , AGTYPE.SUMDOUBLE , null)); res.add(new AjtColumnInfo<Demand>(this , Double.class, null , "Carried traffic (" + getTableNetworkLayer().getLinkCapacityUnits() + ")", "Carried traffic by the demand", null , d->d.getCarriedTraffic() , AGTYPE.SUMDOUBLE , null)); res.add(new AjtColumnInfo<Demand>(this , Double.class, null , "% Lost traffic", "Percentage of the lost traffic by the demand", null, d->d.getOfferedTraffic() == 0? 0 : d.getBlockedTraffic() / d.getOfferedTraffic() , AGTYPE.NOAGGREGATION , d->d.getBlockedTraffic() > 0? Color.RED : Color.GREEN)); res.add(new AjtColumnInfo<Demand>(this , String.class, null , "QoS type", "A used-defined string identifying the type of traffic of the demand", (d,val)-> d.setQoSType((String)val) , d->d.getQosType(), AGTYPE.NOAGGREGATION , null)); res.add(new AjtColumnInfo<Demand>(this , Boolean.class, null , "Source routing?", "", (d,val)->d.setRoutingType((Boolean) val? RoutingType.SOURCE_ROUTING : RoutingType.HOP_BY_HOP_ROUTING), d->d.isSourceRouting() , AGTYPE.COUNTTRUE , null)); res.add(new AjtColumnInfo<Demand>(this , Boolean.class, null , "Is service chain?", "", null, d->d.isServiceChainRequest() , AGTYPE.COUNTTRUE , null)); res.add(new AjtColumnInfo<Demand>(this , String.class, null , "Resource types", "The sequence of resource types that has to be traversed by the routes of the demand, if it is a service chain", null, d->d.isSourceRouting()? d.getServiceChainSequenceOfTraversedResourceTypes().stream().collect(Collectors.joining(",")) : "" , AGTYPE.COUNTTRUE , null)); res.add(new AjtColumnInfo<Demand>(this , String.class, null , "Routing cycles", "Indicates whether there are routing cycles: loopless (no cycle in some route), open cycles (traffic reaches egress node after some cycles in some route), closed cycles (traffic does not reach the egress node in some route)", null, d->d.getRoutingCycleType().name() , AGTYPE.NOAGGREGATION , d->d.getRoutingCycleType() == RoutingCycleType.LOOPLESS? null : Color.ORANGE)); res.add(new AjtColumnInfo<Demand>(this , String.class, null , "Bifurcated?", "Indicates whether the demand is satisfied by more than one path from origin to destination", null, d->!d.isSourceRouting() ? "-" : (d.isBifurcated()) ? String.format("Yes (%d)", d.getRoutes().size()) : "No" , AGTYPE.NOAGGREGATION , null)); res.add(new AjtColumnInfo<Demand>(this , Integer.class, null , "# routes", "Number of associated routes", null, d->!d.isSourceRouting() ? 0 : d.getRoutes().size() , AGTYPE.SUMINT, null)); res.add(new AjtColumnInfo<Demand>(this , Double.class, null , "Worst e2e lat (ms)", "Current worst case end-to-end propagation time in miliseconds (accumulating any lower layer propagation times if any)", null, d->d.getWorstCasePropagationTimeInMs() , AGTYPE.NOAGGREGATION , d->{ final double maxMs = d.getMaximumAcceptableE2EWorstCaseLatencyInMs(); return maxMs <= 0? null : (d.getWorstCasePropagationTimeInMs() > maxMs? Color.RED : null); })); res.add(new AjtColumnInfo<Demand>(this , Double.class, null , "Worst e2e length (km)", "Current worst case end-to-end propagation length in km (accumulating any lower layer propagation lengths if any)", null, d->d.getWorstCaseLengthInKm() , AGTYPE.NOAGGREGATION , null)); res.add(new AjtColumnInfo<Demand>(this , Double.class, null , "Limit e2e lat (ms)", "Maximum end-to-end propagation time in miliseconds (accumulating any lower layer propagation times if any)", (d,val)-> d.setMaximumAcceptableE2EWorstCaseLatencyInMs((Double)val) , d->d.getMaximumAcceptableE2EWorstCaseLatencyInMs() , AGTYPE.NOAGGREGATION , null)); res.add(new AjtColumnInfo<Demand>(this , Double.class, null , "CAGR(%)" , "Compound annual growth factor for this demand", (d,val)->d.setOfferedTrafficPerPeriodGrowthFactor((Double) val), d->d.getOfferedTrafficPerPeriodGrowthFactor() , AGTYPE.NOAGGREGATION , null)); res.add(new AjtColumnInfo<Demand>(this , Integer.class, null , "#Monit points" , "Number of samples of the offered traffic stored, coming from a monitoring or forecasting traffic process", null , d->d.getMonitoredOrForecastedOfferedTraffic().getSize() , AGTYPE.NOAGGREGATION , null)); return res; }
private Pair<Map<Demand,Demand>,Map<Route,Route>> initializeNetPlanLinksBidirDemandsAndRoutes (NetPlan np) { /* Remove lower half demands from np */ np.removeAllRoutes(); for (Node n1 : np.getNodes()) for (Node n2 : np.getNodes()) if (n1.getIndex () > n2.getIndex ()) for (Demand d : np.getNodePairDemands(n1, n2,false)) d.remove (); np.addRoutesFromCandidatePathList(netPlan.computeUnicastCandidatePathList(null , tcfa_maxNumberPathsPerDemand.getInt(), tcfa_maxPathLengthInKm.getDouble(), tcfa_maxPathNumberOfHops.getInt(), -1, -1, -1, -1 , null)); /* Add symmetric demands and routes */ Map<Demand,Demand> opposite_d = new HashMap<Demand,Demand> (); Map<Route,Route> opposite_r = new HashMap<Route,Route> (); for (Demand d : new HashSet<Demand> (np.getDemands())) { final Demand opDemand = np.addDemand(d.getEgressNode(), d.getIngressNode(), d.getOfferedTraffic(), RoutingType.SOURCE_ROUTING , null); opposite_d.put(d,opDemand); opposite_d.put(opDemand,d); for (Route r : new HashSet<Route> (d.getRoutes ())) { final Route oppRoute = np.addRoute(opDemand, r.getCarriedTraffic(), r.getOccupiedCapacity() , oppositeSeqLinks (r.getSeqLinks()), null); opposite_r.put(r,oppRoute); opposite_r.put(oppRoute,r); } } return Pair.of(opposite_d,opposite_r); }
/** <p>Obtains a {@code JGraphT} graph from a given link map.</p> * * @param demands List of demands * @return {@code JGraphT} graph */ public static org.jgrapht.Graph<Node, Demand> getGraphFromDemandMap(List<Demand> demands) { org.jgrapht.Graph<Node, Demand> graph = new DirectedWeightedMultigraph<Node, Demand>(Demand.class); if (demands != null) { for (Demand demand : demands) { Node originNode = demand.getIngressNode(); Node destinationNode = demand.getEgressNode(); if (!graph.containsVertex(originNode)) graph.addVertex(originNode); if (!graph.containsVertex(destinationNode)) graph.addVertex(destinationNode); graph.addEdge(originNode, destinationNode, demand); } } return graph; }
/** <p>Given a list of Network elements, it computes the node-network element outgoing incidence matrix. This is a matrix with as many rows as nodes, and as many columns as elements. Position (<i>n</i>, <i>e</i>) has a 1 if element <i>e</i> (<i>e = 0</i> refers to the first element, <i>e = 1</i> refers to the second one, and so on) is initiated in node <i>n</i> (<i>n = 0</i> refers to the first node , <i>n = 1</i> refers to the second one, and so on), and 0 otherwise.</p> * * @param nodes List of nodes * @param elements List of elements * @return Node-link outgoing incidence matrix * @see com.net2plan.interfaces.networkDesign.NetworkElement */ public static DoubleMatrix2D getOutgoingIncidenceMatrix(List<Node> nodes, List<? extends NetworkElement> elements) { int N = nodes.size(); int E = elements.size(); DoubleMatrix2D A_ne = DoubleFactory2D.sparse.make(N, E); for (NetworkElement o : elements) if (o instanceof Link) { Link e = (Link) o; A_ne.set(e.getOriginNode().getIndex(), e.getIndex(), 1); } else if (o instanceof Demand) { Demand e = (Demand) o; A_ne.set(e.getIngressNode().getIndex(), e.getIndex(), 1); } else if (o instanceof Route) { Route e = (Route) o; A_ne.set(e.getIngressNode().getIndex(), e.getIndex(), 1); } else throw new Net2PlanException("Error making the matrix"); return A_ne; }
for (Demand d : netPlan.getDemands(layer)) List<Link> seqLinks = GraphUtils.getShortestPath(netPlan.getNodes () , netPlan.getLinks (), d.getIngressNode() , d.getEgressNode() , null); if (seqLinks == null) throw new Net2PlanException("Physical topology must be connected"); minTrafficInTheLinks += d.getOfferedTraffic() * seqLinks.size();
/** <p>Given a list of Network Elements, it computes the node-network element incidence matrix. This is a matrix with as many rows as nodes, and as many columns as elements. Position (<i>n</i>, <i>e</i>) has a 1 if element <i>e</i> (<i>e = 0</i> refers to the first element}, <i>e = 1</i> refers to the second one, and so on) is initiated in node <i>n</i> (<i>n = 0</i> refers to the first node , <i>n = 1</i> refers to the second one, and so on), -1 if it ends in node n, and 0 otherwise.</p> * @param nodes List of nodes * @param elements List of elements * @return Incidence matrix * @see com.net2plan.interfaces.networkDesign.NetworkLayer */ public static DoubleMatrix2D getIncidenceMatrix(List<Node> nodes, List<? extends NetworkElement> elements) { int N = nodes.size(); int E = elements.size(); DoubleMatrix2D A_ne = DoubleFactory2D.sparse.make(N, E); for (NetworkElement o : elements) if (o instanceof Link) { Link e = (Link) o; A_ne.set(e.getOriginNode().getIndex(), e.getIndex(), 1); A_ne.set(e.getDestinationNode().getIndex(), e.getIndex(), -1); } else if (o instanceof Demand) { Demand e = (Demand) o; A_ne.set(e.getIngressNode().getIndex(), e.getIndex(), 1); A_ne.set(e.getEgressNode().getIndex(), e.getIndex(), -1); } else if (o instanceof Route) { Route e = (Route) o; A_ne.set(e.getIngressNode().getIndex(), e.getIndex(), 1); A_ne.set(e.getEgressNode().getIndex(), e.getIndex(), -1); } else throw new Net2PlanException("Error making the matrix"); return A_ne; }
private void updateDemandRoutingFromWeightsKnown (Demand d) { final Node a_d = d.getIngressNode(); final double h_d = d.getOfferedTraffic(); final DoubleMatrix1D weightsKnown_e = this.routing_mostUpdatedLinkPriceKnownByNode_ne.viewRow(a_d.getIndex ()); DoubleMatrix1D a_k = DoubleFactory1D.dense.make (R); for (Route r : d.getRoutes()) { double val = 0; for (Link e : r.getSeqLinks()) val += weightsKnown_e.get(e.getIndex()) + 1; a_k.set(r.getIndex (), val); } DoubleMatrix1D x_r = GradientProjectionUtils.regularizedProjection_sumEquality (a_k , control_routeIndexes_d [d.getIndex ()] , null , h_d , this.gradient_regularizationEpsilon.getDouble()); for (Route r : d.getRoutes ()) r.setCarriedTraffic(x_r.get(r.getIndex ()) , x_r.get(r.getIndex ())); }