mirror of
https://github.com/Zenithsiz/ist-ddrs-lab2
synced 2026-02-03 14:10:05 +00:00
Started work on exercise 15.
This commit is contained in:
parent
ef2df1159c
commit
e0617ec046
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@ -20,6 +20,8 @@
|
||||
"linetype",
|
||||
"logseq",
|
||||
"maxs",
|
||||
"ncol",
|
||||
"nrow",
|
||||
"packetsize",
|
||||
"pktnet",
|
||||
"pnet",
|
||||
|
||||
24
code/15.R
24
code/15.R
@ -25,22 +25,24 @@ Flows <- list(
|
||||
|
||||
kleinrock <- approx_kleinrock(LinkCapacities, Flows, packet_size)
|
||||
str(kleinrock)
|
||||
cat(sprintf("Kleinrock average: %.20f\n", kleinrock$total_wait))
|
||||
cat(sprintf("Kleinrock average: %.20f\n", kleinrock$avg_packet_delay_network))
|
||||
|
||||
min_rate <- min(sapply(Flows, function(flow) flow$rate))
|
||||
endTime <- 10000 * (1 / min_rate)
|
||||
cat(sprintf("End time = %.2f\n", endTime))
|
||||
|
||||
set.seed(0)
|
||||
pnet_results <- lapply(1:2, function(...) pnet(LinkCapacities, Flows, endTime))
|
||||
pnet_avgs <- sapply(pnet_results, function(res) res$avg_flow_delays)
|
||||
pnet_results <- lapply(1:10, function(...) pnet(LinkCapacities, Flows, endTime))
|
||||
for (flow_idx in 1:4) {
|
||||
pnet_avgs <- sapply(pnet_results, \(res) res$avg_flow_delays[[flow_idx]])
|
||||
|
||||
pnet_mean <- mean(pnet_avgs)
|
||||
pnet_var <- var(pnet_avgs)
|
||||
pnet_mean <- mean(pnet_avgs)
|
||||
pnet_var <- var(pnet_avgs)
|
||||
|
||||
confidence <- 0.95
|
||||
p <- 1 - (1 - confidence) / 2
|
||||
t <- qt(p, length(pnet_results) - 1)
|
||||
pnet_ci_min <- pnet_mean - t * sqrt(pnet_var / length(pnet_results))
|
||||
pnet_ci_max <- pnet_mean + t * sqrt(pnet_var / length(pnet_results))
|
||||
cat(sprintf("PNet average results: %.5f .. %.5f\n", pnet_ci_min, pnet_ci_max))
|
||||
confidence <- 0.95
|
||||
p <- 1 - (1 - confidence) / 2
|
||||
t <- qt(p, length(pnet_results) - 1)
|
||||
pnet_ci_min <- pnet_mean - t * sqrt(pnet_var / length(pnet_results))
|
||||
pnet_ci_max <- pnet_mean + t * sqrt(pnet_var / length(pnet_results))
|
||||
cat(sprintf("PNet average results: %.5f .. %.5f\n", pnet_ci_min, pnet_ci_max))
|
||||
}
|
||||
|
||||
19
code/15c.R
Normal file
19
code/15c.R
Normal file
@ -0,0 +1,19 @@
|
||||
source("code/kleinrock.R")
|
||||
|
||||
k <- 1000
|
||||
|
||||
link_capacity <- 256 * k
|
||||
packet_size <- 1 * k
|
||||
|
||||
link_capacities <- replicate(7, link_capacity)
|
||||
flows <- list(
|
||||
list(rate = 171.5, packetsize = packet_size, route = c(1, 3, 6)),
|
||||
list(rate = 43.5, packetsize = packet_size, route = c(1, 4, 7)),
|
||||
list(rate = 64, packetsize = packet_size, route = c(2, 5)),
|
||||
list(rate = 128, packetsize = packet_size, route = c(2, 5, 7)),
|
||||
list(rate = 128, packetsize = packet_size, route = c(4))
|
||||
)
|
||||
|
||||
kleinrock <- approx_kleinrock(link_capacities, flows, packet_size)
|
||||
str(kleinrock)
|
||||
cat(sprintf("Kleinrock average: %.20f\n", kleinrock$avg_packet_delay_network))
|
||||
19
code/15d.R
Normal file
19
code/15d.R
Normal file
@ -0,0 +1,19 @@
|
||||
source("code/kleinrock.R")
|
||||
|
||||
k <- 1000
|
||||
|
||||
link_capacity <- 256 * k
|
||||
packet_size <- 1 * k
|
||||
|
||||
link_capacities <- replicate(7, link_capacity)
|
||||
flows <- list(
|
||||
list(rate = 170.168, packetsize = packet_size, route = c(1, 3, 6)),
|
||||
list(rate = 172.832, packetsize = packet_size, route = c(2, 5, 7)),
|
||||
list(rate = 39.218, packetsize = packet_size, route = c(1, 4)),
|
||||
list(rate = 24.782, packetsize = packet_size, route = c(2, 5)),
|
||||
list(rate = 128.0, packetsize = packet_size, route = c(4))
|
||||
)
|
||||
|
||||
kleinrock <- approx_kleinrock(link_capacities, flows, packet_size)
|
||||
str(kleinrock)
|
||||
cat(sprintf("Kleinrock average: %.20f\n", kleinrock$avg_packet_delay_network))
|
||||
116
code/bg/aux_bg.R
Normal file
116
code/bg/aux_bg.R
Normal file
@ -0,0 +1,116 @@
|
||||
loadlinks = function(NumNodes,NumODPairs,Paths) {
|
||||
#Loads links with rate contained in Paths list
|
||||
LinkRates=matrix(rep(0,NumNodes^2),nrow=NumNodes) #Initializes LinkRates matrix with all zeros
|
||||
for (i in 1:NumODPairs) { #Iterates over OD pairs
|
||||
NumPaths=length(Paths[[i]]) #Number of paths in OD pair
|
||||
for (j in 1:NumPaths) { #Iterates over paths of OD pair
|
||||
ThisPath=Paths[[i]][[j]]$route #Current path
|
||||
ThisRate=Paths[[i]][[j]]$rate #Current rate
|
||||
for (k in 1:(length(ThisPath)-1)) { #Iterates over links of path
|
||||
LinkOrigin=ThisPath[k] #Origin of link
|
||||
LinkDestination=ThisPath[k+1] #Destination of link
|
||||
#Loads link with rate of path
|
||||
LinkRates[LinkOrigin,LinkDestination]=LinkRates[LinkOrigin,LinkDestination]+ThisRate
|
||||
}
|
||||
}
|
||||
}
|
||||
return(LinkRates)
|
||||
}
|
||||
|
||||
bestpathinsert = function(ODPair,NumPaths,Paths,BestPath) {
|
||||
#Inserts best path in Paths list for specific OD pair (if not already there) and determines index of
|
||||
#best path within this list; if best path is new its rate is zero
|
||||
BestPathIndex=0 #Initializes index of best path
|
||||
for (j in 1:NumPaths) { #Iterates over paths
|
||||
ThisPath=Paths[[ODPair]][[j]]$route #Extracts path from Paths list
|
||||
if (length(BestPath)==length(ThisPath) && all(BestPath==ThisPath)) { #Best path is already in list
|
||||
BestPathIndex=j #Sets index of best path
|
||||
break
|
||||
}
|
||||
}
|
||||
if (BestPathIndex==0){ #Best path is not in Paths list
|
||||
NumPaths=NumPaths+1 #Increments number of path
|
||||
BestPathIndex=NumPaths #Sets index of best path
|
||||
Paths[[ODPair]][[BestPathIndex]]=list(route=BestPath,rate=0) #Inserts best path in Paths list
|
||||
}
|
||||
return(list(numroutes=NumPaths,bestrouteindex=BestPathIndex,paths=Paths))
|
||||
}
|
||||
|
||||
pathlengths = function(ODPair,NumPaths,Paths,LinkFirstDerivativeCosts) {
|
||||
#Determines first derivative path lengths of all paths belonging to given OD pair
|
||||
PathFirstDerivativeLengths=vector(mode="numeric",length=NumPaths) #Initializes PathFirstDerivativeLengths vector
|
||||
for (j in 1:NumPaths) { #Iterates over paths
|
||||
ThisPath=Paths[[ODPair]][[j]]$route #Extracts path from Paths list
|
||||
ThisLength=0 #Initializes path length
|
||||
for (k in 1:(length(ThisPath)-1)) { #Iterates over links of path
|
||||
LinkOrigin=ThisPath[k] #Origin of link
|
||||
LinkDestination=ThisPath[k+1] #Destination of link
|
||||
ThisLength=ThisLength+LinkFirstDerivativeCosts[LinkOrigin,LinkDestination] #Updates path length
|
||||
}
|
||||
PathFirstDerivativeLengths[j]=ThisLength #Stores path length in PathFirstDerivativeLengths vector
|
||||
}
|
||||
return(PathFirstDerivativeLengths)
|
||||
}
|
||||
|
||||
deviaterate = function(ODPair,NumPaths,BestPathIndex,Paths,PathFirstDerivativeLengths,LinkSecondDerivativeCosts,Alpha) {
|
||||
#Deviates rate between paths of given OD pair, knowing the best route
|
||||
|
||||
#Extracts MFDL and the path that owns it
|
||||
MFDL=PathFirstDerivativeLengths[BestPathIndex] #Extracts MFDL
|
||||
#print("BestIncDelayFirst");print(BestIncDelayFirst)
|
||||
BestPath=Paths[[ODPair]][[BestPathIndex]]$route #Extracts path with MFDL
|
||||
for (i in 1:NumPaths) { #Iterates over paths
|
||||
if (BestPathIndex==i) { #Path is MFDL
|
||||
#Do noting
|
||||
} else { #Path is non-MFDL
|
||||
ThisLength=PathFirstDerivativeLengths[i]
|
||||
#print("ThisLength");print(ThisLength)
|
||||
#Calculates Hp parameter
|
||||
ThisPath=Paths[[ODPair]][[i]]$route #Extracts path from Paths list
|
||||
NonRepeatedLinks=nonrepeatedlinks(ThisPath,BestPath) #Determines list of links not common to MFDL path and non-MFDL path
|
||||
Hp=0 #Initializes Hp parameter
|
||||
for (j in 1:length(NonRepeatedLinks)) { #Iterates over non-repeted links
|
||||
LinkOrigin=NonRepeatedLinks[[j]][1] #Origin of link
|
||||
LinkDestination=NonRepeatedLinks[[j]][2] #Destination of link
|
||||
Hp=Hp+LinkSecondDerivativeCosts[LinkOrigin,LinkDestination] #Updates Hp parameter
|
||||
}
|
||||
#print("Hp");print(Hp)
|
||||
#Calculates Delta parameter
|
||||
Delta=Alpha*(ThisLength-MFDL)/Hp
|
||||
#print("Delta");print(Delta)
|
||||
#Deviates rate
|
||||
PreviousRate=Paths[[ODPair]][[i]]$rate
|
||||
NewRate=PreviousRate-Delta #Checks if new rate of non-MFDL path is non-negative
|
||||
if (NewRate>=0) {
|
||||
Paths[[ODPair]][[BestPathIndex]]$rate=Paths[[ODPair]][[BestPathIndex]]$rate+Delta #Adds Delta to MFDL path
|
||||
Paths[[ODPair]][[i]]$rate=NewRate #Subtracts Delta from non-MFDL path
|
||||
} else {
|
||||
Paths[[ODPair]][[i]]$rate=0
|
||||
Paths[[ODPair]][[BestPathIndex]]$rate=Paths[[ODPair]][[BestPathIndex]]$rate+PreviousRate
|
||||
}
|
||||
}
|
||||
}
|
||||
return(Paths)
|
||||
}
|
||||
|
||||
nonrepeatedlinks = function(Path1,Path2) {
|
||||
#Returns list with the links that are not common to Path1 and Path2
|
||||
NonRepeatedLinks=list() #Initializes NonRepeatedLinks list
|
||||
for (j in 1:(length(Path1)-1)) { #Iterates over links of Path1
|
||||
NonRepeatedLinks[[j]]=Path1[j:(j+1)] #Loads NonRepeatedLinks list with links of Path1
|
||||
}
|
||||
for (j in 1:(length(Path2)-1)) { #Iterates over links of Path2
|
||||
ThisLink=Path2[j:(j+1)] #Extracts link from Path2
|
||||
RepeatedLink=FALSE #Set ThisLink as not repeated, initially
|
||||
for (k in 1:length(NonRepeatedLinks)) { #Iterates over links already in NonRepeatedLinks list
|
||||
if (identical(NonRepeatedLinks[[k]],ThisLink)) { #If ThisLink is already in NonRepeatedLinks list
|
||||
RepeatedLink=TRUE #ThisLink is repeated
|
||||
break #Stop searching
|
||||
}
|
||||
}
|
||||
if (RepeatedLink==FALSE) { #If ThisLink is not repeated
|
||||
NonRepeatedLinks[[length(NonRepeatedLinks)+1]]=ThisLink #Insert ThisLink in NonRepeatedLinks list
|
||||
}
|
||||
}
|
||||
return(NonRepeatedLinks)
|
||||
}
|
||||
160
code/bg/bg.R
Normal file
160
code/bg/bg.R
Normal file
@ -0,0 +1,160 @@
|
||||
# This script determines the optimal flow bifurcations that minimize the network
|
||||
# average packet delay, using the Bertsekas algorithm (section 5.7 of Data
|
||||
# Networks book)
|
||||
|
||||
source("code/bg/parameters.R")
|
||||
source("code/bg/shortestpath.R")
|
||||
source("code/bg/aux_bg.R")
|
||||
|
||||
parameters() # Calls parameters routine
|
||||
|
||||
NumNodes <- ncol(LinkCapacities) # Number of nodes
|
||||
NumLinks <- sum(LinkCapacities != 0) # Number of links
|
||||
NumODPairs <- nrow(Flows) # Number of flows
|
||||
|
||||
# Alpha=NumLinks/NumNodes^2
|
||||
Alpha <- 1 # Stepsize for flow deviation
|
||||
DeltaCap <- 0.05 # Capacity adjusting factor, for phase I
|
||||
ErrorPhase2 <- 10^(-8) # Convergence tolerance phase II
|
||||
|
||||
LinkRates <- matrix(rep(0, NumNodes^2), nrow = NumNodes) # Initializes LinkRates matrix with all zeros
|
||||
|
||||
LinkFirstDerivativeCosts <- 1 / LinkCapacities # Initial link costs with all link rates equal to zero
|
||||
# print(LinkFirstDerivativeCosts)
|
||||
|
||||
Paths <- rep(list(list(list(route = c(), rate = NULL))), NumODPairs) # Initializes Path list
|
||||
|
||||
# Initial solution - each flow routed through shortest path based on link first derivative costs
|
||||
for (i in 1:NumODPairs) {
|
||||
Origin <- Flows[i, 1] # Origin of flow
|
||||
Destination <- Flows[i, 2] # Destination of flow
|
||||
Rate <- Flows[i, 3] # Rate of flow
|
||||
Route <- shortestpath(LinkFirstDerivativeCosts, Origin, Destination) # Shortest path of flow
|
||||
Paths[[i]][[1]] <- list(route = Route, rate = Rate) # Inserts path information in Paths list
|
||||
}
|
||||
|
||||
# Loads links with rate
|
||||
LinkRates <- loadlinks(NumNodes, NumODPairs, Paths)
|
||||
# print("LinkRates");print(LinkRates)
|
||||
|
||||
# Determines maximum link load (ignoring NaN)
|
||||
MaxUtilization <- max(LinkRates / LinkCapacities, na.rm = TRUE)
|
||||
# print("MaxUtilization");print(MaxUtilization)
|
||||
|
||||
# print("Paths");print(Paths)
|
||||
|
||||
# Phase I: finds feasible solution
|
||||
niter1 <- 0 # Initializes number of iterations of phase I
|
||||
while (MaxUtilization >= 1) { # While there is at least one link overloaded
|
||||
CapacityAdjustFactor <- (1 + DeltaCap) * MaxUtilization # Determines capacity adjust factor
|
||||
# print("CapacityAdjustFactor");print(CapacityAdjustFactor)
|
||||
AdjustedLinkCapacities <- CapacityAdjustFactor * LinkCapacities # Determines adjusted link capacities
|
||||
# print("AdjustedLinkCapacities");print(AdjustedLinkCapacities)
|
||||
# Determines link costs based on adjusted link capacities
|
||||
LinkFirstDerivativeCosts <- AdjustedLinkCapacities / (AdjustedLinkCapacities - LinkRates)^2
|
||||
LinkFirstDerivativeCosts[is.nan(LinkFirstDerivativeCosts)] <- Inf
|
||||
# print("LinkFirstDerivativeCosts");print(LinkFirstDerivativeCosts)
|
||||
# Determines second derivative link costs based on adjusted link capacities
|
||||
LinkSecondDerivativeCosts <- 2 * AdjustedLinkCapacities / (AdjustedLinkCapacities - LinkRates)^3
|
||||
LinkSecondDerivativeCosts[is.nan(LinkSecondDerivativeCosts)] <- Inf
|
||||
# print("LinkSecondDerivativeCosts");print(LinkSecondDerivativeCosts)
|
||||
# Iterates over OD pairs to deviate rate
|
||||
for (i in 1:NumODPairs) {
|
||||
Origin <- Flows[i, 1] # Origin of OD pair
|
||||
Destination <- Flows[i, 2] # Destination of OD pair
|
||||
NumPaths <- length(Paths[[i]]) # Number of paths of OD pair
|
||||
# Determines best path of OD pair
|
||||
BestPath <- shortestpath(LinkFirstDerivativeCosts, Origin, Destination)
|
||||
# Inserts best path in Paths list (if not already there) and determines index
|
||||
# of best path within this list; if best path is new its rate is zero
|
||||
Best <- bestpathinsert(i, NumPaths, Paths, BestPath)
|
||||
NumPaths <- Best$numroutes
|
||||
BestPathIndex <- Best$bestrouteindex
|
||||
Paths <- Best$paths
|
||||
# Determines first derivative path lengths
|
||||
PathFirstDerivativeLengths <- pathlengths(i, NumPaths, Paths, LinkFirstDerivativeCosts)
|
||||
# Deviates rate between routes
|
||||
Paths <- deviaterate(i, NumPaths, BestPathIndex, Paths, PathFirstDerivativeLengths, LinkSecondDerivativeCosts, Alpha)
|
||||
# print("Paths");print(Paths)
|
||||
}
|
||||
LinkRates <- loadlinks(NumNodes, NumODPairs, Paths) # Loads links with rate
|
||||
MaxUtilization <- max(LinkRates / LinkCapacities, na.rm = TRUE) # Determines maximum link load
|
||||
niter1 <- niter1 + 1 # Increments number of iterations
|
||||
}
|
||||
|
||||
# Display number of iterations in phase I
|
||||
cat(sprintf("Number of iterations in phase I: %i", niter1), "\n")
|
||||
# print("LinkRates");print(LinkRates)
|
||||
|
||||
# Phase II: finds optimal solution
|
||||
Error2 <- Inf # Initializes convergence error
|
||||
PreviousTotalMeanPackets <- 0 # Initializes PreviousTotalMeanPackets
|
||||
niter2 <- 0 # Initializes number of iterations of phase II
|
||||
while (abs(1 - Error2) > ErrorPhase2) { # While convergence tolerance not reached
|
||||
# Determines link costs
|
||||
LinkFirstDerivativeCosts <- LinkCapacities / (LinkCapacities - LinkRates)^2
|
||||
LinkFirstDerivativeCosts[is.nan(LinkFirstDerivativeCosts)] <- Inf
|
||||
# print("LinkFirstDerivativeCosts");print(LinkFirstDerivativeCosts)
|
||||
# Determines second derivative link costs
|
||||
LinkSecondDerivativeCosts <- 2 * LinkCapacities / (LinkCapacities - LinkRates)^3 # Incremental delays based on adjusted link capacities
|
||||
LinkSecondDerivativeCosts[is.nan(LinkSecondDerivativeCosts)] <- Inf
|
||||
# print("LinkSecondDerivativeCosts");print(LinkSecondDerivativeCosts)
|
||||
# Iterates over OD pairs to deviate rate
|
||||
for (i in 1:NumODPairs) {
|
||||
Origin <- Flows[i, 1] # Origin of OD pair
|
||||
Destination <- Flows[i, 2] # Destination of OD pair
|
||||
NumPaths <- length(Paths[[i]]) # Number of paths of OD pair
|
||||
# Determines best path of OD pair
|
||||
BestPath <- shortestpath(LinkFirstDerivativeCosts, Origin, Destination)
|
||||
# Inserts best path in Paths list (if not already there) and determines index
|
||||
# of best path within this list; if best path is new its rate is zero
|
||||
Best <- bestpathinsert(i, NumPaths, Paths, BestPath)
|
||||
NumPaths <- Best$numroutes
|
||||
BestPathIndex <- Best$bestrouteindex
|
||||
Paths <- Best$paths
|
||||
# Determines first derivative path lengths, of all paths belonging to OD pair i
|
||||
PathFirstDerivativeLengths <- pathlengths(i, NumPaths, Paths, LinkFirstDerivativeCosts)
|
||||
# Deviates rate between routes
|
||||
Paths <- deviaterate(i, NumPaths, BestPathIndex, Paths, PathFirstDerivativeLengths, LinkSecondDerivativeCosts, Alpha)
|
||||
# print("Paths");print(Paths)
|
||||
}
|
||||
# Loads links with rate
|
||||
LinkRates <- loadlinks(NumNodes, NumODPairs, Paths)
|
||||
# Determines average number of packets in each link
|
||||
LinkMeanPackets <- LinkRates / (LinkCapacities - LinkRates)
|
||||
LinkMeanPackets[which(is.nan(LinkMeanPackets))] <- 0
|
||||
# Determines average number of packets in network
|
||||
TotalMeanPackets <- sum(LinkMeanPackets)
|
||||
# Determines convergence error
|
||||
Error2 <- TotalMeanPackets / PreviousTotalMeanPackets
|
||||
# print("Error2");print(Error2)
|
||||
# Updates PreviousTotalMeanPackets
|
||||
PreviousTotalMeanPackets <- TotalMeanPackets
|
||||
# Increments number of iterations
|
||||
niter2 <- niter2 + 1
|
||||
}
|
||||
# print("LinkRates");print(LinkRates)
|
||||
# print("LinkMeanPackets");print(LinkMeanPackets)
|
||||
|
||||
# print("Paths");print(Paths)
|
||||
|
||||
# Print results
|
||||
cat(sprintf("Number of iterations in phase 2: %i", niter2), "\n")
|
||||
cat("\n")
|
||||
cat(sprintf("Average number of packets: %f", TotalMeanPackets), "\n")
|
||||
|
||||
cat("\n")
|
||||
cat(sprintf("Flow rates:"), "\n")
|
||||
for (i in 1:NumODPairs) {
|
||||
Origin <- Flows[i, 1]
|
||||
Destination <- Flows[i, 2]
|
||||
cat(sprintf("Flow from %i to %i", Origin, Destination), "\n")
|
||||
NumPaths <- length(Paths[[i]])
|
||||
for (j in 1:NumPaths) {
|
||||
ThisPath <- Paths[[i]][[j]]$route
|
||||
ThisRate <- Paths[[i]][[j]]$rate
|
||||
cat(" Rate of route ")
|
||||
cat(ThisPath, sep = "-")
|
||||
cat(sprintf(": %f", ThisRate), "\n")
|
||||
}
|
||||
}
|
||||
36
code/bg/parameters.R
Normal file
36
code/bg/parameters.R
Normal file
@ -0,0 +1,36 @@
|
||||
parameters <- function() {
|
||||
# Define here the capacity of each link, in bits/sec. The LinkCapacities matrix
|
||||
# is a square matrix where the number of rows equals the number of nodes. Rows
|
||||
# correspond to origin nodes and columns to destination nodes. Element(i,j)
|
||||
# should be equal to the link capacity if there is a link from node i to node j,
|
||||
# and should be 0 otherwise
|
||||
link_capacity <- 256 * 1000
|
||||
LinkCapacities <<- matrix(
|
||||
c(
|
||||
0, link_capacity, link_capacity, 0, 0, 0,
|
||||
0, 0, 0, link_capacity, link_capacity, 0,
|
||||
0, 0, 0, 0, link_capacity, 0,
|
||||
0, 0, 0, 0, 0, link_capacity,
|
||||
0, 0, 0, 0, 0, link_capacity,
|
||||
0, 0, 0, 0, 0, 0
|
||||
),
|
||||
nrow = 6,
|
||||
ncol = 6,
|
||||
byrow = TRUE
|
||||
)
|
||||
|
||||
# Define here the flows. Flows is a matrix with a user-defined number of rows and
|
||||
# 3 columns. Each row corresponds to a different flow, and the three columns
|
||||
# correspond to (1) the origin node, (2) the destination node, and (3) the
|
||||
# offered rate between the two previous nodes, expressed in bits/sec
|
||||
Flows <<- matrix(
|
||||
c(
|
||||
1, 6, (215 + 128) * 1000,
|
||||
1, 5, 64 * 1000,
|
||||
2, 5, 128 * 1000
|
||||
),
|
||||
nrow = 3,
|
||||
ncol = 3,
|
||||
byrow = TRUE
|
||||
)
|
||||
}
|
||||
59
code/bg/shortestpath.R
Normal file
59
code/bg/shortestpath.R
Normal file
@ -0,0 +1,59 @@
|
||||
shortestpath = function (Costs,Source,Destination) {
|
||||
|
||||
#Given a matrix of costs this function determines the shorthest path between a
|
||||
#source and destination using the Dijkstra's algorithm. The route is the
|
||||
#sequence of nodes from source to destination. Here is an example of a costs
|
||||
#matrix:
|
||||
#Costs = [0 10 10 Inf
|
||||
# 10 0 10 10
|
||||
# 20 5 0 10
|
||||
# Inf 25 5 0];
|
||||
|
||||
NumNodes=nrow(Costs); #number of nodes
|
||||
|
||||
NodeLabels=Costs[Source,] #vector of node label
|
||||
|
||||
TempNodes=1:NumNodes #vector of temporary nodes
|
||||
TempNodes=TempNodes[-Source] #remove source node from vector of temporary nodes
|
||||
TempLabels=NodeLabels #vector of temporary labels
|
||||
TempLabels=TempLabels[-Source] #remove label of source node from vector of temporary labels
|
||||
|
||||
NodeParents=rep(Source,NumNodes) #vector of node parents
|
||||
|
||||
p=Source #node that becomes permanently labelled
|
||||
|
||||
while (TRUE) {
|
||||
i=which.min(TempLabels) #determines index of lower label node
|
||||
c=min(TempLabels) #determines label of lower label node
|
||||
p=TempNodes[i] #p is the next permanent node
|
||||
#print(p)
|
||||
TempNodes=TempNodes[-i] #remove p node from vector of temporary nodes
|
||||
TempLabels=TempLabels[-i] #remove label of p node from vector of temporary labels
|
||||
NodeLabels[p]=c #update node label of p node
|
||||
if (p==Destination) break #iteration ends when destination found
|
||||
for (k in 1:length(TempNodes)) { #update labels of temporary nodes
|
||||
nt=TempNodes[k] #next temporary node
|
||||
#print(nt)
|
||||
ct=NodeLabels[p]+Costs[p,nt] #calculate cost to temporary node via p
|
||||
# print(ct)
|
||||
# print(Costs[p,nt])
|
||||
# print(NodeLabels[nt])
|
||||
if (ct < NodeLabels[nt]) { #update only if new cost is lower
|
||||
TempLabels[k]=ct #update label on vector of temporary node labels
|
||||
NodeLabels[nt]=ct #update label on vector of node labels
|
||||
NodeParents[nt]=p #update node parent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#determines route from vector of node parents
|
||||
Route=c(Destination)
|
||||
r=Destination
|
||||
while (r!=Source) {
|
||||
r=NodeParents[r]
|
||||
Route=cbind(r,Route);
|
||||
}
|
||||
|
||||
return(Route)
|
||||
|
||||
}
|
||||
BIN
images/15-diagram.png
(Stored with Git LFS)
Normal file
BIN
images/15-diagram.png
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -1,7 +1,7 @@
|
||||
#import "@preview/tablex:0.0.6": tablex, rowspanx, colspanx
|
||||
#import "/typst/util.typ" as util: indent_par, code_figure
|
||||
|
||||
#indent_par[The following code 10 is our implementation of the kleinrock approximation. It takes the link capacities, flows and packet size similarly to the `pnet` simulator.]
|
||||
#indent_par[The following code 10 is our implementation of the Kleinrock approximation. It takes the link capacities, flows and packet size similarly to the `pnet` simulator.]
|
||||
|
||||
#code_figure(
|
||||
text(size: 0.8em, raw(read("/code/kleinrock.R"), lang: "R", block: true)),
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#import "@preview/tablex:0.0.6": tablex, rowspanx, colspanx
|
||||
#import "/typst/util.typ" as util: indent_par, code_figure
|
||||
|
||||
#indent_par[We used our previously developed kleinrock simulator and the `pnet` simulator, running it 10 times and calculating 95% confidence intervals, acquiring the following results in table 18:]
|
||||
#indent_par[We used our previously developed Kleinrock script and the `pnet` simulator, running it 10 times and calculating 95% confidence intervals, acquiring the following results in table 18:]
|
||||
|
||||
#figure(
|
||||
pad(1em, tablex(
|
||||
@ -41,6 +41,6 @@
|
||||
caption: [Results]
|
||||
)
|
||||
|
||||
#indent_par[Although the kleinrock approximation never enters the confidence intervals obtained from the `pnet` simulator, for lower values of $ρ$, it is close to the confidence intervals. However for larger values of $ρ$, it starts to drift apart very noticeably.]
|
||||
#indent_par[Although the Kleinrock approximation never enters the confidence intervals obtained from the `pnet` simulator, for lower values of $ρ$, it is close to the confidence intervals. However for larger values of $ρ$, it starts to drift apart very noticeably.]
|
||||
|
||||
#pagebreak()
|
||||
|
||||
240
typst/exercises/15.typ
Normal file
240
typst/exercises/15.typ
Normal file
@ -0,0 +1,240 @@
|
||||
#import "@preview/tablex:0.0.6": tablex, rowspanx, colspanx
|
||||
#import "/typst/util.typ" as util: indent_par, code_figure
|
||||
|
||||
#indent_par[Using the following network in figure 22, adapted from the guide, we define the link numbers and routes in the following colors:]
|
||||
|
||||
- Flow 1: Red
|
||||
- Flow 2: Green
|
||||
- Flow 3: Blue
|
||||
- Flow 4: Cyan
|
||||
|
||||
#figure(
|
||||
image("/images/15-diagram.png", width: 75%),
|
||||
caption: "Network diagram"
|
||||
)
|
||||
|
||||
==== a. Kleinrock
|
||||
|
||||
#indent_par[Using the previously developed Kleinrock script, we obtained the following results in table 20:]
|
||||
|
||||
#figure(
|
||||
pad(1em, tablex(
|
||||
columns: (auto, 1fr, 1fr),
|
||||
align: center + horizon,
|
||||
|
||||
|
||||
rowspanx(2)[ Flow ],
|
||||
colspanx(2)[ Average packet delay ($"ms"$) ],
|
||||
|
||||
[ Per flow ],
|
||||
[ Network ],
|
||||
|
||||
[1],
|
||||
[73.2],
|
||||
rowspanx(4)[44.36],
|
||||
|
||||
[2],
|
||||
[31.2],
|
||||
|
||||
[3],
|
||||
[39.1],
|
||||
|
||||
[4],
|
||||
[7.81],
|
||||
|
||||
)),
|
||||
kind: table,
|
||||
caption: [Results]
|
||||
)
|
||||
|
||||
#pagebreak()
|
||||
|
||||
==== b.
|
||||
|
||||
#indent_par[We ran the `pnet` simulator 10 times, calculating 95% confidence intervals, and obtained the results in table 21:]
|
||||
|
||||
#indent_par[The network average packet delay was calculated from each flow's average delay via the following formula:]
|
||||
|
||||
$ W = (sum_i λ_i W_i) / (sum_j λ_j) $
|
||||
|
||||
#indent_par[We used the following parameters for the simulation:]
|
||||
|
||||
- ```R
|
||||
LinkCapacities <- replicate(7, 256 * 1000)
|
||||
```
|
||||
- ```R
|
||||
Flows <- list(
|
||||
list(rate = 215, packetsize = packet_size, route = c(1, 3, 6)),
|
||||
list(rate = 64, packetsize = packet_size, route = c(2, 5)),
|
||||
list(rate = 128, packetsize = packet_size, route = c(2, 5, 7)),
|
||||
list(rate = 128, packetsize = packet_size, route = c(4))
|
||||
)
|
||||
```
|
||||
- ```R
|
||||
endTime <- 10000 * (1 / 64) # 156.25
|
||||
```
|
||||
|
||||
#figure(
|
||||
pad(1em, tablex(
|
||||
columns: (auto, 1fr, 1fr),
|
||||
align: center + horizon,
|
||||
|
||||
|
||||
rowspanx(2)[ Flow ],
|
||||
colspanx(2)[ Average packet delay ($"ms"$) ],
|
||||
|
||||
[ Per flow ],
|
||||
[ Network ],
|
||||
|
||||
[1],
|
||||
[53.64 .. 57.33],
|
||||
rowspanx(4)[ 35.30 .. 37.15 ],
|
||||
|
||||
[2],
|
||||
[27.96 .. 28.80],
|
||||
|
||||
[3],
|
||||
[35.80 .. 36.72],
|
||||
|
||||
[4],
|
||||
[7.66 .. 7.84],
|
||||
)),
|
||||
kind: table,
|
||||
caption: [Results]
|
||||
)
|
||||
|
||||
#pagebreak()
|
||||
|
||||
==== c.
|
||||
|
||||
#indent_par[In order to determine the optimal bifurcation path, we first determine that the flow through the link $2 -> 4$ and $2 -> 5$ must be equal. Given that the flow 4 already uses the link $2 -> 5$, we must account for it in the calculations.]
|
||||
|
||||
#indent_par[With this in mind, we reach the following equation system 17, where $l_24$ is the flow through link $2 -> 4$ and $l_25$ is the flow through link $2 -> 5$]
|
||||
|
||||
$ cases( l_24 + l_25 = 215, l_24 = l_25 + 128 ) $
|
||||
|
||||
#indent_par[Solving these, we reach $l_24 = 171.5$ and $l_25 = 43.5$]
|
||||
|
||||
#indent_par[In order to compare against our results in exercise 15.a, we used the Kleinrock script and got the following results in table 22.]
|
||||
|
||||
#figure(
|
||||
pad(1em, tablex(
|
||||
columns: (auto, auto, 1fr, 1fr),
|
||||
align: center + horizon,
|
||||
|
||||
|
||||
rowspanx(2)[ Flow ],
|
||||
rowspanx(2)[ Bifurcation ],
|
||||
colspanx(2)[ Average packet delay ($"ms"$) ],
|
||||
|
||||
[ Per flow ],
|
||||
[ Network ],
|
||||
|
||||
rowspanx(2)[1],
|
||||
[1],
|
||||
rowspanx(2)[48.1],
|
||||
rowspanx(5)[36.19],
|
||||
|
||||
[2],
|
||||
|
||||
[2],
|
||||
rowspanx(3)[ N/A ],
|
||||
[31.2],
|
||||
|
||||
[3],
|
||||
[43.1],
|
||||
|
||||
[4],
|
||||
[11.8],
|
||||
|
||||
)),
|
||||
kind: table,
|
||||
caption: [Results]
|
||||
)
|
||||
|
||||
#indent_par[We can be sure that we have obtained the optimal bifurcation, because the average packet delay for each bifurcated flow has the same value. We also see that flow 2 was not affected at all, since flow 1 does not cross it on any of it's path or bifurcations. However, flow 3 and flow 4 have both been slightly affected due to the 2nd bifurcation of flow 1 passing through them. This is to be expected, as we are pushing more packets through the same links. Overall, the network average packet delay is lower, despite the increases to flow 3 and 4, due to flow 1 now having much lower delays.]
|
||||
|
||||
#pagebreak()
|
||||
|
||||
==== d.
|
||||
|
||||
#indent_par[We used the following parameters for the simulation of `bg.R`:]
|
||||
|
||||
- #text(size: 0.7em, ```R
|
||||
LinkCapacities <<- matrix(
|
||||
c(
|
||||
0, 256e3, 256e3, 0 , 0 , 0,
|
||||
0, 0 , 0 , 256e3, 256e3, 0,
|
||||
0, 0 , 0 , 0 , 256e3, 0,
|
||||
0, 0 , 0 , 0 , 0 , 256e3,
|
||||
0, 0 , 0 , 0 , 0 , 256e3,
|
||||
0, 0 , 0 , 0 , 0 , 0
|
||||
),
|
||||
nrow = 6,
|
||||
ncol = 6,
|
||||
byrow = TRUE
|
||||
)
|
||||
```)
|
||||
- #text(size: 0.7em, ```R
|
||||
Flows <<- matrix(
|
||||
c(
|
||||
1, 6, 215e3 + 128e3,
|
||||
1, 5, 64e3,
|
||||
2, 5, 128e3
|
||||
),
|
||||
nrow = 3,
|
||||
ncol = 3,
|
||||
byrow = TRUE
|
||||
)
|
||||
```)
|
||||
|
||||
#indent_par[Then obtained the results from the `bg.R` script in the following table 23:]
|
||||
|
||||
#figure(
|
||||
pad(1em, tablex(
|
||||
columns: (auto, auto, auto),
|
||||
align: center + horizon,
|
||||
|
||||
|
||||
[ Flow ],
|
||||
[ Rate ($"bits" s^(-1)$) ],
|
||||
[ Rate ($"packets" s^(-1)$) ],
|
||||
|
||||
[ $1 -> 2 -> 4 -> 6$ ], [ 170168 ], [ 170.168 ],
|
||||
[ $1 -> 3 -> 5 -> 6$ ], [ 172832 ], [ 172.832 ],
|
||||
[ $1 -> 2 -> 5 -> 6$ ], [ 0 ], [ 0 ],
|
||||
[ $1 -> 2 -> 5$ ], [ 39218 ], [ 39.218 ],
|
||||
[ $1 -> 3 -> 5$ ], [ 24782 ], [ 24.782 ],
|
||||
[ $2 -> 5$ ], [ 128000 ], [ 128.000 ],
|
||||
)),
|
||||
kind: table,
|
||||
caption: [Results]
|
||||
)
|
||||
|
||||
#indent_par[Finally, using our previously developed Kleinrock script to get the following results in table 24:]
|
||||
|
||||
#figure(
|
||||
pad(1em, tablex(
|
||||
columns: (auto, 1fr, 1fr, 1fr),
|
||||
align: center + horizon,
|
||||
|
||||
|
||||
colspanx(2, rowspanx(2)[ Flow ]),
|
||||
colspanx(2)[ Average packet delay ($"ms"$) ],
|
||||
|
||||
[ Per flow ],
|
||||
[ Network ],
|
||||
|
||||
[1], [ $1 -> 2 -> 4 -> 6$ ], [ 44.8 ],
|
||||
rowspanx(5)[ 35.87 ],
|
||||
|
||||
[2], [ $1 -> 3 -> 5 -> 6$ ], [ 46.3 ],
|
||||
[3], [ $1 -> 2 -> 5$ ], [ 32.7 ],
|
||||
[4], [ $1 -> 3 -> 5$ ], [ 34.3 ],
|
||||
[5], [ $2 -> 5$ ], [ 11.3 ],
|
||||
)),
|
||||
kind: table,
|
||||
caption: [Results]
|
||||
)
|
||||
|
||||
#indent_par[Comparing with our previous attempt at bifurcation in exercise 15.c, we see an small overall improvement to the network average packet delay. The gradient projection algorithm discovered 2 new flows we hadn't used, namely $1 -> 3 -> 5 -> 6$ and $1 -> 2 -> 5$. Despite outputting the flow $1 -> 2 -> 5 -> 6$, it has no rate, so we did not include it in the kleinrock script.]
|
||||
@ -100,3 +100,6 @@
|
||||
|
||||
=== 14. Exercise 14
|
||||
#include "exercises/14.typ"
|
||||
|
||||
=== 15. Exercise 15
|
||||
#include "exercises/15.typ"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user