library(ggplot2);library(magrittr); library(ggsci); library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
library(reshape2)
Rules (From McCue, 2005)
Ocean is an 8 x 5 “chessboard.” • Squares are 250 nm on a side. • A 12-boat wolf pack can search a square in a day. • The steps: 1. Update the wolf packs’ score. 2. Roll a die for each ongoing sighting, using theappropriate “rule of13rd” described below, to see ifit is converted into an attack. 3. Roll a die each convoy that is under attack to see if it gets rescued and returns to being unsighted, usingthe appropriate “rule of1/3rd” described below. 4. The SIGINT step: Assign a wolf pack to convergeupon any compromised convoy that is not yetthreatened. Then roll the die for ULTRA, if applica-ble, using the appropriate “rule of13rd” describedbelow, to return the convoy to unsighted status andthe corresponding pack to patrolling status. 5. Move the convoys as described below. 6. Move the packs as described below. 7. Check for new sightings. Any unsighted or threat-ened convoy in the same square as a wolf packbecomes sighted, including ones that just becameunsighted as a result of ULTRA
ConvoyTool = function(Width = 5, Depth = 8, phold = .66, DaysToMove = 2){
ConvoyMat = matrix(0, nrow = Width, ncol = Depth)
SubMat = matrix(0, nrow = Width, ncol = Depth)
Score = 0
turn = 0
#initialize Positions
StartX = 1
StartY = 1
ConvoyMat[StartX, StartY] = 1
SubX = sample(1:Width, 1)
SubY = sample(1:Depth, 1)
SubMat[SubX, SubY] = 1
#Score adjudicated when Wolfpack attacks a convoy
ConD = 0
### Loop over the game
while(ConD <= Depth){
ConvoyOld = ConvoyMat #Save a copy for below
if(which(ConvoyMat == 1) == which(SubMat == 1)){Score %<>% `+`(1)}
turn %<>% `+`(1)
ConW = which(ConvoyMat == 1, arr.ind = TRUE)[1]
ConD = which(ConvoyMat == 1, arr.ind = TRUE)[2]
#Move Convoy on Even Turns only
if(turn %% DaysToMove == 0){
ConD = ConD + 1
ConW = if(ConW == 1){ConW = 2
}else if(ConW == Width){
ConW = Width - 1
}else if(runif(1) < .5){
ConW = ConW - 1
}else{
ConW = ConW + 1
}
}
ConvoyMat[,] = 0
ConvoyMat[ConW, min(ConD, Depth)] = 1 #Min Statemetn prevents crashes
#Move Hunters
SubW = 1
SubD = 1 #Error generation for base cases
SubWOld = which(SubMat == 1, arr.ind = TRUE)[1]
SubDOld = which(SubMat == 1, arr.ind = TRUE)[2]
#If in contact, 2/3 chance to stay in contact
if(which(ConvoyOld == 1) == which(SubMat == 1)){
if(runif(1) < phold){
SubW = ConW
SubD = ConD
}
}else{ #Move the Hunters
if(SubWOld == 1){SubW = 2} else if(SubWOld == Width){
SubW = Width - 1} else if(runif(1) < .5){SubW = SubWOld -1}else{
SubW = SubWOld + 1
}
if(SubDOld == 1){SubD =2}else if(SubDOld == Depth){
SubD = Depth - 1}else if(runif(1) < .5){SubD = SubDOld -1} else{
SubD = SubDOld + 1
}
}
SubMat[,] = 0
SubMat[SubW, min(Depth, SubD)] = 1
}
return(Score)
}
ConvoyMaster = function(Nreps = 100, phold = .66, DaysToMove = 2){
Vec = rep(-1, length = Nreps)
for(i in 1:Nreps){
Vec[i] = ConvoyTool(Width = 5, Depth = 8, phold = phold, DaysToMove = DaysToMove)
}
return(Vec)
}
set.seed(2255)
Basic = ConvoyMaster(Nreps = 100) #Actual production had 10000 reps
sum(Basic==0)
## [1] 72
Contact = Basic[Basic>0]
theme_set(theme_minimal())
data.frame(Contact = Contact) %>% ggplot(aes(x = Contact)) + geom_density(color = 'darkblue') + ggtitle("Contact Days") + labs(subtitle = "Basic Convoy Model") + xlab("Contact Days") + scale_y_continuous(labels = scales::percent)
High Speed Excursion
set.seed(2255)
HighSpeed = ConvoyMaster(Nreps = 100, phold = .8, DaysToMove = 1)
#Let’s try starting the submarine closer to the convoy
ConvoyTool2 = function(Width = 5, Depth = 8, phold = .66, DaysToMove = 2){
ConvoyMat = matrix(0, nrow = Width, ncol = Depth)
SubMat = matrix(0, nrow = Width, ncol = Depth)
Score = 0
turn = 0
#initialize Positions
StartX = 1
StartY = 1
ConvoyMat[StartX, StartY] = 1
SubX = sample(1:3, 1)
SubY = sample(1:3, 1)
SubMat[SubX, SubY] = 1
#Score adjudicated when Wolfpack attacks a convoy
ConD = 0
### Loop over the game
while(ConD <= Depth){
ConvoyOld = ConvoyMat #Save a copy for below
if(which(ConvoyMat == 1) == which(SubMat == 1)){Score %<>% `+`(1)}
turn %<>% `+`(1)
ConW = which(ConvoyMat == 1, arr.ind = TRUE)[1]
ConD = which(ConvoyMat == 1, arr.ind = TRUE)[2]
#Move Convoy on Even Turns only
if(turn %% DaysToMove == 0){
ConD = ConD + 1
ConW = if(ConW == 1){ConW = 2
}else if(ConW == Width){
ConW = Width - 1
}else if(runif(1) < .5){
ConW = ConW - 1
}else{
ConW = ConW + 1
}
}
ConvoyMat[,] = 0
ConvoyMat[ConW, min(ConD, Depth)] = 1 #Min Statemetn prevents crashes
#Move Hunters
SubW = 1
SubD = 1 #Error generation for base cases
SubWOld = which(SubMat == 1, arr.ind = TRUE)[1]
SubDOld = which(SubMat == 1, arr.ind = TRUE)[2]
#If in contact, 2/3 chance to stay in contact
if(which(ConvoyOld == 1) == which(SubMat == 1)){
if(runif(1) < phold){
SubW = ConW
SubD = ConD
}
}else{ #Move the Hunters
if(SubWOld == 1){SubW = 2} else if(SubWOld == Width){
SubW = Width - 1} else if(runif(1) < .5){SubW = SubWOld -1}else{
SubW = SubWOld + 1
}
if(SubDOld == 1){SubD =2}else if(SubDOld == Depth){
SubD = Depth - 1}else if(runif(1) < .5){SubD = SubDOld -1} else{
SubD = SubDOld + 1
}
}
SubMat[,] = 0
SubMat[SubW, min(Depth, SubD)] = 1
}
return(Score)
}
ConvoyMaster2 = function(Nreps = 100, phold = .66, DaysToMove = 2){
Vec = rep(-1, length = Nreps)
for(i in 1:Nreps){
Vec[i] = ConvoyTool2(Width = 5, Depth = 8, phold = phold, DaysToMove = DaysToMove)
}
return(Vec)
}
set.seed(2255)
CloseStart = ConvoyMaster2(Nreps = 100, phold = .5, DaysToMove = 2)