The goal of this document is to introduce the main steps distilling a CPDnA like simulator as dicrete event engine.
The first step will be focused on defining the the structure of the netkork. Main hypothesis are: * The network topology is fixed. * The process KPI per node uses one time step. (output kpis at time t will be based on input kpi until t-1 * Different reporting wavelenghts are enabled. * Output times for nodes will be the maximum of their input kpis
It will be stored in a csv file, having * Label ID for the KPI (link) * Source Node ID * Sink Node ID * Wavelength of the reporting (0 when the link is internal) * The KPI will vary between 0 and 1 (normalized status), therefore it is defined if the optimal status is growing (+1) or decreasing (-1)
#
lnk=read.csv(file="links.csv",sep=",",header = TRUE,
stringsAsFactors = FALSE)
Every node has its own transference funtion, which fits into the expression: G(z)=exp(-kz) when the UPD is 1 or G(z)=1-exp(-kz) when UPD=-1 as it is normalized between 0 and 1 k(t+1) = sum(intg(kpi(i,t)))*w(i,t) i=1,…,Nj when j are the total links enering into the node j w(i,j) will represent the way of weighting and i can depend on t intg(kpi(i,t)) will represent how to proceed when several samples are reported (average, last, max(range), etc.) the value of the KPI. It is stored the node ID, the ID for coming KPI, the ID for the exiting KPI, the w expression and the operating function over the KPI
nod=read.csv(file="nodes.csv",sep=",",header = TRUE,
stringsAsFactors = FALSE)
# Let's update the updating freq for inner cpdna
updf=function(rowcp,links,nodes) {
if (rowcp[4]==0) {
idcp=rowcp[1]
idnod = unique(nodes[nodes[,4]==idcp,2])
if (length(idnod) > 1) {
cat(paste("Error ",idcp, "cpdna outputs more than one node:",idnod,sep=""))
exit;
} else {
idjcp = unique(nodes[(nodes[,2]==idnod & nodes[,4]==idcp),3])
valid = min(links[links$ID %in% idjcp,4])
res = max(links[links$ID %in% idjcp,4])
if (valid == 0 ) { # Not all the inner cpdna are already calculates
res = 0
}
}
} else {
res=rowcp[4]
}
return(res)
}
#
wij=function(t,txt){
res=eval(parse(text=txt))
if (res > 1 ) {
res = 1
}
if (res < 0) {
res = 0
}
return(res)
}
kpi=function(vkpi,txt){
res=eval(parse(text=txt))
if (res > 1 ) {
res = 1
}
if (res < 0) {
res = 0
}
return(res)
}
#
lnk[,6]=lnk[,4]
colnames(lnk)[6]="OldFrq"
iter = 0
crit = sum(lnk[,4]==0)
while (crit > 0 ) {
lnk[,4] = apply(lnk,1,updf,lnk,nod)
crit=sum(lnk[,4]==0)
iter = iter + 1
}
Because of the time being, each PO should behave better and better. This effect will be implemented by controlling the z factor of the G function
#
defz=function(t,T) {
z=t/T/3
if(z>1) {
z=1+log(z)
}
return(z)
}
Let’s define the function evaluating the CPDnA being outcome for the node I at time t+1 when input CPDnA at time t are available
#
e_cpdna=function(idcpdna,t,T,arr_cpdna=acpdna,links=lnk,nodes=nod) {
ni=links[links$ID==idcpdna,2]
vcpin = links[links[,3]==ni,1]
ff = links[idcpdna,4]
sgn= links[idcpdna,5]
if ( t %% ff != 0 ){ # It is not the right time to calculate
return(NA)
}
if ( sum(is.na(arr_cpdna[vcpin,t])) > 0 ) {
return(NA)
}
vt = 0
for (j in vcpin) {
nstps = floor(ff/links[j,4])
vkpi = as.double(arr_cpdna[j,((t-nstps+1):t)])
txtw = nodes[(nodes[,2]==ni & nodes[,3]==j & nodes[,4]==idcpdna),5]
txtkpi= nodes[(nodes[,2]==ni & nodes[,3]==j & nodes[,4]==idcpdna),6]
w = wij(t,txtw)
mkp = kpi(vkpi,txtkpi)
z = defz(t,T)
vt = vt + mkp*w
}
Gz = exp(-1/vt)
if ( sgn > 0 ) {
Gz = 1 - Gz
}
if (Gz > 1 ) {
Gz = 1
}
if (Gz < 0 ) {
Gz = 0
}
return(Gz)
}
#
t_cpdna=function(t,T,arr_cpdna=acpdna,links=lnk,nodes=nod) {
idx=t%%links[,4]==0
still = sum(is.na(arr_cpdna[idx,t]))
while (still > 0) {
jdx=(1:nrow(links))[is.na(arr_cpdna[,t]) & idx]
for (j in jdx) {
arr_cpdna[j,t]=e_cpdna(j,t,T,arr_cpdna,links,nodes)
}
still = sum(is.na(arr_cpdna[idx,t]))
}
return(arr_cpdna[,t])
}
#
random=function(i,T,a,b){
return(runif(T,a,b))
}
#
Starting with the feed-in cpdna (freq > 0 in links[,6]) we will run several times per time-step looking to fulfill the pending CPDnA values.
#
T=1000
results = as.data.frame(matrix(rep(NA,nrow(lnk)*T),nrow=nrow(lnk),ncol=T),
stringsAsFactors=FALSE,row.names=1:nrow(lnk),
col.names=1:T)
vecin = as.data.frame(lnk[lnk[,6]>0,1])
matrdm= t(apply(vecin,1,random,T,0,0.15))
results[as.vector(unlist(vecin)),]=matrdm
# Random Pick setup
npick = sample(1:nrow(vecin),1)
vpick = sample(1:2*nrow(lnk),npick,replace=TRUE)
for (i in 1:length(vpick)) {
matrdm[i,vpick[i]]=1
}
#
When all the parameters are setup, it’s time to run the simulation
#
ini = results
for (i in 1:T) {
results[,i]=t_cpdna(i,T,results,lnk,nod)
}
plot(seq(lnk[12,4],T,lnk[12,4]),as.double(
results[12,seq(lnk[12,4],T,lnk[12,4])]),
ylim=c(0,1),type="l")
#