"gen.data"<-function(funind,n=NULL,p=NULL){
if(is.null(n)) n=400
if(is.null(p)) p=1000
y0=NULL
if(funind<=4){
s=3*2^(funind-1)
u=matrix(rnorm(n*(p-50)),n,p-50)
v=matrix(rnorm(n*50),n,50)
w=u[,1:s]
wcoef=(-1)^(1:s+1)/5
x0=w%*%wcoef
x2=as.vector(x0)+sqrt(25-s)/5*v
x=cbind(u,x2)
betatrue=(-1)^(1:s+1)
y0=w%*%betatrue
y=y0+rnorm(n)*sqrt(3)
}  else if(funind==5){
s=3
x=matrix(rnorm(n*p),n,p)
x[,2]=-1/3*x[,1]^3+rnorm(n)
y0= x[,1]+x[,2]+x[,3]
y=y0+rnorm(n)*sqrt(3)
}
#if(funind<=4){
#s=3*2^(funind-1)
#u=matrix(rnorm(n*(p-50)),n,p-50)
#v=matrix(rnorm(n*50),n,50)
#w=u[,1:s]
#wcoef=(-1)^(1:s+1)/5
#x0=w%*%wcoef
#x2=as.vector(x0)+sqrt(25-s)/5*v
#x=cbind(u,x2)
#betatrue=(-1)^(1:s+1)
#y=w%*%betatrue+rnorm(n)
#}  else if(funind==5){
#s=3
#x=matrix(rnorm(n*p),n,p)
#x[,2]=-1/3*x[,1]^3+rnorm(n)
#y=x[,1]+x[,2]+x[,3]+rnorm(n)
#}
#
else if(funind==6){
s=4
x=matrix(runif(n*p),n,p)
y0=5*f1(x[,1])+3*f2(x[,2])+4*f3(x[,3])+6*f4(x[,4])
y=y0+rnorm(n)*sqrt(1.74)
} else if(funind==7){
s=4
w=matrix(runif(n*p),n,p)
u=runif(n)
x=(w+u)/2
y0=5*f1(x[,1])+3*f2(x[,2])+4*f3(x[,3])+6*f4(x[,4])
y=y0+rnorm(n)*sqrt(1.74)
} else if(funind==8){
s=12
x=matrix(runif(n*p),n,p)
y0=(f1(x[,1])+f2(x[,2])+f3(x[,3])+f4(x[,4])+
1.5*f1(x[,5])+1.5*f2(x[,6])+1.5*f3(x[,7])+1.5*f4(x[,8])+
2*f1(x[,9])+2*f2(x[,10])+2*f3(x[,11])+2*f4(x[,12]))
y=y0+rnorm(n)*sqrt(0.5184)
} else if(funind==9){
s=12
w=matrix(runif(n*p),n,p)
u=runif(n)
x=(w+u)/2
y0=(f1(x[,1])+f2(x[,2])+f3(x[,3])+f4(x[,4])+
1.5*f1(x[,5])+1.5*f2(x[,6])+1.5*f3(x[,7])+1.5*f4(x[,8])+
2*f1(x[,9])+2*f2(x[,10])+2*f3(x[,11])+2*f4(x[,12]))
y=y0+rnorm(n)*sqrt(0.5184)
} else if(funind==10){
s=4
x=matrix(rnorm(p*n, mean=0, sd=1), n, p)
betatrue <- c(2,2,2,-3*sqrt(2))
truerho=0.5
corrmat=diag(rep(1-truerho, p))+matrix(truerho, p, p)
corrmat[,4]=sqrt(truerho)
corrmat[4, ]=sqrt(truerho)
corrmat[4,4]=1
cholmat=chol(corrmat)
x=x%*%cholmat
y0 <- x[,1:s]%*%betatrue
y=y0+rnorm(n)
} else if(funind==11){
s=12
x=matrix(runif(n*p),n,p)
y=(f1(x[,1])+f2(x[,2])+f3(x[,3])+f4(x[,4])+
1.5*f1(x[,5])+1.5*f2(x[,6])+1.5*f3(x[,7])+1.5*f4(x[,8])+
2*f1(x[,9])+2*f2(x[,10])+2*f3(x[,11])+2*f4(x[,12]))+0.5*rnorm(n)*sqrt(0.5184)
} else if(funind==12){
s=12
w=matrix(runif(n*p),n,p)
u=runif(n)
x=(w+u)/2
y=(f1(x[,1])+f2(x[,2])+f3(x[,3])+f4(x[,4])+
1.5*f1(x[,5])+1.5*f2(x[,6])+1.5*f3(x[,7])+1.5*f4(x[,8])+
2*f1(x[,9])+2*f2(x[,10])+2*f3(x[,11])+2*f4(x[,12]))+0.5*rnorm(n)*sqrt(0.5184)
}  else if(funind>=18 & funind<=22)
{
s=4
x=matrix(runif(n*p),n,p)
y0=3*f1(x[,1])+3*f2(x[,2])+2*f3(x[,3])+2*f4(x[,4])
y=y0+rnorm(n)*sqrt(3.3843)*sqrt(2^(20-funind))
}   else if(funind>=28 & funind<=32)
{
s=4
w=matrix(runif(n*p),n,p)
u=runif(n)
x=(w+u)/2
y0=3*f1(x[,1])+3*f2(x[,2])+2*f3(x[,3])+2*f4(x[,4])
y=y0+rnorm(n)*sqrt(3.3843)*sqrt(2^(30-funind))
}
return(data=list(x=x,y=y,n=n,p=p,s=s,y0=y0))

}

f1<-function(x){x}
f2<-function(x){(2*x-1)^2}
f3<-function(x){sin(2*pi*x)/(2-sin(2*pi*x))}
f4<-function(x){0.1*sin(2*pi*x)+0.2*cos(2*pi*x)+0.3*sin(2*pi*x)^2+0.4*cos(2*pi*x)^3+0.5*sin(2*pi*x)^3}

simuNIS<-function(funind=NULL, repgroup=NULL, n=NULL, p=NULL, trace.it=NULL, knots=NULL, maxloop=NULL, eps0=NULL, randSeed = 0)
{
  if(is.null(funind)) stop('No given data generating scheme.')
  if(is.null(trace.it)) trace.it=FALSE
  if(is.null(maxloop)) maxloop=10
  if(is.null(eps0)) eps0=1e-6
  if(is.null(n)) n=400
  if(is.null(p)) p=1000
  if(is.null(knots)) knots=ceiling(n^0.2)

  trace.it=as.logical(trace.it)
  set.seed(randSeed)
    cat('Random seed=', randSeed, '...\n')
    data=gen.data(funind,n,p)
    testdata=gen.data(funind,n/2,p)

    greedINIS.fit = greedINIS(data, testdata,  knots=knots, eps0=eps0, DOISIS=TRUE,trace=trace.it)

    aINIS.fit = adaptINIS(data, testdata,  knots=knots, eps0=eps0, DOISIS=TRUE, maxloop=maxloop,trace=trace.it)

  return(list(greedyINIS = greedINIS.fit, INIS = aINIS.fit))
  #filename=paste(newpath,'/','funind=',funind,'_knots=',knots,'_r0=',r0,'_r1=',r1,'.RData',sep='')
  #save(aINIS.fit, greedINIS.fit, penGAM.fit,lmsis.fit,results,file=filename)
}

###########################################################################
#greedINIS: g-INIS algorithm, using knots=n^0.2
###########################################################################
greedINIS <- function(data, testdata=NULL, lambda.pen.list=NULL, folds=NULL, quant=NULL, gnum=1, kfold=NULL, knots=NULL,  eps0=1e-6, DOISIS=TRUE, maxloop=20, trace=FALSE, detailed=FALSE){
  t0=proc.time()[1]
  cat('starting greedINIS, g-INIS-penGAM algorithm, adatively choose number of variables\n')
  x=data$x
  y=data$y
  n <- nrow(x)
  p <- ncol(x)

  #if(is.null(nsis)) nsis=min(floor(n/log(n)),p-1)
  if(is.null(knots)) knots=ceiling(n^0.2)
  if(is.null(folds)) {
    temp= sample(1:n, n, replace = FALSE)
    if(is.null(kfold)) kfold=5
    for(i in 1:kfold){
      folds[[i]]=setdiff(1:n, temp[seq(i, n, kfold)])
    }
  }
  if(is.null(quant)) quant=1
  df0 <- knots+1

  xbs=matrix(0,n,df0*p)

  for(i in 1:p)
    xbs[,(i-1)*(df0)+(1:df0)]=ns(x[,i],df=df0)

  tempresi <- rep(0,p)

  curloop=1
  for(i in 1:p)
  {

    tempfit <-lm.fit (x=cbind(1,xbs[,(i-1)*df0+1:df0]),y=y)
    tempresi[i] <- sum(tempfit$residuals^2)
  }

  used.list<- tempresi

  used.sort <- sort(used.list, method= "sh", index=TRUE, decreasing=FALSE)
  initRANKorder <- used.sort$ix

  mindex <- sample(1:n)
  mresi=NULL
  for(i in 1:p){
    tempfit <-lm.fit (x=cbind(1,xbs[,(i-1)*df0+1:df0]),y=y[mindex])
    mresi[i] <- sum(tempfit$residuals^2)
  }
  resi.thres = quantile(mresi,1-quant)
  nsis <- min(sum(used.list<resi.thres), floor(n/df0/2),gnum)

  SISind <- sort(initRANKorder[1:nsis])
  if(!DOISIS) return (list(initRANKorder=initRANKorder, SISind=SISind, nsis=nsis))

  cat('loop ', curloop, '...SISind ', SISind,'\n')
  pick.ind=initRANKorder[1:nsis]

  xnew=x[,pick.ind]

  fit.tmp <- cv.penGAM(data=list(x=xnew,y=y), folds=folds, lambda.pen.list=NULL, knots=knots, eps0=eps0,cv.trace=trace)
  ISISind <- sort(pick.ind[fit.tmp$penGAMind])
  cat('loop ', curloop, '...ISISind ', ISISind,'\n')
  test= 1
  normal.exit = 1

  detail.pickind=NULL
  detail.ISISind=NULL
  detail.pickind=as.list(detail.pickind)
  detail.ISISind=as.list(detail.ISISind)

  detail.pickind[[curloop]]=pick.ind
  detail.ISISind[[curloop]]=ISISind

  if(length(ISISind)==0) {
    warnings('No variable was selected by this variant of ISIS.')
    normal.exit = 0
    if(detailed){
      return(list(fit=fit.tmp,initRANKorder=initRANKorder, detail.pickind=detail.pickind, detail.ISISind=detail.ISISind,
                  SISind=SISind, ISISind=ISISind,  nsis=nsis, normal.exit=normal.exit))
    } else
    {
      return(list(fit=fit.tmp,SISind=SISind, ISISind=ISISind))
    }
  }

  while(test){
    oldISISind=ISISind
    curloop=curloop+1
    remind <- setdiff(1:p, ISISind)

    tempresi=rep(0,length(remind))

    oldInd = rep(1:df0,length(ISISind))+df0*rep(ISISind-1,each=df0)

    for(i in 1:length(remind))
    {
      tempfit <-lm.fit (x=cbind(1,xbs[,c(oldInd,(remind[i]-1)*df0+1:df0)]),y=y)
      tempresi[i]<-sum(tempfit$residuals^2)
    }

    used.list<- tempresi

    used.sort <- sort(used.list, method= "sh", index=TRUE, decreasing=FALSE)

    mindex <- sample(1:n)
    mresi=NULL
    for(i in 1:length(remind))
    {
      tempfit <-lm.fit (x=cbind(1,xbs[,oldInd],xbs[mindex,(remind[i]-1)*df0+1:df0]),y=y)
      mresi[i] <- sum(tempfit$residuals^2)
    }
    resi.thres = quantile(mresi,1-quant)
    newind <- min(sum(used.list<resi.thres), floor(n/df0/2)-length(ISISind),gnum)

    if(newind==0)
    {
      test=0
      break
    }
    new.pickind <- sort(remind[used.sort$ix[1:newind]])

    pick.ind=c(ISISind, new.pickind)

    cat('loop ', curloop, '...SISind ', sort(pick.ind),'\n')
    xnew=x[,pick.ind]

    fit.tmp <- cv.penGAM(data=list(x=xnew,y=y), folds=folds, lambda.pen.list=NULL, knots=knots, eps0=eps0 ,cv.trace=trace)
    ISISind <- sort(pick.ind[fit.tmp$penGAMind])
    cat('loop ', curloop, '... ISISind ', ISISind,'\n')

    detail.pickind[[curloop]]=pick.ind
    detail.ISISind[[curloop]]=ISISind

    if(setequal(oldISISind, ISISind)) test=0
    if(curloop>=maxloop) {
      test=0
      normal.exit=0
    }

  }
  final.fit<-fit.tmp$fit
  cv.error<-fit.tmp$cv.error
  if(!is.null(testdata)){
    testx=testdata$x
    testy=testdata$y
    pred.error<-mean((predict(final.fit,as.matrix(testx[,pick.ind]))-testy)^2)
  } else pred.error=NULL

  ISISind=sort(ISISind)
  SISind=sort(SISind)
  ptime = proc.time()[1]-t0
  cat('finishing adaptINIS...\n')
  if(detailed){
    return(list(fit=fit.tmp, initRANKorder=initRANKorder, detail.pickind=detail.pickind, detail.ISISind=detail.ISISind,
                SISind=SISind, ISISind=ISISind,  nsis=nsis, cv.error=cv.error, pred.error=pred.error, ptime = ptime, normal.exit=normal.exit))
  } else
  {
    return(list(fit=fit.tmp, ISISind=ISISind, cv.error=cv.error, pred.error=pred.error, ptime = ptime, normal.exit=normal.exit))
  }
}

###########################################################################
#adaptINIS: INIS-penGAM algorithm, using knots=n^0.2
###########################################################################
adaptINIS <- function(data, testdata=NULL, lambda.pen.list=NULL, folds=NULL, quant=NULL, kfold=NULL, knots=NULL,  eps0=1e-6, DOISIS=TRUE, maxloop=10, trace=FALSE, detailed=FALSE){
  t0=proc.time()[1]
  cat('starting adaptINIS, INIS-penGAM algorithm, adatively choose number of variables\n')
  x=data$x
  y=data$y
  n <- nrow(x)
  p <- ncol(x)

  #if(is.null(nsis)) nsis=min(floor(n/log(n)),p-1)
  if(is.null(knots)) knots=ceiling(n^0.2)
  if(is.null(folds)) {
    temp= sample(1:n, n, replace = FALSE)
    if(is.null(kfold)) kfold=5
    for(i in 1:kfold){
      folds[[i]]=setdiff(1:n, temp[seq(i, n, kfold)])
    }
  }
  if(is.null(quant)) quant=1
  df0 <- knots+1

  xbs=matrix(0,n,df0*p)

  for(i in 1:p)
    xbs[,(i-1)*(df0)+(1:df0)]=ns(x[,i],df=df0)

  tempresi <- rep(0,p)

  curloop=1
  for(i in 1:p)
  {

    tempfit <-lm.fit (x=cbind(1,xbs[,(i-1)*df0+1:df0]),y=y)
    tempresi[i] <- sum(tempfit$residuals^2)
  }

  used.list<- tempresi

  used.sort <- sort(used.list, method= "sh", index=TRUE, decreasing=FALSE)
  initRANKorder <- used.sort$ix

  mindex <- sample(1:n)
  mresi=NULL
  for(i in 1:p){
    tempfit <-lm.fit (x=cbind(1,xbs[,(i-1)*df0+1:df0]),y=y[mindex])
    mresi[i] <- sum(tempfit$residuals^2)
  }
  resi.thres = quantile(mresi,1-quant)
  nsis <- max(min(sum(used.list<resi.thres), floor(n/df0/3)),2)

  SISind <- sort(initRANKorder[1:nsis])
  if(!DOISIS) return (list(initRANKorder=initRANKorder, SISind=SISind, nsis=nsis))

  cat('loop ', curloop, '...SISind ', SISind,'\n')
  pick.ind=initRANKorder[1:nsis]

  xnew=x[,pick.ind]

  fit.tmp <- cv.penGAM(data=list(x=xnew,y=y), folds=folds, lambda.pen.list=NULL, knots=knots, eps0=eps0,cv.trace=trace)
  ISISind <- sort(pick.ind[fit.tmp$penGAMind])
  cat('loop ', curloop, '...ISISind ', ISISind,'\n')
  test= 1
  normal.exit = 1

  detail.pickind=NULL
  detail.ISISind=NULL
  detail.pickind=as.list(detail.pickind)
  detail.ISISind=as.list(detail.ISISind)

  detail.pickind[[curloop]]=pick.ind
  detail.ISISind[[curloop]]=ISISind

  if(length(ISISind)==0) {
    warnings('No variable was selected by this variant of ISIS.')
    normal.exit = 0
    if(detailed){
      return(list(fit=fit.tmp,initRANKorder=initRANKorder, detail.pickind=detail.pickind, detail.ISISind=detail.ISISind,
                  SISind=SISind, ISISind=ISISind,  nsis=nsis, normal.exit=normal.exit))
    } else
    {
      return(list(fit=fit.tmp,SISind=SISind, ISISind=ISISind))
    }
  }

  while(test){
    oldISISind=ISISind
    curloop=curloop+1
    remind <- setdiff(1:p, ISISind)

    tempresi=rep(0,length(remind))

    oldInd = rep(1:df0,length(ISISind))+df0*rep(ISISind-1,each=df0)

    for(i in 1:length(remind))
    {
      tempfit <-lm.fit (x=cbind(1,xbs[,c(oldInd,(remind[i]-1)*df0+1:df0)]),y=y)
      tempresi[i]<-sum(tempfit$residuals^2)
    }

    used.list<- tempresi

    used.sort <- sort(used.list, method= "sh", index=TRUE, decreasing=FALSE)

    mindex <- sample(1:n)
    mresi=NULL
    for(i in 1:length(remind))
    {
      tempfit <-lm.fit (x=cbind(1,xbs[,oldInd],xbs[mindex,(remind[i]-1)*df0+1:df0]),y=y)
      mresi[i] <- sum(tempfit$residuals^2)
    }
    resi.thres = quantile(mresi,1-quant)
    newind <- min(sum(used.list<resi.thres), floor(n/df0/3)-length(ISISind))

    if(newind==0)
    {
      test=0
      break
    }
    new.pickind <- sort(remind[used.sort$ix[1:newind]])

    pick.ind=c(ISISind, new.pickind)

    cat('loop ', curloop, '...SISind ', sort(pick.ind),'\n')
    xnew=x[,pick.ind]

    fit.tmp <- cv.penGAM(data=list(x=xnew,y=y), folds=folds, lambda.pen.list=NULL, knots=knots, eps0=eps0 ,cv.trace=trace)
    ISISind <- sort(pick.ind[fit.tmp$penGAMind])
    cat('loop ', curloop, '... ISISind ', ISISind,'\n')

    detail.pickind[[curloop]]=pick.ind
    detail.ISISind[[curloop]]=ISISind
    for(testind in (curloop-1):1){
      if(setequal(detail.ISISind[[testind]], ISISind)){
        test=0
        break
      }
    }
    #if(setequal(oldISISind, ISISind)) test=0
    if(curloop>=maxloop) {
      test=0
      normal.exit=0
    }

  }
  final.fit<-fit.tmp$fit
  cv.error<-fit.tmp$cv.error
  if(!is.null(testdata)){
    testx=testdata$x
    testy=testdata$y
    pred.error<-mean((predict(final.fit,testx[,pick.ind])-testy)^2)
  } else pred.error=NULL

  ISISind=sort(ISISind)
  SISind=sort(SISind)
  ptime = proc.time()[1]-t0
  cat('finishing adaptINIS...\n')
  if(detailed){
    return(list(fit=fit.tmp, initRANKorder=initRANKorder, detail.pickind=detail.pickind, detail.ISISind=detail.ISISind,
                SISind=SISind, ISISind=ISISind,  nsis=nsis, cv.error=cv.error, pred.error=pred.error, ptime = ptime, normal.exit=normal.exit))
  } else
  {
    return(list(fit=fit.tmp, ISISind=ISISind, cv.error=cv.error, pred.error=pred.error, ptime = ptime, normal.exit=normal.exit))
  }
}

#########################################################################################################
compModelSize<-function(funind=NULL, n=NULL, p=NULL, repgroup=NULL,  r0=NULL, r1=NULL,  knots=NULL, maxloop=NULL, eps0=NULL, path=NULL)
{
  if(is.null(funind)) stop('No given data generating scheme.')

  if(is.null(eps0)) eps0=1e-6

  if(is.null(n)) n=400
  if(is.null(p)) p=1000
  if(is.null(knots)) knots=ceiling(n^0.2)
  if(is.null(r0)&is.null(r1)){
    if(is.null(repgroup))
    {
      r0=r1=1
    }
    else{
      r0=(repgroup-1)*10+1
      r1=(repgroup)*10
    }
  }

  if(is.null(path)) path='../'

  ########################################
  ####loading packages
  ########################################
  lib.loc=paste(path, 'packages', sep='')
  library(zoo, lib.loc=lib.loc)
  library(fda, lib.loc=lib.loc)
  library(grplasso, lib.loc=lib.loc)
  library(penGAM, lib.loc=lib.loc)
  library(SIS, lib.loc=lib.loc)

  library(mgcv)

  source('gen.datanew.r')

  newpath=paste('result',funind,sep='')
  if(!file.exists(newpath))
    dir.create(newpath)

  s0=gen.data(funind,n,p)$s
  truemodel<-1:s0

  sizelist=matrix(0,r1,3)
  outputfilename=paste('results/result', funind,'/',funind,'modelsize.txt',sep='')
  for(repind in r0:r1){
    set.seed(repind)
    cat('Random seed=', repind, '...\n')
    data=gen.data(funind,n,p)
    sizelist[repind,]=c(getSISSize(data,truemodel=truemodel),getPenGamSize(data,truemodel=truemodel),getLmSISSize(data,truemodel=truemodel))
    cat(repind,sizelist[repind,],'\n',sep=' ',file=outputfilename, append=T)
  }

  filename=paste('result', funind,'/',funind,'_r0=',r0,'_r1=',r1,'modelsize.RData',sep='')

  save(truemodel,sizelist,file=filename)
}
#######################################################################################################
#######################################################################################################
cv.penGAM<- function(data, testdata=NULL, knots=NULL, folds=NULL, kfold=NULL, lambda.pen.list=NULL, model=LinReg(), control = grpl.control(trace=0),
                     eps0=1e-6 ,cv.trace=FALSE, detailed=FALSE){
  t0=proc.time()[1]
  x=data$x
  y=data$y
  x=as.matrix(x)
  n=nrow(x)

  if(is.null(folds)) {
    temp= sample(1:n, n, replace = FALSE)
    if(is.null(kfold)) kfold=5
    for(i in 1:kfold){
      folds[[i]]=setdiff(1:n, temp[seq(i, n, kfold)])
    }
  }
  kfold=length(folds)
  if(is.null(knots)) knots=ceiling(n^0.2)

  if(is.null(lambda.pen.list)){
    lambda.pen.list=seq(1,0.02,-0.02)
  }
  error <- rep(0, length(lambda.pen.list))
  if(cv.trace) cat('Beginning Cross Validation.....\n')

  for(i in 1:kfold){
    if(cv.trace) cat('Cross Validation...', 'fold ', i,'...\n')
    train <- folds[[i]]
    test <- setdiff(1:n, folds[[i]])
    fit <- penGAM(as.matrix(x[train,]), y[train], lambda.pen=lambda.pen.list, lambda.curv=0,
                  knots=knots, model=LinReg(), control = grpl.control(trace=0))
    fit.pred <- predict(fit, as.matrix(x[test,]))
    fit.mat<-t(fit.pred[,1,])
    error <- error+apply((fit.mat-y[test])^2,2,mean)
  }

  if(cv.trace) cat('Ending Cross Validation.....\n')
  best.lambda.pen.ind <- (1:length(lambda.pen.list))[which.min(error)]

  fit <- penGAM(x, y, lambda.pen=lambda.pen.list[best.lambda.pen.ind], lambda.curv=0,
                knots=knots, model=LinReg(), control = grpl.control(trace=0))

  cv.error <- mean((predict(fit,x)-y)^2)

  coef.mat <- matrix(fit$coef[1,1,][-1],nrow=knots+2,ncol=ncol(x))

  coef.norm <- apply(coef.mat^2, 2, sum)

  non.zero.ind <- which(coef.norm>eps0)

  if(!is.null(testdata)){
    testx=as.matrix(testdata$x)
    testy=testdata$y
    pred.error<-mean((predict(fit,testx)-testy)^2)
  } else pred.error=NULL

  ptime = proc.time()[1]-t0
  if(detailed){
    return (list=list(fit=fit, best.lambda.pen.ind=best.lambda.pen.ind, best.lambda=lambda.pen.list[best.lambda.pen.ind],
                      penGAMind=non.zero.ind, cv.error=cv.error, pred.error=pred.error, penGAMfit=fit, ptime = ptime))
  }
  else
  {
    return (list=list(fit=fit, penGAMind=non.zero.ind, cv.error=cv.error, pred.error=pred.error, ptime = ptime))
  }

}
########################################################################################
getSISSize <- function(data, truemodel,  knots=NULL){
  x = data$x
  y = data$y
  n = nrow(x)
  p = ncol(x)

  if(is.null(knots)) knots=ceiling(n^0.2)
  df0 <- knots+1

  xbs=matrix(0,n,df0*p)

  for(i in 1:p)
    xbs[,(i-1)*(df0)+(1:df0)]=ns(x[,i],df=df0)

  tempresi <- rep(0,p)

  curloop=1
  for(i in 1:p)
  {

    tempfit <-lm.fit (x=cbind(1,xbs[,(i-1)*df0+1:df0]),y=y)
    tempresi[i] <- sum(tempfit$residuals^2)
  }

  used.list<- tempresi

  used.sort <- sort(used.list, method= "sh", index=TRUE, decreasing=FALSE)
  amsis.ind <- used.sort$ix

  for(i in 1:p)
  {
    if(length(setdiff(truemodel,amsis.ind[1:i]))==0) {
      amsis.size=i
      break
    }
  }

  return(amsis.size)

}
#######################################################################################
########################################################################################
getPenGamSize <- function(data,  truemodel, lambda.pen.list=NULL, knots=NULL, eps0=1e-6){
  x = data$x
  y = data$y
  n = nrow(x)
  p = ncol(x)
  if(is.null(knots)) knots=ceiling(n^0.2)
  if(is.null(lambda.pen.list)){
    lambda.max=0.99
    lambda.pen.list=lambda.max*(2^seq(0,-10,-0.1))
  }
  lam.len=length(lambda.pen.list)

  fit <- penGAM(x, y, lambda.pen=lambda.pen.list, lambda.curv=0,
                knots=knots, model=LinReg(), control = grpl.control(trace=0))

  coef.mat <- array(fit$coef[,1,-1],c(lam.len,knots+2,p))

  coef.norm <- apply(coef.mat^2, c(1,3), sum)

  nonzeros = coef.norm[,truemodel]>eps0;
  lambdas = apply(nonzeros, 1, all);
  ##str(fit.a);

  pickone = max(which(lambdas==F))+1;

  if (pickone==lam.len+1){
    mlasso <- p;
  }
  if (pickone<lam.len+1){
    mlasso <- sum(coef.norm[pickone,]>eps0);
  }
  return(mlasso)

}

########################################################################################
getLmSISSize <- function(data, truemodel){
  x = data$x
  y = data$y
  n = nrow(x)
  p = ncol(x)

  lmsis.corr <- NULL
  for(i in 1:p)
  {
    lmsis.corr[i] <- -abs(cor(x[,i],y))
  }
  lmsis.sort <- sort(lmsis.corr, method= "sh", index=TRUE, decreasing=FALSE)
  lmsis.ind <- lmsis.sort$ix

  for(i in 1:p)
  {
    if(length(setdiff(truemodel,lmsis.ind[1:i]))==0) {
      lmsis.size=i
      break
    }
  }
  return(lmsis.size)

}
########################################################################################
getAmSISSize <- function(data, truemodel, rank.method='corr'){
  x = data$x
  y = data$y
  n = nrow(x)
  p = ncol(x)
  q <- ceiling(n^0.2)
  amsis.corr <- NULL
  amsis.resi <- NULL
  amsis.norm <- NULL
  for(i in 1:p)
  {
    #if(i%%(round(p/10))==0) cat('First Step:', round(i*100/p), 'percent complete\n')
    amsis.fit <-gam (y~s(x[,i],k=q,fx=TRUE, bs="cr"))
    amsis.corr[i] <- mean(fitted(amsis.fit)*y)
    amsis.resi[i] <- amsis.fit$deviance
    amsis.norm[i] <- sum(fitted(amsis.fit)^2)
  }
  amsis.list<-switch(rank.method, corr=-amsis.corr, resi=amsis.resi, norm=-amsis.norm)
  amsis.sort <- sort(amsis.list, method= "sh", index=TRUE, decreasing=FALSE)
  amsis.ind <- amsis.sort$ix
  lmsis.corr <- NULL
  for(i in 1:p)
  {
    lmsis.corr[i] <- -abs(cor(x[,i],y))
  }
  lmsis.sort <- sort(lmsis.corr, method= "sh", index=TRUE, decreasing=FALSE)
  lmsis.ind <- lmsis.sort$ix

  for(i in 1:p)
  {
    if(length(setdiff(truemodel,amsis.ind[1:i]))==0) {
      amsis.size=i
      break
    }
  }
  for(i in 1:p)
  {
    if(length(setdiff(truemodel,lmsis.ind[1:i]))==0) {
      lmsis.size=i
      break
    }
  }
  return(size=list(amsis.size=amsis.size,lmsis.size=lmsis.size))

}
####################

####################################################
#######################################################################################
##################################################
"gen"<-function(n,p,funind,t=0){
  if(funind==4){
    w=matrix(runif(n*p),n,p)
    u=runif(n)
    v=runif(n)
  } else {
    w=truncnorm.gen(n,p)
    u=as.vector(truncnorm.gen(n,1))
    v=as.vector(truncnorm.gen(n,1))
  }
  x=matrix(0,n,p)
  x[,1:4]=(w[,1:4]+t*u)/(1+t)
  x[,5:p]=(w[,5:p]+t*v)/(1+t)
  epsi=rnorm(n)
  s=3
  y=switch(funind, -3+3*x[,1]+4*x[,2]-8*x[,3]+5*x[,4]+epsi, -7+8*x[,1]-3*x[,2]+10*x[,3]^3-6*x[,4]*(x[,4]-1)+epsi , -5+8*x[,1]^3+10*x[,2]*(1-x[,2])-10*x[,3]^5-8*x[,4]^2+epsi, -4+4*x[,1]+cos(2*pi*x[,2])-8*x[,3]^3+sqrt(x[,4]*(1-x[,4]))*sin(2*pi*(1+2^((9-4*s)/5))/(x[,4]+2^((9-4*s)/5)))+epsi)
  data=list(x=x,y=y)
}

############################################################################################################

"truncnorm.gen"<-function(n,p){
  norm.trunc<-rnorm(n*p)
  ind= abs(norm.trunc)>2
  test=sum(ind)
  count=0
  while(test>0){
    tmp=rnorm(test)
    test=sum(abs(tmp)>2)
    norm.trunc[ind]= tmp
    ind=abs(norm.trunc)>2
  }
  abs(matrix(norm.trunc,n,p))/2
}


# setwd(dirname(rstudioapi::getActiveDocumentContext()$path))

#########################################################################
# Dependencies

# library(purrr)
# library(glmnet)

#########################################################################
# Tuning parameter

.Lambdahat <- function(X, t = .05, m = 500){
  n <- nrow(X)
  g <- rnorm(n * m, 0, 1)
  map(1:m, ~ (X * rnorm(n, 0, 1)) %>%
        apply(2, sum) %>%
        max) %>%
    as.numeric %>%
    quantile(1 - t)
}

.lambda <- function(X, sigma0hat, t = 0.05, c = 1.1) {  2 * c * sigma0hat * .Lambdahat(X, t = t) / nrow(X) }

.sigma0_u.hat <- function(y, x, beta_est) { sd(y - x %*% beta_est) }

#########################################################################
# Estimation

# First-stage
.lambda_j.Alpha0hat <- function(X, Z, sigma0_v, tune_type = "CV"){
  px <- ncol(X); pz <- ncol(Z)
  if ( tune_type == "CV") {
    # fits <- map(1:px, ~ cv.glmnet(Z, X[,.], intercept = FALSE, nfolds = 5)) %>%
    # ncores <- 100
    # cl <- makeCluster(ncores, type="FORK")
    # fits <- parLapply(cl, 1:px, function(j) cv.glmnet(Z, X[,j], intercept=F, nfolds=5))
    # stopCluster(cl)
    fits <- lapply(1:px, function(j) cv.glmnet(Z, X[,j], intercept=F, nfolds=5))
    fits <- fits %>%
      map(~ list(lambda_j = .$lambda.min,
                 alpha0_jhat = coef(., s = "lambda.min")))
  } else {
    if ( tune_type == "semioracle" ) {
      sigma0_vhat <- sigma0_v
    } else if ( tune_type == "feasible" ) {
      # ...
    }
    lambda <- .lambda(Z, sigma0_vhat)
    fits <- map(1:px, ~ list(X_j = X[,.], fit = glmnet(Z, X[,.], intercept = FALSE))) %>%
      map(~ list(lambda_j = lambda,
                 alpha0_jhat = predict(.$fit, type = "coefficients",
                                       s = lambda, exact = TRUE, x = Z, y = .$X_j)))
  }
  Alpha0hat <- map(fits, ~ as.numeric(.$alpha0_jhat)[2:(pz+1)]) %>%
    reduce(cbind) %>% { colnames(.) <- NULL; . }
  list(lambda_j = map_dbl(fits, ~ .$lambda_j), Alpha0hat = Alpha0hat)
}

# Second-stage
.lambda.beta_Lasso <- function(y, Dhat, sigma0_u, tune_type = "CV", no_pen_ids = c()) {
  px <- ncol(Dhat)
  if ( length(no_pen_ids)==0 ) {
    penalties <- rep(1, px)
  } else {
    penalties <- rep(1, px); penalties[no_pen_ids] <- 0
  }
  if ( tune_type == "CV") {
    res <- cv.glmnet(Dhat, y, intercept = FALSE, standardize=F, nfolds = 5, penalty.factor=penalties) %>%
    { list(lambda = .$lambda.min,
           beta_Lasso = as.numeric(coef(., s = "lambda.min"))[2:(px+1)]) }
  } else {
    if ( tune_type == "infeasible" ) {
      sigma0_u.hat <- sigma0_u
    } else if ( tune_type == "feasible" ) {
      # ...
    }
    lambda <- .lambda(Dhat, sigma0_u.hat)
    res <- glmnet(Dhat, y, intercept = FALSE, penalty.factor=penalties) %>%
    { list(lambda = lambda,
           beta_Lasso = as.numeric(predict(., type = "coefficients", s = lambda,
                                           exact = TRUE, x = Dhat, y = y))[2:(px+1)]) }
  }
  res
}

# Empirical Gram matrix
.Sigmahat <- function(x) { (t(x) %*% x) / nrow(x) }

find_mus <- function(Sigma.hat) {
  ##########################
  # Using lpSolve
  #
  # px <- ncol(Sigma.hat)
  # Id <- diag(1, px)
  # zeros <- matrix(ncol=px,nrow=px); zeros[,] <- 0
  #
  # c1 <- cbind(Sigma.hat, -1*Sigma.hat, -1*Id, rep(0, px))
  # c2 <- cbind(-1*Sigma.hat, Sigma.hat, -1*Id, rep(0, px))
  # c3 <- cbind(zeros, zeros, diag(1, px), rep(-1, px))
  # A <- rbind(c1, c2, c3)
  #
  # obj <- c(rep(0, 3*px), 1)
  # dir <- rep("<=", 3*px)
  # mus <- lapply(
  #   1:px,
  #   function(j) {
  #     b1.j <- rep(0,px); b1.j[j] <- -1
  #     b2.j <- rep(0,px); b2.j[j] <- 1
  #     b3.j <- rep(0,px)
  #     b.j <- c(b1.j, b2.j, b3.j)
  #     res.j <- lp(direction="min", objective.in=obj, const.mat=A, const.dir=dir, const.rhs=b.j)
  #     res.j$objval
  #   }
  # ) %>% as.numeric
  # mus

  ##########################
  # Using Mosek

  px <- ncol(Sigma.hat)
  Id <- diag(1, px)
  zeros <- matrix(ncol=px,nrow=px); zeros[,] <- 0
  mus <- numeric(px)

  # constraint marix A
  A1 <- cbind(Sigma.hat, -Id, rep(0,px))
  A2 <- cbind(-Sigma.hat, -Id, rep(0,px))
  A3 <- cbind(zeros, Id, rep(-1, px))
  A <- rbind(A1, A2, A3) %>%
    Matrix(sparse=T)

  # lower bounds on variables
  blx <- c(rep(-Inf, px), rep(0, px), 0)
  bux <- c(rep(Inf, 2*px), Inf)

  objective <- c(rep(0,2*px), 1)

  for ( j in 1:px ){
    blc <- rep(-Inf, 3*px)
    buc1 <- rep(0, px); buc1[j] <- 1
    buc2 <- rep(0, px); buc2[j] <- -1
    buc3 <- rep(0, px)
    buc <- c(buc1, buc2, buc3)

    mosek.prob <- list(
      sense="min",
      c=objective,
      A=A,
      bc=rbind(blc, buc),
      bx=rbind(blx, bux)
      )
    mosek.res <- try(mosek(mosek.prob, list(verbose=0, soldetail=1)), silent=TRUE)
    mus[j] <- mosek.res$sol$bas$pobjval
  }
  mus
}

.Theta.hat_JM <- function(Sigma.hat, n) {
  Theta.hat <- InverseLinfty(Sigma.hat, n)
  Theta.hat
}

.Theta.hat_CLIME <- function(Sigma.hat, mus) {
  #################################
  # lpSolve method

  # px <- ncol(Sigma.hat)
  # c1 <- lapply(1:px,
  #              function(j) { a <- rep(0,3*px); a[j] <- -1; a[j+px] <- 1; a[j+2*px] <- -1; a } ) %>%
  #   reduce(rbind)
  # c2 <- lapply(1:px,
  #              function(j) { a <- rep(0,3*px); a[j] <- 1;a[j+px] <- -1; a[j+2*px] <- -1; a } ) %>%
  #   reduce(rbind)
  # c3 <- lapply(1:px,
  #              function(j) { c(-1*Sigma.hat[j,], Sigma.hat[j,], rep(0, px)) }) %>%
  #   reduce(rbind)
  # c4 <- lapply(1:px,
  #              function(j) { c(Sigma.hat[j,], -1*Sigma.hat[j,], rep(0, px)) }) %>%
  #   reduce(rbind)
  # A <- rbind(c1, c2, c3, c4)
  # dir <- rep("<=", 4*px)
  # obj <- c(rep(0,px), rep(0,px), rep(1,px))
  #
  # Theta.hat <- lapply(
  #   1:px,
  #   function(j) {
  #     mu <- mus[j]
  #     b1 <- rep(mu, px); b1[j] = mu-1
  #     b2 <- rep(mu, px); b2[j] = mu+1
  #     b <- c(rep(0, 2*px), b1, b2)
  #     res_j <- lp(direction="min", objective.in=obj, const.mat=A, const.dir=dir, const.rhs=b)
  #     theta_j <- res_j$solution[1:px] - res_j$solution[(px+1):(2*px)]
  #     theta_j
  #   }
  # ) %>%
  #   reduce(rbind)
  # Theta.hat

  #################################
  # Mosek method

  px <- ncol(Sigma.hat)
  Id <- diag(1, px)
  zeros <- matrix(ncol=px,nrow=px); zeros[,] <- 0
  Theta.hat <- matrix(ncol=px,nrow=px)

  # constraint matrix
  A1 <- cbind(Id, -1*Id)
  A2 <- cbind(-1*Id, -1*Id)
  A3 <- cbind(Sigma.hat, zeros)
  A4 <- cbind(-1*Sigma.hat, zeros)
  A <- rbind(A1, A2, A3, A4) %>%
    Matrix(sparse=T)

  # lower and upper bounds on variables
  blx <- c(rep(-Inf, px), rep(0, px))
  bux <- rep(Inf, 2*px)

  objective <- c(rep(0,px), rep(1,px))

  for ( j in 1:px ) {
    mu <- mus[j]

    # lower and upper bounds on constraints
    blc <- rep(-Inf, 4*px)
    buc3 <- rep(mu, px); buc3[j] <- mu+1
    buc4 <- rep(mu, px); buc4[j] <- mu-1
    buc <- c(rep(0, 2*px), buc3, buc4)

    mosek.prob <- list(
      sense="min",
      c=objective,
      A=A,
      bc=rbind(blc, buc),
      bx=rbind(blx, bux)
      )
    mosek.res <- try(mosek(mosek.prob, list(verbose=0)), silent=TRUE)
    Theta.hat[j,] <- mosek.res$sol$bas$xx[1:px]
  }
  Theta.hat
}

# De-biased second-stage Lasso estimation

.beta_debiased <- function(y, X, Dhat, beta_Lasso, Thetahat) {
  n <- length(y)
  lambda_kappahat <- t(Dhat) %*% (y - Dhat %*% beta_Lasso) / n
  beta_debiased <- beta_Lasso + Thetahat %*% lambda_kappahat + (Thetahat %*% t(Dhat) %*% (Dhat - X) %*% beta_Lasso)/n
  beta_debiased
}

#########################################################################
# Standard errors

# SE1
# This is given by sigma_u.hat * theta_j^T * Sigma_d.hat * theta_j
.SE1 <-function(Sigma_d.hat, Theta.hat, sd_u.hat) {
  sd_u.hat * (Theta.hat %*% Sigma_d.hat %*% t(Theta.hat)) %>% diag %>% sqrt
}

# SE2
# This is given by E_n[{theta_j, d_i}^2u_i^2] %>% sqrt
.SE2 <- function(D.hat, Theta.hat, u.hat) {
  # n <- length(u.hat); p <- ncol(D.hat)
  (Theta.hat %*% t(D.hat)) %>%
    apply(1, function(X) { mean(X^2 * u.hat^2) }) %>%
    sqrt
}

# SE3
# This is given by sigma_u.hat *
.SE3 <- function(Theta.hat, sd_u.hat) {
  sqrt(diag(Theta.hat)) * sd_u.hat
}


# écriture de stochastic_model sans array
# avec output true

# modèle simplifié

# écart de production -------------------
og <- lagog + dog
dog <- og_lag * (lagog - lag2og) +
  - og_mce * (lagog - 0) +
  og_k * ib + og_noise

update(lagog) <- og
update(lag2og) <- lagog
update(og_noise) <- ogn_ar * og_noise + rnorm(0, ogn_sigma)

# dette ------------
dette <- lagdette + ddette
update(lagdette) <- dette
update(lag2dette) <- lagdette
ddette <- lagrho*lagdette - surplus

# rho écart critique
rho <- lagrho + drho
update(lagrho) <- rho
drho <- -rho_mce*(lagrho - rhostar) + rho_d*(lagdette - dstarr)

# surplus
surplus <- lagsurplus + sur_og * (og - lagog) - ib
update(lagsurplus) <- surplus
update(lag2surplus) <- lagsurplus

# règle budgétaire --------------
sstar <- rhostar*dstar

ib <- tpo_sstar * (lagsurplus - sstar ) + tpo_1sstar * (lagsurplus - lag2surplus) + tpo_sstar2 * (lagsurplus - sstar)^2 +
      tpo_dstar * (lagdette - dstar) + tpo_1dstar * (lagdette - lag2dette) + tpo_dstar2 * (lagdette - dstar)^2 +
      tpo_og*(lagog) + tpo_og2*(lagog)^2 + tpo_1og*(lagog - lag2og) +
      tpo_rho*(rho - rhostar) +
      phi[step]

# fonction de perte ----------------------
# utilisée pour la partie optimisation
update(loss_d_only) <- loss_d_only + loss_d * (step >= loss_t)*(lagdette - dstar)^2
initial(loss_d_only) <- 0
update(loss_no_d) <- loss_no_d + og^2/(1+loss_df)^(step-1) + loss_dog * (og-lagog)^2 + loss_ib * (ib)^2
initial(loss_no_d) <- 0

# sorties ------

update(dettep_o) <- dette
update(og_o) <- og
update(surplus_o) <- surplus
update(ib_o) <- ib
update(rho_o) <- rho
update(loss_o) <- loss_no_d + loss_d_only
update(loss_nd_o) <- loss_no_d

initial(surplus_o) <- 0
initial(og_o) <- 0
initial(dettep_o) <- 0
initial(ib_o) <- 0
initial(rho_o) <- 0
initial(loss_o) <- 0
initial(loss_nd_o) <- 0

# init ----------------
i_lagog <- user(0)
i_lag2og <- user(0)
i_lagrho <- user(0)
i_lagdette <- user(1)
i_lagsurplus <- user(-0.01)
i_lag2surplus <- user(-0.01)
i_lag2dette <- user(1)

## Initial conditions
# initial(og) <- init_og
initial(lagog) <- i_lagog
initial(lag2og) <- i_lag2og
initial(og_noise) <- i_ogn
initial(lagrho) <- i_lagrho
initial(lagdette) <- i_lagdette
initial(lag2dette) <- i_lag2dette
initial(lagsurplus) <- i_lagsurplus
initial(lag2surplus) <- i_lag2surplus

# params -------------
periods <- user(50)

## parameters
og_lag   <- user(0)
og_mce   <- user(0.15)
og_k <- user(0.7)
rho_d <- user(0.01)
rho_mce <- user(0.15)
dstar <- user(0.6)
dstarr <- user(0.6)
tpo_sstar <- user(0.4)
tpo_dstar <- user(-0.1)
tpo_sstar2 <- user(0)
tpo_1sstar <- user(0)
tpo_dstar2 <- user(0)
tpo_1dstar <- user(0)
tpo_1og <- user(0)
tpo_og <- user(0)
tpo_og2 <- user(0)
tpo_rho <- user(0)
loss_df <- user(0.02)
loss_ib <- user(0)
ogn_ar <- user(0)
ogn_sigma <- user(0.005)
rhostar <- user(-0.015)
i_ogn <- user(0.005)
sur_og <- user(0.5)

# loss
loss_dog <- user(0)
loss_d <- user(0.5)
loss_t <- user(20)

# controls&exogenes -----------
phi[] <- user(0)

dim(phi) <- periods


# take input from the user
num = as.integer(readline(prompt = "Enter a number: "))
if(num < 0) {
print("Enter a positive number")
} else {
sum = 0
# use while loop to iterate until zero
while(num > 0) {
sum = sum + num
num = num - 1
}
print(paste("The sum is", sum))
}


# 4. faza: Analiza podatkov

#LINEARNA REGRESIJA

library(ggplot2)
library(GGally)

g <- ggplot(tabela_tri_zdruzene, aes(x=skupaj.x, y=skupaj.y)) + geom_point()
graf13 <- g + geom_smooth(method="lm", formula=y ~ x) + labs(x = "Število prebivalcev (v stotisočicah)", y = "Število dijakov", title = "Število dijakov v Sloveniji na leto  \nglede na število prebivalcev v istem letu")

p <- ggplot(tabela_tri_zdruzene, aes(x=skupaj.x, y=skupaj)) + geom_point()
graf14 <- p + geom_smooth(method="lm", formula=y ~ x)+ labs(x = "Število prebivalcev (v stotisočicah)", y = "Število diplomantov", title = "Število diplomantov v Sloveniji na leto  \nglede na število prebivalcev v istem letu")


#' Calculate TSI values from input data
#'
#' This function calculates TSI values according to Utah's IR methods from input data containing values for of chlorophyll, total phosphorus, and secchi disk depth.
#' Note that inputs for these parameters must be specified in units of ug/L, mg/L, and meters, respectively.
#' @param x Input dataset
#' @param in_format One of "wide" or "flat" to specify data input format. Note that only wide format inputs are currently supported.
#' @param chl_ugL Name of chlorophyll-a variable in ug/L
#' @param TP_mgL Name of total phosphorus variable in mg/L
#' @param SD_m Name of secchi disk depth variable in m
#' @examples
#' data(ul_trophic)
#' head(ul_trophic)
#' tsi=calcTSI(ul_trophic,chl_ugL="ChlA",TP_mgL="Phosphate.phosphorus.Total",SD_m="Depth.Secchi.disk.depth")
#' head(tsi)
#' plot(TSIchl~ChlA,tsi)

#' @export
calcTSI=function(x,in_format="wide",chl_ugL="Chlorophyll a",TP_mgL="Phosphate-phosphorus",SD_m="Depth, Secchi disk depth", value_var='ResultMeasureValue', param_var='CharacteristicName'){
#x=trophic_data
#x=within(x, {
#	IR_Value[IR_Value == 0] = 0.001
#})
#any(x[,'IR_Value'] == 0, na.rm=T)
#chl_ugL="Chlorophyll a"
#TP_mgL="Phosphate-phosphorus"
#SD_m="Depth, Secchi disk depth"
#value_var='IR_Value'
#param_var='CharacteristicName'

#default input units: chla (ug/L), TP (mg/L), SD (m)
	if(in_format=="wide"){
		TSIchl=9.81*log(x[,chl_ugL])+30.6
		TSItp=14.2*log(x[,TP_mgL]*1000)+4.15
		TSIsd=60-14.41*log(x[,SD_m])
		tsi=cbind(x, TSIchl, TSItp, TSIsd)
	}
	if(in_format=="flat"){
		x$TSI=NA
		x$TSI[x[,param_var] == chl_ugL] = 9.81*log(x[x[,param_var]==chl_ugL,value_var])+30.6
		x$TSI[x[,param_var] == TP_mgL] =14.2*log(x[x[,param_var]==TP_mgL,value_var]*1000)+4.15
		x$TSI[x[,param_var] == SD_m] = 60-14.41*log(x[x[,param_var]==SD_m,value_var])
		tsi=x
	}
	return(tsi)
}


#' f_smoothh1
#'
#' Construct the $K_\tau K_1$ vector $h_1$
#'
#' @param n1 matrix n1 output from f_n1
#' @param g1 $G_1$ diagonal matrix
#' @param g2 $G_2$ diagonal matrix
#' @param sigmatau $\Sigma_tau$ diagonal matrix
#'
#'
#' @return $K_\tau K_1$ vector $H_1$
#'
#' @examples
#' \dontrun{
#' devtools::load_all()
#'k1 <- 4; ktau <- 4; m1 <- 4; mtau <- 4; n <- 400
#' v_dim <- c(ktau + mtau, k1 + m1)
#' v_x <- runif(n); v_y <- log(v_x); sigma <- 0.4 * (0.5 + v_x)
#' n1 <- f_n1(v_x, k1, m1); beta <- rnorm(prod(v_dim[1], v_dim[2]))
#' m_sigmatau <- f_sigmatau(v_dim[1])
#' m_g1 <- f_g1(ktau, mtau)
#' m_g2 <- f_g2(ktau, mtau)
#' #h1
#' m_h1 <- f_smoothh1(n1, m_g1, m_g2, m_sigmatau)
#' m_h1$h1
#' m_h1$h0
#' }
f_smoothh1 <- function(n1, g1, g2, sigmatau) {
    #form N^{m_tau+1}(1) and N^{m_tau+2}(\tau)|_0^1
    nm1 <- rep(0, nrow(sigmatau)); nm1[nrow(sigmatau)] <- 1
    h_1 <- nm1 - tcrossprod(g2, sigmatau) %*% nm1
    h_1 <- tcrossprod(g1, sigmatau) %*% h_1
    h_1 <- kronecker(h_1, t(n1))
    h_1 <- rowSums(h_1)

    h_0 <- tcrossprod(g1, sigmatau) %*% nm1
    h_0 <- kronecker(h_0, t(n1))
    h_0 <- 0.5 * rowSums(h_0) - h_1
    return(list(h1 = h_1,
                h0 = h_0))
}

#' f_smoothres
#'
#' Construct the $n n_tau$ residual vector
#'
#' @param ndesign   design matrix $n n_\tau \times K_\tau K_1$ $N(\tau, x)$
#' @param v_y       vector of observations y_i
#' @param sigma  $\Sigma$ diagonal matrix
#' @param til_beta  tilde_beta coefficients
#'
#' @param h         bandwidth value
#' @return $n n_tau$ residual vector
#'
#'
#' @examples
#' \dontrun{
#' s_ntau <- 500; v_taus <- seq(0, 1, length.out = s_ntau)
#' m_ndesign <- kronecker(f_ntau(v_taus, ktau, mtau), n1)
#' m_sigma <- f_sigma(ktau + mtau, k1 + m1)
#' til_beta <- tilde_beta(beta, k1 + m1)
#' h <- max((((log(n) + 1) / n) ^ 0.4), 0.05)
#' v_res <- f_smoothres(m_ndesign, v_y, m_sigma, til_beta)
#' }
f_smoothres <- function(ndesign, v_y, sigma, til_beta, h) {
    #Calculate the residual
    c(ndesign %*% sigma %*% til_beta - v_y) / h
}

#' f_smoothhtau
#'
#' Construct the $K_\tau K_1$ vector $h_\tau$
#'
#' @param ndesign   design matrix $n n_\tau \times K_\tau K_1$ $N(\tau, x)$
#' @param pres  error function of the $K_\tau n_tau$ residual vector devided by h
#' @param s_ntau    number of taus values
#'
#'
#' @return $K_\tau K_1$ vector $h_\tau$
#'
#'
#' @examples
#' \dontrun{
#' s_ntau <- 500; v_taus <- seq(0, 1, length.out = s_ntau)
#' m_ndesign <- kronecker(f_ntau(v_taus, ktau, mtau), n1)
#' m_sigma <- f_sigma(ktau + mtau, k1 + m1)
#' til_beta <- tilde_beta(beta, k1 + m1)
#' h <- max((((log(n) + 1) / n) ^ 0.4), 0.05)
#'
#' ptm <- proc.time()# Start the clock!
#' v_res <- f_smoothres(m_ndesign, v_y, m_sigma, til_beta)
#' print(proc.time() - ptm)# Stop the clock
#' #Using the Gaussian kernel
#' v_pres <- pnorm(v_res)
#' m_htau <- f_smoothhtau(m_ndesign, v_pres, h, s_ntau)
#' }
f_smoothhtau <- function(ndesign, pres, s_ntau) {
    c(crossprod(pres, ndesign) / s_ntau)
}

#' f_smoothderiv
#'
#' Construct the $K_\tau K_1$ gradient vector for the loss
#'
#' @param til_beta the current estimation fro $\tilde{\beta}$
#' @param v_dim vector contain the dimension of covariates
#'             $(K_\tau, K_1, K_2, K_3, \cdots)$
#'
#' @param m_sigma $K_\tau K_1K_2 \times K_1K_2 \Sigma$ diagonal block matix.
#' @param h1 $K_\tau K_1K_2$ vector
#' @param h2 $K_\tau K_1K_2$ vector
#'
#'
#' @return the $K_\tau K_1$ gradient vector for the loss
#'
#' @examples
#' \dontrun{
#' f_smoothderiv(til_beta, v_dim, m_sigma, m_htau, m_h1)
#' }
f_smoothderiv <- function(til_beta, v_dim, m_sigma, htau, h1) {
    m_c <- f_matc(v_dim, til_beta)
    lossderiv <- m_c %*% crossprod(m_sigma, (htau - h1))
    return(c(lossderiv))
}

#' f_smoothgrad
#'
#' Construct the $K_\tau K_1K_2$ gradient vector for $\beta$
#'
#' @param beta the current estimation fro $\beta$
#' @param loss_deriv the derivative of the loss
#' @param s $K_\tau K_1K_2 \times K_1K_2$ $S$ matrix
#'
#'
#' @return the $K_\tau K_1K_2$ gradient vector for $\beta$
#'
#' @examples
#' \dontrun{
#' f_grad(beta, v_lossderiv, m_s)
#' }
f_smoothgrad <- function(beta, loss_deriv, s) {
    loss_deriv + c(s %*% beta)
}

#' f_smoothloss
#'
#' Return the quantile loss criteria
#'
#' @param res   $K_\tau n_tau$ residual vector
#' @param pres  error function of the $K_\tau n_tau$ residual vector devided by h
#' @param h0sig    $K_\tau K_1$ vector $H_0$ times m_sigma
#' @param til_beta  estimation for $\tilde{\beta}$
#'
#' @param s_ntau    number of taus values
#' @param h bandwidth value
#' @param s_n number of observation
#'
#' @return the smooth quantile loss
#'
f_smoothloss <- function(res, pres, h0sig, til_beta,
                        s_ntau, h, s_n) {
    loss <- crossprod(h0sig, til_beta)
    resloss <- h / 2 * sqrt(2 / pi) * sum(exp(- (- res / 2)^2))
    resloss <- resloss - crossprod(res, (1 - 2 * pres))
    loss <- loss + resloss / s_ntau
    return(c(loss) / s_n)
}

#' f_smoothcrit
#'
#' Return the smooth QR criteria
#'
#' @param res   $n n_tau$ residual vector
#' @param pres  error function of the $K_\tau n_tau$ residual vector devided by h
#' @param h0sig    $K_\tau K_1$ vector $H_0$ times m_sigma
#' @param til_beta  estimation for $\tilde{\beta}$
#' @param beta the current estimation for $\beta$
#'
#' @param s_ntau    number of taus values
#' @param h bandwidth value
#' @param s_n number of observation
#' @param s $K_1K_2 \times K_1K_2$ $S$ matrix
#'
#' @return the smooth quantile criteria
#'
f_smoothcrit <- function(res, pres, h0sig, til_beta, beta,
                        s_ntau, h, s_n, s) {
    loss <- f_smoothloss(res, pres, h0sig, til_beta, s_ntau, h, s_n)
    criteria <- loss + crossprod(beta, s %*% beta)
    return(c(criteria))
}

#' f_smoothbbgd
#'
#' The descent algorithm using bb stepsize
#'
#' @param v_y   vector of y
#' @param v_x   vector of x
#' @param v_k0  vector of internal knots for covariates
#' @param v_m   vector of orders for covariates
#'
#' @param init initialization for $\beta$
#' @param h     bandwidth value
#' @param s_ntau    number of taus for numerical integration
#' @param v_smooth  vector of smoothing parameters
#' @param maxit maximum number of iterations
#' @param eps   stopping critria threshhold
#' @param eta   stopping criteria for gradient size
#' @param trace indicator whether to plot trace
#'
#'
#' @return the estimated $\beta$
#'
f_smoothbbgd <- function(v_y, v_x, v_k0, v_m, init = NULL,
                        v_smooth = rep(1, 3),
                        h=max((((log(length(v_y))+1)/length(v_y))^0.4), 0.05),
                        s_ntau = 200,
                        maxit = 1e4, eps = 1e-3, eta = 1e-3,
                        trace = NULL, echostep = F) {

#-------------------------------------------------------
##### set up #####
#-------------------------------------------------------
    function_call <- match.call()
    x_ord <- order(v_x)
    v_x <- v_x[x_ord]
    v_y <- v_y[x_ord]
    s_center <- mean(v_x)
    s_sd <- sd(v_x)
    v_x <- c(scale(v_x))
    iter <- 0L
    converge <- F
    s_n <- length(v_y)
    #Define dimensions
    k1 <- v_k0[2]; ktau <- v_k0[1]; m1 <- v_m[2]; mtau <- v_m[1]
    v_dim <- v_k0 + v_m
    #Require
    m_n1 <- f_n1(v_x, k1, m1)
    m_g1 <- f_g1(ktau, mtau)
    m_g2 <- f_g2(ktau, mtau)
    m_sigmatau <- f_sigmatau(v_dim[1])
    m_sigma <- f_sigma(v_dim[1], v_dim[2])
    m_s <- f_mats(v_dim[1], v_dim[2], v_smooth)
    # Set up design matrix
    v_taus <- seq(0, 1, length.out = s_ntau)
    m_ndesign <- kronecker(f_ntau(v_taus, ktau, mtau), m_n1)

    #Precalculate h1, h0, h0 * Sigma
    m_h1 <- f_smoothh1(m_n1, m_g1, m_g2, m_sigmatau)
    m_h0 <- m_h1$h1
    m_h1 <- m_h1$h1
    v_h0sig <- c(crossprod(m_h0, m_sigma))

    #Initialization
    if (is.null(init)) {
        init <- f_init(v_y, v_x, m_sigma, m_n1, v_k0, v_m, m_s)
    }
    til_beta0 <- init
    v_beta0 <- og_beta(til_beta0, v_dim[1], v_dim[2])
    v_grad0 <- 0

    #Calculate v_res (most time consuming)
    v_res <- f_smoothres(m_ndesign, v_y, m_sigma, til_beta0, h)
    #Using the Gaussian kernel for h_\tau
    v_pres <- pnorm(v_res)
    m_htau <- f_smoothhtau(m_ndesign, v_pres, s_ntau)

    ##Loss
    s_loss <- f_smoothcrit(v_res, v_pres, v_h0sig, til_beta0, v_beta0,
                            s_ntau, h, s_n, m_s)

    ##trace
    if (!is.null(trace)) {
        v_taus <- trace
        con_quan <- list(x = v_x, y = v_y, center = s_center, sd = s_sd,
                    v_k0 = v_k0, v_m = v_m, m_sigma = m_sigma, n1 = m_n1,
                    til_beta = til_beta0)
        sub <- paste("Iter:", iter, ", Error=", round(s_loss, 3))
        main <- paste("Smoothing:", v_smooth[1:2], "dim:", v_dim)
        cq_plot(trace, con_quan, sub = sub, main = main)
    }

    #Standard gradient updates
    v_deriv <- f_smoothderiv(til_beta0, v_dim, m_sigma, m_htau, m_h1)
    v_grad1 <- f_smoothgrad(v_beta0, v_deriv / s_n, m_s)

    #Calculate new coefficients
    v_beta1 <- v_beta0 - v_grad1
    til_beta1 <- tilde_beta(v_beta1, v_dim[2])
    new_loss <- f_smoothcrit(v_res, v_pres, v_h0sig, til_beta1, v_beta1,
                            s_ntau, h, s_n, m_s)

    #Repeat
    while (maxit > iter) {
        iter <- iter + 1

        #Calculate difference
        v_delta <- v_beta1 - v_beta0
        v_gdiff <- v_grad1 - v_grad0

        #bb stepsize
        s_delgrad <- crossprod(v_delta, v_gdiff)
        if (s_delgrad < 0) {
            if (echostep) print(s_delgrad)
            s_step <- 1
        } else  {
            step1 <- crossprod(v_delta) / s_delgrad
            step2 <- s_delgrad / crossprod(v_gdiff)
            s_step <- min(step1, step2, 10)
            if (echostep) print(s_step)
        }

        #update v_beta0, til_beta0, v_grad0, s_loss
        v_beta0 <- v_beta1
        til_beta0 <- til_beta1
        v_grad0 <- v_grad1
        s_loss <- new_loss

        #Calculate v_res (most time consuming)
        v_res <- f_smoothres(m_ndesign, v_y, m_sigma, til_beta0, h)
        #Using the Gaussian kernel for h_\tau
        v_pres <- pnorm(v_res)
        m_htau <- f_smoothhtau(m_ndesign, v_pres, s_ntau)

        #Calculate gradient
        v_deriv <- f_smoothderiv(til_beta0, v_dim, m_sigma, m_htau, m_h1)
        v_grad1 <- f_smoothgrad(v_beta0, v_deriv / s_n, m_s)

        #Update v_beta1, til_beta1
        v_beta1 <- v_beta0 - s_step * v_grad1
        til_beta1 <- tilde_beta(v_beta1, v_dim[2])
        new_loss <- f_smoothcrit(v_res, v_pres, v_h0sig, til_beta1, v_beta1,
                            s_ntau, h, s_n, m_s)

        ##trace
        if (!is.null(trace)) {
            con_quan$til_beta <- til_beta1
            sub <- paste("Iter:", iter, ", Error=", round(new_loss, 3))
            cq_plot(trace, con_quan, sub = sub, main = main)
        }

        #Check stop criterion
        if (is.null(eta)) {
            converge <- (abs(new_loss - s_loss) <= eps * abs(s_loss))
        } else {
            converge <- (norm_2(v_grad1) / norm_2(v_beta0) <= eta)
        }

        #If gradient size criteria
        if (is.na(converge)) {
            converge <- F
            break
        }
        if (converge) break

    }

#-------------------------------------------------------
##### Output #####
#-------------------------------------------------------
    out <- list(
        beta = v_beta1,
        til_beta = til_beta1,
        gradient = v_grad1,
        converge = converge,
        grad_size = sum(v_grad1 ^ 2),
        iter = iter,
        loss = s_loss,
        x = v_x,
        y = v_y,
        center = s_center,
        sd = s_sd,
        v_k0 = v_k0,
        v_m = v_m,
        n1 = m_n1,
        m_sigma = m_sigma,
        mat_s = m_s,
        call = function_call)

    return(out)
}

#' f_smoothdescent
#'
#' The descent algorithm using back tracking line search stepsize
#'
#' @param v_y   vector of y
#' @param v_x   vector of x
#' @param v_k0  vector of internal knots for covariates
#' @param v_m   vector of orders for covariates
#'
#' @param init initialization for $\beta$
#' @param alpha threshold $\alpha$, within $(0, 0.5)$.
#' @param bet   shrinkage rate $\bet$, within $(0, 1)$.
#' @param v_smooth  vector of smoothing parameters
#' @param maxit maximum number of iterations
#' @param eps   stopping critria threshhold
#' @param eta   stopping criteria for gradient size
#' @param trace indicator whether to plot trace
#'
#'
#' @return the estimated $\beta$
#'
f_smoothdescent <- function(v_y, v_x, v_k0, v_m, init = NULL,
                        alpha = 0.3, bet = 0.8, v_smooth = rep(1, 3),
                        h=max((((log(length(v_y))+1)/length(v_y))^0.4), 0.05),
                        s_ntau = 200,
                        maxit = 1e4, eps = 1e-3, eta = NULL, trace = NULL) {

#-------------------------------------------------------
##### set up #####
#-------------------------------------------------------
    function_call <- match.call()
    x_ord <- order(v_x)
    v_x <- v_x[x_ord]
    v_y <- v_y[x_ord]
    s_center <- mean(v_x)
    s_sd <- sd(v_x)
    v_x <- c(scale(v_x))
    iter <- 0L
    converge <- F
    s_n <- length(v_y)
    #Define dimensions
    k1 <- v_k0[2]; ktau <- v_k0[1]; m1 <- v_m[2]; mtau <- v_m[1]
    v_dim <- v_k0 + v_m
    #Require
    m_n1 <- f_n1(v_x, k1, m1)
    m_g1 <- f_g1(ktau, mtau)
    m_g2 <- f_g2(ktau, mtau)
    m_sigmatau <- f_sigmatau(v_dim[1])
    m_sigma <- f_sigma(v_dim[1], v_dim[2])
    m_s <- f_mats(v_dim[1], v_dim[2], v_smooth)
    # Set up design matrix
    v_taus <- seq(0, 1, length.out = s_ntau)
    m_ndesign <- kronecker(f_ntau(v_taus, ktau, mtau), m_n1)

    #Precalculate h1, h0, h0 * Sigma
    m_h1 <- f_smoothh1(m_n1, m_g1, m_g2, m_sigmatau)
    m_h0 <- m_h1$h1
    m_h1 <- m_h1$h1
    v_h0sig <- c(crossprod(m_h0, m_sigma))

    #Initialization
    if (is.null(init)) {
        init <- f_init(v_y, v_x, m_sigma, m_n1, v_k0, v_m, m_s)
    }
    til_beta <- init
    v_beta <- og_beta(til_beta, v_dim[1], v_dim[2])
    v_grad <- 0

    #Calculate v_res (most time consuming)
    v_res <- f_smoothres(m_ndesign, v_y, m_sigma, til_beta, h)
    #Using the Gaussian kernel for h_\tau
    v_pres <- pnorm(v_res)
    m_htau <- f_smoothhtau(m_ndesign, v_pres, s_ntau)

    ##Loss
    s_loss <- f_smoothcrit(v_res, v_pres, v_h0sig, til_beta, v_beta,
                            s_ntau, h, s_n, m_s)

    ##trace
    if (!is.null(trace)) {
        v_taus <- trace
        con_quan <- list(x = v_x, y = v_y, center = s_center, sd = s_sd,
                    v_k0 = v_k0, v_m = v_m, m_sigma = m_sigma, n1 = m_n1,
                    til_beta = til_beta)
        sub <- paste("Iter:", iter, ", Error=", round(s_loss, 3))
        main <- paste("alpha=", alpha, "beta=", bet,
                "Smoothing:", v_smooth[1:2], "dim:", v_dim)
        cq_plot(trace, con_quan, sub = sub, main = main)
    }

    #Repeat
    while (maxit > iter) {
        iter <- iter + 1
        #Calculate gradient
        v_deriv <- f_smoothderiv(til_beta, v_dim, m_sigma, m_htau, m_h1)
        v_grad <- f_smoothgrad(v_beta, v_deriv / s_n, m_s)
        grad_size <-  sum(v_grad ^ 2)
        #backtracking line search
        t <- 1
        repeat{
            new_beta <- v_beta - t * v_grad
            new_tilbeta <- tilde_beta(new_beta, v_dim[2])
            new_loss <- f_smoothcrit(v_res, v_pres, v_h0sig,
                                new_tilbeta, new_beta,
                                s_ntau, h, s_n, m_s)
            t <- bet * t
            if (new_loss <= (s_loss - alpha * t * grad_size) || t < 1e-4) {
                break
            }
        }

        #Update v_beta
        v_beta <- new_beta
        til_beta <- new_tilbeta

        #Calculate v_res (most time consuming)
        v_res <- f_smoothres(m_ndesign, v_y, m_sigma, til_beta, h)
        #Using the Gaussian kernel for h_\tau
        v_pres <- pnorm(v_res)
        m_htau <- f_smoothhtau(m_ndesign, v_pres, s_ntau)

        ##trace
        if (!is.null(trace)) {
            con_quan$til_beta <- til_beta
            sub <- paste("Iter:", iter, ", Error=", round(new_loss, 3))
            cq_plot(trace, con_quan, sub = sub, main = main)
        }

        #Check stop criterion
        if (is.null(eta)) {
            converge <- (abs(new_loss - s_loss) <= eps * abs(s_loss))
        } else {
            converge <- (sqrt(grad_size) / norm_2(v_beta) <= eta)
        }

        s_loss <- new_loss
        #If gradient size criteria
        if (is.na(converge)) {
            converge <- F
            break
        }
        if (converge) break

    }

#-------------------------------------------------------
##### Output #####
#-------------------------------------------------------
    out <- list(
        beta = v_beta,
        til_beta = til_beta,
        gradient = v_grad,
        converge = converge,
        grad_size = sum(v_grad ^ 2),
        iter = iter,
        loss = s_loss,
        x = v_x,
        y = v_y,
        center = s_center,
        sd = s_sd,
        v_k0 = v_k0,
        v_m = v_m,
        n1 = m_n1,
        m_sigma = m_sigma,
        mat_s = m_s,
        alpha = alpha,
        bet = bet,
        call = function_call)

    return(out)
}


state_prediction <- function(obs,delta,gamma,lls,param_lls,h)
  {
  m <- ncol(gamma)
  n <- length(obs)

  p <- function(state, x){
    lls[[state]](x, param_lls[[state]])
  }
  p <- Vectorize(p)

  p_mat <- outer(1:m, obs, p)
  log_p_mat <- log(p_mat)

  log_delta <- log(delta)
  log_gamma <- log(gamma)
  log_alpha <- forward_logprobabilities(obs, gamma, p, delta)

  log_theta <- rep(NA, m)
  k <- max(log_alpha[, n])
  denominator <- k + log(sum(exp(log_alpha[, n] - k)))
  log_theta <- log_alpha[, n] - denominator

  log_gamma_power <- matrix(0, nrow = m, ncol = m)
  for(i in 1:h){
    log_gamma_power <- log_gamma + log_gamma_power
  }

  log_prob <- rep(NA, m)
  for(i in 1:m){
    temp <- log_gamma_power[,i] + log_theta
    k <- max(temp)
    log_prob[i] <- k + log(sum(exp(temp - k)))
  }

  exp(log_prob)
}


model_deterministic_simulateR <- function(init_obs, period_start, times, pars, fix_pars){
  ode_solveR <- function(stage_pars, fix_pars, old_values) {
    ## stage pars
    b = stage_pars[1]
    r = stage_pars[2]
    ## fixed pars
    alpha_p = fix_pars[1]
    alpha_u = fix_pars[2]
    beta_1 = fix_pars[3]
    beta_2 = fix_pars[4]
    delta_1 = fix_pars[5]
    delta_2 = fix_pars[6]
    lambda = fix_pars[7]
    mu = fix_pars[8]
    mu_c = fix_pars[9]
    De = fix_pars[10]
    Dr = fix_pars[11]
    f = fix_pars[12]
    N = fix_pars[13]
    ## old values
    S = old_values[1]
    E = old_values[2]
    U = old_values[3]
    P = old_values[4]
    F = old_values[5]
    RU = old_values[6]
    RR = old_values[7]
    DU = old_values[8]
    DR = old_values[9]
    ## new values

    S_new = S - b * S * (alpha_p * P + alpha_u * U + F) / N + lambda * N - mu * S
    E_new = E + b * S * (alpha_p * P + alpha_u * U + F) / N - E / De - mu * E
    U_new = U + (1 - r) * E / De - U / (beta_1 * Dr) - delta_1 * mu_c * U - mu * U
    P_new = P + r * (1 - f) * E / De - P / Dr - mu_c * P - mu * P
    F_new = F + r * f * E / De - F * beta_2 / Dr - mu_c * F / delta_2 - mu * F
    RU_new <- RU + U / (beta_1 * Dr) + F * beta_2 / Dr - mu * RU
    RR_new <- RR + P / Dr - mu * RR
    DU_new <- DU + delta_1 * mu_c * U + mu_c * F / delta_2
    DR_new <- DR + mu_c * P
    est_P_new_n <- E
    est_P_new_prob <- r * (1 - f) / De
    est_RD_new_n <- P
    est_RD_new_prob_R <- 1 / Dr
    est_RD_new_prob_D <- mu_c

    return(c(S_new, E_new, U_new, P_new, F_new, RU_new, RR_new, DU_new, DR_new,
             est_P_new_n, est_P_new_prob,
             est_RD_new_n, est_RD_new_prob_R, est_RD_new_prob_D))
  }
  n_period = length(period_start)
  ymat = matrix(0, length(times), length(init_obs) + 6)
  ymat[, 1] = times

  colnames(ymat) <- c("time", names(init_obs), "est_p_n", "est_p_prob", "est_RD_n", "est_RD_prob_R", "est_RD_prob_D")

  which.period <- function(i, phase = period_start){ # function to determine which period i falls in
    sum(i >= phase)
  }

  for(i in 1:length(times)){
    stage_pars <- c(b = pars[which.period(i)], r = pars[n_period + which.period(i)])
    if(i == 1) {
      old_values <- init_obs
    } else {
      old_values <- ymat[i - 1, 2:10]
    }
    ymat[i, 2:15] <- ode_solveR(stage_pars = stage_pars, fix_pars = fix_pars, old_values = old_values)
  }

  return(ymat)
}


#   Copyright (C) 2019  Dr. Norbert Bátfai, nbatfai@gmail.com
#
#   This program is free software: you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation, either version 3 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program.  If not, see <http://www.gnu.org/licenses/>

library(matlab)

stp <- function(x){

    primes = primes(x)
    diff = primes[2:length(primes)]-primes[1:length(primes)-1]
    idx = which(diff==2)
    t1primes = primes[idx]
    t2primes = primes[idx]+2
    rt1plust2 = 1/t1primes+1/t2primes
    return(sum(rt1plust2))
}

x=seq(13, 1000000, by=10000)
y=sapply(x, FUN = stp)
plot(x,y,type="b")


#' @title Fitting bivariate MGL copula models for two continuous data
#' @description \code{MGL.mle} is used to fit bivariate copula regression models via maximum likelihood (ML) method for two continuous variables.
#' @param U two-dimensional matrix with values in \eqn{[0,1]}.
#' @param copula copula 'MGL', 'MGL180', "MGL-EV", "MGL-EV180", "MGB2", "Normal" , "t".
#' @param hessian Logical. Should a numerically differentiated Hessian matrix be returned?
#' @param initpar Initial values for the parameters to be optimized over.
#' @param ... additional arguments, see \code{\link[stats]{nlm}} for more details.
#' @importFrom stats nlm
#' @md
#' @details
#' The estimation method is performed via \code{\link[stats]{nlm}} function.
#'
#' copula:
#' * "MGB2" is multivariate GB2.
#' * "Normal" and "t" denote the Gaussian copula and Student-t copula respectively.
#' * "MGL" and "MGL-EV" denote the MGL and MGL-EV copula respectively.
#' * "MGL180" and "MGL-EV180" denote the survival MGL and survival MGL-EV copula respectively.
#' * "Gumbel" is Gumbel copula.
#'
#' @return A list containing the following components:
#' * loglike: the value of the estimated maximum of the loglikelihood function.
#' * copula: the name of the fitted copula. "MGL180" and "MGL-EV180" denote the survival MGL and MGL-EV copula respectively.
#' * estimates: the point at which the maximum value of the loglikelihood is obtained.
#' * se: the standard errors of the estimators.
#' * AIC, BIC: the goodness fit of the regression models.
#' * hessian: the hessian at the estimated maximum of the loglikelihood (if requested).
#'
#' @references Zhang, F. Z. . "A generalized beta copula with applications in modeling multivariate long-tailed data." Insurance: Mathematics and Economics (2011).
#'
#' @examples
#'   library(rMGLReg)
#'   Usim <- rcMGL.bivar(n = 500, pars = 0.5)
#'   m.MGL <- MGL.mle(Usim,
#'   copula  = "MGL",
#'   initpar = c(2))
#'   # estimation results
#'   m.MGL
#' @export
#'
MGL.mle <- function(U, copula = c(
                      "MGL", "MGL180", "MGL-EV",
                      "MGL-EV180",
                      "Gumbel",
                      "Normal", "MGB2", "t"
                    ),
                    hessian = TRUE,
                    initpar, ...) {
  dnormcop <- function(U, param) {
    as.numeric(fCopulae::dellipticalCopula(U, rho = param[1], type = "norm"))
  } # normal copula

  dtcop <- function(U, param) {
    as.numeric(fCopulae::dellipticalCopula(U,
      rho = param[1], type = "t",
      param = param[2]
    ))
  } # t copula
  dgumcop <- function(U, param) {
    as.numeric(fCopulae::devCopula(U, type = "gumbel", param = param[1]))
  } # Bivariate Extreme

  dMGL <- function(U, param) {
    as.numeric(dcMGL.bivar(u1 = U[, 1], u2 = U[, 2], pars = param[1]))
  }

  dMGL180 <- function(U, param) {
    as.numeric(dcMGL180.bivar(u1 = U[, 1], u2 = U[, 2], pars = param[1]))
  }

  dMGB2 <- function(U, param) {
    as.numeric(dcMGB2.bivar(u1 = U[, 1], u2 = U[, 2], pars1 = param[1], pars2 = param[2], pars3 = param[3]))
  }

  dMGLEV <- function(U, param) {
    as.numeric(dcMGLEV.bivar(u1 = U[, 1], u2 = U[, 2], param = param[1])) # Bivariate Extreme
  }

  dMGLEV180 <- function(U, param) {
    as.numeric(dcMGLEV180.bivar(u1 = U[, 1], u2 = U[, 2], param = param[1])) # Bivariate Extreme
  }

  argnorm <- list(length = 1, lower = 0, upper = 1, name = "Gaussian")
  argt <- list(length = 2, lower = c(0, 0), upper = c(1, 100), name = "Student")
  arggum <- list(length = 1, lower = 1, upper = 50, name = "Gumbel")
  argMGB2 <- list(
    length = 3, lower = c(0, 0, 0), upper = c(50, 50, 50),
    name = "MGB2"
  )
  argMG180 <- list(length = 1, lower = 0, upper = 10, name = "MGL180")
  argMGLEV180 <- list(length = 1, lower = 0, upper = 10, name = "MGL-EV180")
  argMG <- list(length = 1, lower = 0, upper = 10, name = "MGL")
  argMGLEV <- list(length = 1, lower = 0, upper = 10, name = "MGL-EV")
  if (copula == "MGL") {
    dcop <- dMGL
    arg.cop <- argMG
  } else if (copula == "MGL180") {
    dcop <- dMGL180
    arg.cop <- argMG180
  } else if (copula == "MGL-EV") {
    dcop <- dMGLEV
    arg.cop <- argMGLEV
  } else if (copula == "MGL-EV180") {
    dcop <- dMGLEV180
    arg.cop <- argMGLEV180
  } else if (copula == "Gumbel") {
    dcop <- dgumcop
    arg.cop <- arggum
  } else if (copula == "Normal") {
    dcop <- dnormcop
    arg.cop <- argnorm
  } else if (copula == "t") {
    dcop <- dtcop
    arg.cop <- argt
  } else if (copula == "MGB2") {
    dcop <- dMGB2
    arg.cop <- argMGB2
  }

  # loglike.copula <- function(U, initpar, ...){
  copLogL <- function(x) {
    if (all(arg.cop$lower < x && arg.cop$upper > x)) {
      logL <- log(dcop(U, param = x))
      # res <- -sum((logL))
      remove.naninf <- function(z) z[!is.nan(z) & is.finite(z)]
      res <- -sum(remove.naninf(logL))
    } else {
      res <- 10000000000000
    }
    return(res)
  }
  # }

  resopt <- nlm(
    f = copLogL,
    p = initpar,
    hessian = hessian, ...
  )

  # results
  if (hessian == TRUE){
    out <-  list(
      loglike = -resopt$minimum,
      copula = list(name = arg.cop$name),
      estimates = resopt$estimate,
      se = sqrt(diag(solve(resopt$hessian))),
      hessian = -resopt$hessian,
      AIC = 2 * length(resopt$estimate) + 2 * resopt$minimum,
      BIC = log(nrow(U)) * length(resopt$estimate) + 2 * resopt$minimum
    )
  } else {
    out <-   list(
      loglike = -resopt$minimum,
      copula = list(name = arg.cop$name),
      estimates = resopt$estimate,
      AIC = 2 * length(resopt$estimate) + 2 * resopt$minimum,
      BIC = log(nrow(U)) * length(resopt$estimate) + 2 * resopt$minimum
    )
  }
  out
}


#' Susceptibility and Infection
#'
#' Calculates infectiousness and susceptibility for each node in the graph
#' @templateVar dynamic TRUE
#' @templateVar toa TRUE
#' @templateVar valued TRUE
#' @template graph_template
#' @param t0 Integer scalar. See \code{\link{toa_mat}}.
#' @param normalize Logical. Whether or not to normalize the outcome
#' @param K Integer scalar. Number of time periods to consider
#' @param r Numeric scalar. Discount rate used when \code{expdiscount=TRUE}
#' @param expdiscount Logical scalar. When TRUE, exponential discount rate is used (see details).
#' @param outgoing Logical scalar. When \code{TRUE}, computed using outgoing ties.
#' @family statistics
#' @aliases susceptibility
#' @keywords univar
#' @seealso The user can visualize the distribution of both statistics
#' by using the function \code{\link{plot_infectsuscep}}
#' @details
#'
#' Normalization, \code{normalize=TRUE}, is applied by dividing the
#' resulting number from the infectiousness/susceptibility stat
#' by the number of individuals who adopted the innovation at
#' time \eqn{t}.
#'
#' Given that node \eqn{i} adopted the innovation in time \eqn{t}, its
#' Susceptibility is calculated as follows
#'
#' \deqn{S_i = \frac{%
#' \sum_{k=1}^K\sum_{j=1}^n x_{ij(t-k+1)}z_{j(t-k)}\times \frac{1}{w_k}}{%
#' \sum_{k=1}^K\sum_{j=1}^n x_{ij(t-k+1)}z_{j(1\leq t \leq t-k)} \times \frac{1}{w_k} }\qquad \mbox{for }i,j=1,\dots,n\quad i\neq j}{%
#' S(i) = [\sum_k \sum_j (x(ij,t-k+1) * z(j,t-k))/w(k)]/[\sum_k \sum_j (x(ij,t-k+1) * z(j, 1<=t<=t-k))/w(k)]  for  j != i}
#'
#' where \eqn{x_{ij(t-k+1)}}{x(ij,t-k+1)} is 1 whenever there's a link from \eqn{i}
#' to \eqn{j} at time \eqn{t-k+1}, \eqn{z_{j(t-k)}}{z(j,t-k)}
#' is 1 whenever individual \eqn{j} adopted the innovation at time \eqn{t-k},
#' \eqn{z_{j(1\leq t \leq t-k)}}{z(j, 1<=t<=t-k)} is 1 whenever
#' \eqn{j} had adopted the innovation up to \eqn{t-k}, and \eqn{w_k}{w(k)} is
#' the discount rate used (see below).
#'
#' Similarly, infectiousness is calculated as follows
#'
#' \deqn{I_i = \frac{%
#' \sum_{k=1}^K \sum_{j=1}^n x_{ji(t+k-1)}z_{j(t+k)}\times \frac{1}{w_k}}{%
#' \sum_{k=1}^K \sum_{j=1}^n x_{ji(t+k-1)}z_{j(t+k\leq t \leq T)}\times \frac{1}{w_k} }\qquad \mbox{for }i,j=1,\dots,n\quad i\neq j}{%
#' I(i) = [\sum_k \sum_j (x(ji,t) * z(j,t+1))/w(k)]/[\sum_k \sum_j (x(ji,t) * z(j, t+1<=t<=T))/w(k)]   for  j != i}
#'
#' It is worth noticing that, as we can see in the formulas, while susceptibility
#' is from alter to ego, infection is from ego to alter.
#'
#' When \code{outgoing=FALSE} the algorithms are based on incoming edges, this is
#' the adjacency matrices are transposed swapping the indexes \eqn{(i,j)} by
#' \eqn{(j,i)}. This can be useful for some users.
#'
#' Finally, by default both are normalized by the number of individuals who
#' adopted the innovation in time \eqn{t-k}. Thus, the resulting formulas,
#' when \code{normalize=TRUE}, can be rewritten as
#'
#' \deqn{%
#' S_i' = \frac{S_i}{\sum_{k=1}^K\sum_{j=1}^nz_{j(t-k)}\times \frac{1}{w_k}} %
#' \qquad I_i' = \frac{I_i}{\sum_{k=1}^K\sum_{j=1}^nz_{j(t-k)} \times\frac{1}{w_k}}}{%
#' S(i)' = S(i)/[\sum_k \sum_j z(j,t-k)/w(k)]
#'
#' I(i)' = I(i)/[\sum_k \sum_j z(j,t-k)/w(k)]}
#'
#' For more details on these measurements, please refer to the vignette titled
#' \emph{Time Discounted Infection and Susceptibility}.
#'
#' @section Discount rate:
#'
#' Discount rate, \eqn{w_k}{w(k)} in the formulas above, can be either exponential
#' or linear. When \code{expdiscount=TRUE}, \eqn{w_k = (1 + r)^{k-1}}{w(k) = (1+r)^(k-1)}, otherwise
#' it will be \eqn{w_k = k}{w(k)=k}.
#'
#' Note that when \eqn{K=1}, the above formulas are equal to the ones presented
#' in Valente et al. (2015).
#'
#' @references
#' Thomas W. Valente, Stephanie R. Dyal, Kar-Hai Chu, Heather Wipfli, Kayo
#' Fujimoto Diffusion of innovations theory applied to global tobacco control
#' treaty ratification, Social Science & Medicine, Volume 145, November 2015,
#' Pages 89-97, ISSN 0277-9536
#' \doi{10.1016/j.socscimed.2015.10.001}
#'
#' Myers, D. J. (2000). The Diffusion of Collective Violence: Infectiousness,
#' Susceptibility, and Mass Media Networks. American Journal of Sociology, 106(1),
#' 173–208. \doi{10.1086/303110}
#'
#' @examples
#'
#' # Creating a random dynamic graph
#' set.seed(943)
#' graph <- rgraph_er(n=100, t=10)
#' toa <- sample.int(10, 100, TRUE)
#'
#' # Computing infection and susceptibility (K=1)
#' infection(graph, toa)
#' susceptibility(graph, toa)
#'
#' # Now with K=4
#' infection(graph, toa, K=4)
#' susceptibility(graph, toa, K=4)
#'
#' @export
#' @return A numeric column vector (matrix) of size \eqn{n} with either infection/susceptibility rates.
#' @author George G. Vega Yon
infection <- function(graph, toa, t0=NULL,
                      normalize=TRUE, K=1L, r=0.5, expdiscount=FALSE,
                      valued   = getOption("diffnet.valued", FALSE),
                      outgoing = getOption("diffnet.outgoing", TRUE)) {

  # Checking the times argument
  if (missing(toa))
    if (!inherits(graph, "diffnet")) {
      stop("-toa- should be provided when -graph- is not of class 'diffnet'")
    } else {
      toa <- graph$toa
      t0    <- min(graph$meta$pers)
    }

  # Checking baseline time
  if (!length(t0)) t0 <- min(toa, na.rm=TRUE)

  switch (class(graph),
    array = infection.array(graph, toa, t0, normalize, K, r, expdiscount, valued, outgoing),
    list = infection.list(graph, toa, t0, normalize, K, r, expdiscount, valued, outgoing),
    diffnet = infection.list(graph$graph, toa, t0, normalize, K, r, expdiscount, valued, outgoing),
    stopifnot_graph(graph)
  )
}

# @rdname infection
# @export
infection.array <- function(graph, toa, t0, normalize, K, r, expdiscount, valued, outgoing) {
  toa <- toa - t0 + 1L
  t <- dim(graph)[3]
  n <- nrow(graph)
  ngraph <- vector("list", t)

  for(i in 1:t)
    ngraph[[i]] <- methods::as(graph[,,i], "dgCMatrix")

  out <- infection_cpp(ngraph, toa, normalize, K, r, expdiscount, n, valued, outgoing)

  # Naming
  rn <- rownames(graph)
  if (!length(rn)) rn <- 1:n
  structure(out, dimnames=list(rn, "infection"), dim=c(n,1))
}

# @rdname infection
# @export
infection.list <- function(graph, toa, t0, normalize, K, r, expdiscount, valued, outgoing) {
  t <- length(graph)
  n <- nrow(graph[[1]])
  toa <- toa - t0 + 1L

  out <- infection_cpp(graph, toa, normalize, K, r, expdiscount, n, valued, outgoing)

  # Naming
  rn <- rownames(graph[[1]])
  if (!length(rn)) rn <- 1:n

  structure(out, dimnames=list(rn, "infection"), dim=c(n,1))
}

#' @rdname infection
#' @export
susceptibility <- function(graph, toa, t0=NULL, normalize=TRUE, K=1L, r=0.5,
                           expdiscount=FALSE,
                           valued=getOption("diffnet.valued",FALSE),
                           outgoing=getOption("diffnet.outgoing",TRUE)) {
  # Checking the toa argument
  if (missing(toa))
    if (!inherits(graph, "diffnet")) {
      stop("-toa- should be provided when -graph- is not of class 'diffnet'")
    } else {
      toa <- graph$toa
      t0    <- min(graph$meta$pers)
    }

  # Checking baseline time
  if (!length(t0)) t0 <- min(toa, na.rm=TRUE)

  cls <- class(graph)

  if ("array" %in% cls) {
    susceptibility.array(graph, toa, t0, normalize, K, r, expdiscount, valued, outgoing)
  } else if ("list" %in% cls) {
    susceptibility.list(graph, toa, t0, normalize, K, r, expdiscount, valued, outgoing)
  } else if ("diffnet" %in% cls) {
    susceptibility.list(graph$graph, toa, t0, normalize, K, r, expdiscount, valued, outgoing)
  } else
    stopifnot_graph(graph)

}

# @rdname infection
# @export
susceptibility.list <- function(graph, toa, t0, normalize, K, r, expdiscount, valued, outgoing) {
  t <- length(graph)
  n <- nrow(graph[[1]])
  toa <- toa - t0 + 1L

  out <- susceptibility_cpp(graph, toa, normalize, K, r, expdiscount, n, valued, outgoing)

  # Naming
  rn <- rownames(graph[[1]])
  if (!length(rn)) rn <- 1:n

  structure(out, dimnames=list(rn, "susceptibility"), dim=c(n,1))

}

# @rdname infection
# @export
susceptibility.array <- function(graph, toa, t0, normalize, K, r, expdiscount, valued, outgoing) {
  toa <- toa - t0 + 1L
  t <- dim(graph)[3]
  n <- nrow(graph)
  ngraph <- vector("list", t)

  for(i in 1:t)
    ngraph[[i]] <- methods::as(graph[,,i], "dgCMatrix")

  out <- susceptibility_cpp(ngraph, toa, normalize, K, r, expdiscount, n, valued, outgoing)

  # Naming
  rn <- rownames(graph)
  if (!length(rn)) rn <- 1:n
  structure(out, dimnames=list(rn, "susceptibility"), dim=c(n,1))
}


# 4. faza: Analiza podatkov

#linearni model s intervalom zaupanja

model1 <- lm(neto_izvoz ~ leto , data = pdf1)
prihodnost <- data.frame(leto = seq(2020,2024))

napoved1 <- prihodnost %>% mutate(neto_izvoz= predict(model1, .))

tabela.napoved1 <- bind_rows( (pdf1)[c(1,4)],napoved1)

graf.napoved1 <- ggplot(tabela.napoved1, aes(x = leto, y = neto_izvoz)) +
  geom_point() + scale_x_continuous(name = "Leto", breaks = seq(1950,2024,2)) + ylab("Neto izvoz") +
  ggtitle("Napoved gibanja neto izvoza-linearna") +
  geom_smooth(method = 'lm', formula = y ~ x,col="red") +
  theme(axis.text.x=element_text(angle=90, vjust=0.5, hjust=1),
         panel.grid.minor = element_blank())+
  scale_y_continuous(labels=comma)+
  geom_point(data=napoved1, aes(x=leto, y=neto_izvoz), fill='yellow',shape=21, size=2)

#linearni model uvoz izvoz

model2 <- lm(izvoz ~ uvoz , data = pdf1)
novi.uvozi <- data.frame(uvoz = c(500000,1000000,1200000))

napoved2 <- novi.uvozi %>% mutate(izvoz= predict(model2, .))

tabela.napoved2 <- bind_rows( (pdf1)[c(2,3)],napoved2)

graf.napoved2 <- ggplot(tabela.napoved2, aes(x = uvoz, y = izvoz)) +
  geom_point() + scale_x_continuous(name = "Uvoz",labels = scales::comma, breaks = seq(0,1300000,100000)) + ylab("Izvoz") +
  ggtitle("Napoved gibanja izvoza glede na uvoz") +
  geom_smooth(method = 'lm', formula = y ~ x,col="red") +
  theme(axis.text.x=element_text(angle=90, vjust=0.5, hjust=1),
        panel.grid.minor = element_blank())+
  scale_y_continuous(labels=comma)+
  geom_point(data=napoved2, aes(x=uvoz, y=izvoz), fill='yellow',shape=24, size=3.5)


dt <- 0.01
Nstep <- 10000
k1 <- 0.1
lambda1 <- 1.0
lambda2 <- 0.5
k2 <- 0.2
Ncell <- 600
F0 <- 0.1
p0 <- 0.7
## F0 <- 0.8
## p0 <- 0.8
ec <- 1.6
sig1 <- 0
sig2 <- 0
alpha <- 0.5
sig <- 0.0

thetabarList <- NULL
for (nsample in seq(1))
{
e <- seq(1.2, 1.2, length.out=Ncell)
theta <- runif(Ncell, -pi/2, pi/2)

output <- NULL

thetabar <- 0
for ( i in seq(Nstep) )
{
    if ( i %% 20 == 0 )
    {
        n <- cbind(cos(theta), sin(theta))
        Q <- cbind(n[,1]*n[,1]-0.5, n[,1]*n[,2], n[,2]*n[,1], n[,2]*n[,2]-0.5)
        M <- matrix(colMeans(Q), nrow=2, ncol=2, byrow=TRUE)
        eigenvec <- eigen(M)$vectors[,1]
        thetabar <- atan(abs(eigenvec[2])/pmax(0.000001, abs(eigenvec[1])))
    }
    F <- max(0, F0 - alpha * sig/(1+abs(sig)))
    S <- mean(cos(2.0*theta))
    e <- e + dt*(F*cos(theta) - lambda1*(e-1)) + k1*sqrt(dt)*rnorm(Ncell, mean=0, sd=1)
    e <- pmax(e, 1)
    theta <- theta - dt*lambda2*(e-1)*(theta - thetabar) + k2*sqrt(dt)*rnorm(Ncell, mean=0, sd=1)
    ##theta <- theta - dt*S*lambda2*(theta-thetabar) + k2*sqrt(dt)*rnorm(Ncell, mean=0, sd=1)
    ##theta <- atan(abs(sin(theta))/pmax(0.000001, abs(cos(theta))))
    #cat(i, S, '\n')

    if ( i%%10 == 0 )
    {
        theta1 <- theta
        theta1 <- atan(abs(sin(theta1))/pmax(0.000001, abs(cos(theta1))))
        ecut <- e < ec
        theta2 <- theta1 * (1 - ecut) + ecut * runif(Ncell, 0, pi/2)
        A1 <- mean(sin(theta1) - cos(theta1))
        A2 <- mean(sin(theta2) - cos(theta2))
        ES <- mean((1-p0)*cos(theta1) - p0*sin(theta1))
        #cat(A1, A2, S, ES, F, sig, thetabar*180/pi, '\n')

        divtheta <- sample(theta1, 1)
        sig1 <- sig1 + cos(divtheta)
        sig2 <- sig2 + sin(divtheta)
        sig <- ((1-p0)*sig1 - p0*sig2)

        output <- rbind(output, c(sig, F, A1, A2, ES, sig1, sig2, divtheta))
    }
}

cat(A1, A2, S, ES, F, sig, thetabar*180/pi, '\n')
thetabarList <- c(thetabarList, thetabar*180/pi)
}
##png("output1.png")
pdf("output1.pdf")
par(mfrow=c(2, 1))
par(mar=c(4,6,4,4))
plot(output[200:800,1], type='o', col='blue', ylim=c(-6, 6),
     xlab="Number of divisions",cex.lab=1.5, cex.axis=1.5,
     ylab="Signal")
abline(h=0, lty=2)
##lines(output[,2], col='green', lty=1)
##lines(output[,3], col='blue')
plot(output[200:800,5], col='red')
dev.off()

sig0 <- mean(output[,1])
F0rec = F0 - alpha * sig0/(1+abs(sig0))
## theta1 <- theta
## theta1 <- atan(abs(sin(theta1))/pmax(0.000001, abs(cos(theta1))))
## ecut <- e < ec
## theta2 <- theta1 * (1 - ecut) + ecut * runif(Ncell, 0, pi/2)
## A1 <- mean(sin(theta1) - cos(theta1))
## A2 <- mean(sin(theta2) - cos(theta2))
## A1List <- c(A1List, A1)
## A2List <- c(A2List, A2)
## cat(A1, A2, S, thetabar*180/pi, '\n')


#' @title calcCm
#'
#' @description  Calculates the midship section coefficient (\code{Cm})
#' (dimensionless).
#'
#' @param shipType Ship type (vector of strings, see \code{\link{calcShipType}}).
#' Must align with \code{tankerBulkCarrierShipTypes}, \code{tugShipTypes}, and
#' \code{roroPaxShipTypes} groupings
#' @param Cbw Waterline block coefficient (vector of numericals, dimensionless)
#' (see \code{\link{calcCbw}})
#' @param maxDraft Maximum summer load line draft (vector of numericals, m)
#' @param actualDraft Actual draft (vector of numericals, m)
#' @param CmEquationType Equation type: \itemize{
#' \item"kristensen"
#' \item"benford"
#' \item"schneekluth"}
#' This argument is not vectorized, as it takes only a single string
#'@param tankerBulkCarrierShipTypes Ship types specified in input \code{shipTypes}
#'to be modeled as tankers and bulk carriers (vector of strings)
#'@param tugShipTypes Ship types specified in input \code{shipTypes} to be
#'modeled as tugs (vector of strings)
#'@param roroPaxShipTypes Ship types specified in input \code{shipTypes} to be
#'modeled as RORO and passenger ships (vector of strings)
#'
#' @details
#' The midship section coefficient calculation depends on the ship type, in
#' addition to the actual draft. Actual draft is typically obtained from sources
#' such as AIS messages or ship records.
#'
#' This function can calculate \code{Cm} using three different methods:
#' Kristensen, Benford, and Schneekluth. The Kristensen method requires ship
#' types to be grouped. Use the \code{tankerBulkCarrierShipTypes},
#' \code{tugShipTypes}, and \code{roroPaxShipTypes} parameters to provide these
#' ship type groupings. Any ship types not included in these groupings will be
#' considered as miscellaneous vessels.
#'
#' Use the \code{CmEquationType} parameter to indicate which method to use:\itemize{
#'
#'  \item "kristensen" (see Kristensen 2013 & 2017): \itemize{
#'    \item Bulk Carriers and Tankers: \code{Cm} = 0.995
#'    \item Passenger Vessels: \code{Cm} = 0.95
#'    \item Tugboats: \code{Cm} = 0.92
#'    \item Miscellaneous Vessels: \code{Cm} = 0.98
#'  }
#'
#'  \item "benford" (see Rakke 2016):
#'  \deqn{Cm=0.977+0.085*(Cbw-0.6)}
#'
#'  \item "schneekluth" (see Schneekluth 1998):
#'  \deqn{Cm=1.006-0.0056*Cbw^-3.65}
#'
#' }
#'
#' @return \code{Cm} (vector of numericals, dimensionless)
#'
#' @references
#'Kristensen, H. O. and Lutzen, M. 2013. "Prediction of Resistance and Propulsion
#'Power of Ships."
#'
#'\href{https://gitlab.gbar.dtu.dk/oceanwave3d/Ship-Desmo}{Kristensen, H. O.
#'"Ship-Desmo-Tool." https://gitlab.gbar.dtu.dk/oceanwave3d/Ship-Desmo}
#'
#'Schneekluth, H. and Bertram, V. 1998. "Ship Design for Efficiency and Economy."
#'2nd ed. Oxford, Boston: Butterworth-Heinemann.
#'
#' @seealso \itemize{
#'   \item \code{\link{calcCbw}}
#'   \item \code{\link{calcShipType}}
#'  }
#'
#' @examples
#' calcCm(c("chemical.tanker","container.ship"),c(0.8,0.75),c(13.6,15.6),c(12.5,14.1),"kristensen")
#' calcCm(c("chemical.tanker","container.ship"),c(0.8,0.75),c(13.6,15.6),c(12.5,14.1),"kristensen",
#'        tankerBulkCarrierShipTypes=c("other.tanker"))
#'
#' @export

calcCm <-function(shipType,Cbw,maxDraft,actualDraft,CmEquationType,
                  tankerBulkCarrierShipTypes=c("tanker","chemical.tanker","liquified.gas.tanker","oil.tanker","other.tanker","bulk.carrier"),
                  tugShipTypes=c("service.tug","tug"),
                  roroPaxShipTypes=c("ferry.pax","ferry.ro.pax","cruise","cruise.ed","yacht","ro.ro","passenger")
                  ){

  if(grepl("kristensen",tolower(CmEquationType))==TRUE){
    Cm<- ifelse(#case 1
          shipType %in% tankerBulkCarrierShipTypes
        ,
        0.995,
        ifelse(#case 2
          shipType %in% tugShipTypes,
          0.92,
          ifelse(#case 3
            shipType %in% roroPaxShipTypes,
            0.95,# passenger case
            0.98 # misc type case
          )#end of case 3

        )#end of case 2
      )#end of case 1

    #adjust for actual draft
    Cm<-1-maxDraft/actualDraft*(1-Cm)

  }else if(grepl("benford",tolower(CmEquationType))==TRUE){

    Cm<-0.977+0.085*(Cbw-0.6)

  }else if(grepl("schneekluth",tolower(CmEquationType))==TRUE){

    Cm<-1.006-0.0056*Cbw^-3.56

  }
  return(Cm)
}


## Function to do Wright-Fisher simulation with selection and a finite sample size
# using priors on Ne and s
# and specify initial sample allele frequency, f1samp (compare to wfs.r, which sets a prior on initial true allele freq f1)
# Sample at THREE time points

# f1samp: the initial sample allele frequency. Initial true allele freq will be sampled with this constraint.
# smin: the minimum for the selection coefficient uniform prior
# smax:
# c1: the size of the first sample (in # chromosomes)
# c2: the size of the second sample (in # chromosomes)
# c3: the size of the third sample (in # chromosomes)
# gen1: the number of generations for sample c2
# gen2: the number of generations for sample c3
# ne: a vector of possible Ne values. Simulation picks one to use.
# h: dominance effect

wfs_byf1samp_3samps <- function(f1samp=0.5, smin=-1, smax=1, c1=58, c2=48, c3=48, gen1=10, gen2=20, ne=100, hmin=0.5, hmax=0.5){
	tol <- .Machine$double.eps^0.5 # tolerane for equality. default tolerance in all.equal

	# make sure f1samp is possible given initial sample size (c1)
	# test whether difference from a possible sample size is less than tol
	if(!any(abs(f1samp - ((0:c1)/c1)) < tol)) stop(paste('f1samp=', f1samp, 'not possible given c1=', c1))

	# choose parameters for this simulation
	s <- runif(1, min=smin, max=smax) # selection coefficient
	h <- runif(1, min=hmin, max=hmax) # dominance coefficient
	if(length(ne)>1) thisne <- round(sample(ne, 1)) # ne has to be integer for binomial sampling
	if(length(ne)==1) thisne <- round(ne)

	# choose initial population frequency
	# brute force method: keep picking possible f1s until one produces the correct f1samp
	thisf1 <- -100
	while(abs(thisf1 - f1samp) >= tol){
		f1 <- runif(1, min=0, max=1) # pick a starting allele frequency
		thisf1 <- rbinom(1,c1,f1)/c1 # pick a first sample allele frequency that corresponds
	}

#	print(paste(f1, s, thisne))

	p <- f1 # current allele frequency
	waa <- 1+s # relative fitness of genotype AA
	wab <- 1+s*h
	wbb <- 1
	for(i in 1:gen2){
		x <- (waa*p^2 + wab*p*(1-p))/(waa*p^2 + wab*2*p*(1-p) + wbb*(1-p)^2) # probability of sampling allele A, given selection
		p <- rbinom(1,thisne,x)/thisne
#		print(paste(x,p))
		if(i==gen1){
			f2 <- p # take second sample
		}
	}
	f3 <- p # third sample

	f2samp <- rbinom(1,c2,f2)/c2 # second sample allele frequency
	f3samp <- rbinom(1,c3,f3)/c3 # third sample allele frequency

	# return values
#	out <- c(ne=thisne, f1=f1, s=s, gen=gen, f2=f2, f1samp=f1samp, f2samp=f2samp, fsdprime=stats[1], fsiprime=stats[2])
	out <- c(ne=thisne, f1=f1, s=s, h=h, gen1=gen1, gen2=gen2, f2=f2, f3=f3, f1samp=f1samp, f2samp=f2samp, f3samp=f3samp)
	return(out)
}


"
С клавиатуры ввести целое число N. Рассчитать соответствующий числу день недели
месяц и год, исходя из того, что в каждом месяце 30 дней, 1 задает понедельник января
2 – вторник января и т.д. Вывести результат в виде строки следующего шаблона:
«Введенное значение N соответствует среде марта, 22-й год».
"

{
  number <- as.integer(readline("Введите число -> "))
  year <- number %/% 360 + 1
  number <- number %% 360
  month <- (number %/% 30) + 1
  day <- number %% 7
  monthwrite <- switch(
    month,
    "Январь",
    "Февраль",
    "Март",
    "Апрель",
    "Май",
    "Июнь",
    "Июль",
    "Август",
    "Сентябрь",
    "Октябрь",
    "Ноябрь",
    "Декабрь"
  )
  daywrite <- switch (
    day,
    "Понедельник",
    "Вторник",
    "Среда",
    "Четверг",
    "Пятница",
    "Суббота",
    "Воскресенье"
  )

  print(paste(
    "Введенное значение N соответствует",
    day ,
    daywrite,
    monthwrite,
    year,
    "год"
  ))
}


## Insang Song (isong@uoregon.edu)
## Spatially Enhanced and Entropy-Derived MATrix (SpEED-MAT)
speedmat <- function(sf,
                     mode = "CDE", # "CE"/"DE"/"CDE"
                     input_vars = c(), # Contiguity Distance Entropy
                     bandwidth = NULL, # bandwidth: Currently only supports gaussian
                     q_jsd = 0.05,     # quantile of j-s divergence
                     kneigh = NULL,    # k-nearest neighbor for point data
                     queen = TRUE,     # Queen's contiguity for "C" mode for polygon data
                     cutoff_dist = NULL,
                     cutoff_weightd = 0.001,
                     cutoff_weightc = 0.001,
                     sup_factor = 0.5){
    if (is.null(bandwidth) & grepl("D", mode))
        stop("No bandwidth was entered")
    if (length(input_vars) == 0)
        stop("No input variable were specified")
    if (!grepl("E", mode))
        stop("Please use the methods for standard spatial weight matrices for non-entropy matrices")
    if (!is.null(bandwidth)) {
        cutoff_dist <- bandwidth
    }
    sfp <- sf[1,]

    sf_ent <- sf %>%
        dplyr::select(input_vars) %>%
        st_set_geometry(NULL) %>%
        mutate_at(.vars = vars(input_vars),
                  .funs = list(~as.vector(scale(.)))) %>%
        mutate_at(.vars = vars(everything()),
                  .funs = list(~.+abs(min(.)))) %>%
        as.matrix %>%
        philentropy::JSD(.)
    sf_ent <- sf_ent * (sf_ent <= quantile(sf_ent, q_jsd))
    sf_ent_ex <- exp(-1 * sf_ent)
    sf_ent_f <- (sf_ent_ex * (sf_ent_ex != 1))

    if (grepl("C", mode)){
        if (queen){
            pat <- 'F***T****'
        } else {
            pat <- 'F***1****'
        }

        if (any(st_is(sfp, 'POLYGON'), st_is(sfp, 'MULTIPOLYGON'), st_is(sfp, "POLYGON Z"), st_is(sfp, "MULTIPOLYGON Z")))
            {sf_touch <- st_relate(sf, pattern = pat) %>% #poly2nb(sf, queen = queen) %>%
                as(., 'matrix')#nb2mat
             sf_touch_ <- sf_touch
            } else {
            sf_touch <- st_nn(sf, sf, k = kneigh + 1, sparse = FALSE, returnDist = TRUE) #%>%
            sf_touch_ <- sf_touch
            sf_touch_nn <- sf_touch$nn
            diag(sf_touch_nn) <- FALSE
            sf_touch <- sf_touch_nn
            }
        # 122820
        sf_invdv <- ((1-sup_factor)*sf_touch) + (sup_factor * sf_ent_f)
    }
    if (grepl("D", mode))
    {
        if (any(st_is(sfp, 'POLYGON'), st_is(sfp, 'MULTIPOLYGON'), st_is(sfp, "POLYGON Z"), st_is(sfp, "MULTIPOLYGON Z"))) {
            sf_interd <- as(st_distance(st_centroid(sf)), 'matrix')
        } else {
            sf_interd <- as(st_distance(sf), 'matrix')
        }
        sf_interd <- sf_interd * (sf_interd <= cutoff_dist)
        sf_invd <- exp(-1 * ((sf_interd^2)/(bandwidth^2)))
        sf_invd <- sf_invd * (sf_invd != 1)
        diag(sf_invd) <- 0

        if (grepl("^C", mode)) {
            if (!any(st_is(sfp, 'POLYGON'), st_is(sfp, 'MULTIPOLYGON'), st_is(sfp, "POLYGON Z"), st_is(sfp, "MULTIPOLYGON Z")))
            {
                sf_touch_ <- sf_touch
                sf_touch_d <- do.call(c, sf_touch_$dist)
                sf_touch_d <- sf_touch_d[sf_touch_d != 0]
                sf_touch_nn[sf_touch_nn == TRUE] <- sf_touch_d
                sf_touch <- sf_touch_nn
            }

            sf_invdv <- ((1-sup_factor) * (sf_touch * sf_invd)) + (sup_factor * sf_ent_f)
            sf_invdv <- sf_invdv * (sf_invdv >= cutoff_weightc)
        } else {
            sf_invdv <- ((1-sup_factor)* (sf_invd * (sf_invd >= cutoff_weightd))) + (sup_factor * sf_ent_f)
            sf_invdv <- sf_invdv * (sf_invdv >= cutoff_weightc)
        }
    }

    # error check
    checksum <- apply(sf_invdv, 1, sum)
    if (any(is.nan(checksum) | checksum == 0)){
        addr_check <- (is.nan(checksum) | checksum==0)
        diag(sf_invdv)[addr_check] <- 1
    }
    speedmat <- sf_invdv / apply(sf_invdv, 1, sum)
    return(speedmat)
}


#!/usr/bin/r
##
## varSimulation.r: Simulation of first-order vector autoregression data
##
## Copyright (C)  2011 - 2015  Lance Bachmeier and Dirk Eddelbuettel
##
## This file is part of RcppArmadillo.
##
## RcppArmadillo is free software: you can redistribute it and/or modify it
## under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 2 of the License, or
## (at your option) any later version.
##
## RcppArmadillo is distributed in the hope that it will be useful, but
## WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with RcppArmadillo.  If not, see <http://www.gnu.org/licenses/>.

## load Rcpp to be able to use cppFunction() below
suppressMessages(library(Rcpp))

## parameter and error terms used throughout
a <- matrix(c(0.5,0.1,0.1,0.5),nrow=2)
e <- matrix(rnorm(10000),ncol=2)

## Let's start with the R version
rSim <- function(coeff, errors) {
    simdata <- matrix(0, nrow(errors), ncol(errors))
    for (row in 2:nrow(errors)) {
        simdata[row,] = coeff %*% simdata[(row-1),] + errors[row,]
    }
    return(simdata)
}

rData <- rSim(a, e)                     # generated by R

## Now let's load the R compiler (requires R 2.13 or later)
suppressMessages(require(compiler))
compRsim <- cmpfun(rSim)

compRData <- compRsim(a,e)              # generated by R 'compiled'

stopifnot(all.equal(rData, compRData))  # checking results

## C++ variant: code passed as a text variable ...
code <- '
arma::mat rcppSim(const arma::mat& coeff, const arma::mat& errors) {
    int m = errors.n_rows;
    int n = errors.n_cols;
    arma::mat simdata(m,n);
    simdata.row(0) = arma::zeros<arma::mat>(1,n);
    for (int row=1; row<m; row++) {
        simdata.row(row) = simdata.row(row-1) * coeff + errors.row(row);
    }
    return simdata;
}
'
## ... which is compiled/linked/loaded here to create the compiled function
cppFunction(code=code, depends="RcppArmadillo")

rcppData <- rcppSim(a,e)                # generated by C++ code

stopifnot(all.equal(rData, rcppData))   # checking results

## now load the rbenchmark package and compare all three
suppressMessages(library(rbenchmark))
res <- benchmark(rcppSim(a,e),
                 rSim(a,e),
                 compRsim(a,e),
                 columns=c("test", "replications", "elapsed",
                           "relative", "user.self", "sys.self"),
                 order="relative")
print(res)


> ## inicio da aula R ##
>

> ## UNIDADE 1 ##

> ## OPERACOES MATEMATICAS##
> 3+3
[1] 6
> 3-4
[1] -1
> 3*3
[1] 9
> 4/2
[1] 2
> %% 2
Error: unexpected SPECIAL in "%%"
>
> ## VARIAVEL ##
> var <- 3*4
> var
[1] 12
>
> ## VARIAVEL NAO TEM TIPO PODE SER CHARACTER ##
> VAR <- "jONATHAN sARTORI bRUZARROSCO"
> VAR
[1] "jONATHAN sARTORI bRUZARROSCO"

> ##SALVAR DADOS NO ENVIRONMENT##
> idade <- 34
> nome <- "Jonathan Sartori Bruzarrosco"
> logica <- TRUE
> salario <- 1000.15
> var <- "qualquer coisa"
>
> ## MOSTRAR A KISTA DAS VARIAVEIS SALVAS ##
> ls()
[1] "idade"   "logica"  "nome"    "salario"
[5] "var"
>
> ## REMOVER VARIAVEL SALVA ##
> rm(var)
>
> ## REMOVER A LISTA TODA ##
> rm(list = ls())
>
>

> ## UNIDADE 2 ##

## ADICIONANDO VARIAVEIS ##
> nome <- "Jonathan Sartori Bruzarrosco"
> idade <- 34
> salario <- 1000.15
> logica <- TRUE
>
> ## PARA SABER O TIPO DE DADO ##
> class(idade)
[1] "numeric"
> class(salario)
[1] "numeric"
> class(nome)
[1] "character"
> class(logica)
[1] "logical"
> ## LOGICAL ACEITA VERDADEIRO OU FALSO ##

> ## character vai estar sempre entre""##
>
> ## EXEMPLO ##
> idade <- "5"
> class(idade)
[1] "character"
>
> ## TESTAR O TIPO DO DADO ##
> is.numeric(idade)
[1] FALSE
> is.character(nome)
[1] TRUE
> is.logical(logica)
[1] TRUE
>
> ## CONVERTER TIPO ##
> var <- idade + 5
Error in idade + 5 : non-numeric argument to binary operator
> as.integer(idAde)
Error: object 'idAde' not found
> as.integer(idade)
[1] 5
> var <- as.integer(idade) + 5
> var
[1] 10
> ## ou seja is verifica e as converte ##
> ## nem sempre se consegue exemplo ##
> as.integer(nome)
[1] NA
Warning message:
NAs introduced by coercion

> ## INICIANDO CONDICIONAL ##
> numero <- 10
>
> ##SHIFT + ENTER PARA PASSAR LINHA SEM RODAR CODIGO##
>
> if(class(numero) != "numeric"){
+     print("não é numerico")
+ }else{
+     if(numero %% 2 == 0){
+         print("o numero é par")
+     }else{
+         print("o numero é impar")
+     }
+ }
[1] "o numero é par"
>
> numero <- 11
> if(class(numero) != "numeric"){
+     print("não é numerico")
+ }else{
+     if(numero %% 2 == 0){
+         print("o numero é par")
+     }else{
+         print("o numero é impar")
+     }
+ }
[1] "o numero é impar"
>
> numero <- "jonathan"
> if(class(numero) != "numeric"){
+     print("não é numerico")
+ }else{
+     if(numero %% 2 == 0){
+         print("o numero é par")
+     }else{
+         print("o numero é impar")
+     }
+ }
[1] "não é numerico"

> ## != diferente ##
> ## %% 2 == 0 (resto da divisao é igual a 0 ou nao)##
> ## %% = mod ##
>
>
> ##ESTRUTURA DE REPETIÇÃO##
>
> professores <- c("Gobbato", "Maito", "alcides")
>
> ##saber a quantidade de elementos dentro do conjunto##
>
> length(professores)
[1] 3
> professores[1]
[1] "Gobbato"
> professores[2]
[1] "Maito"
> professores[0]
character(0)
> ##diferente de outras linguagens R comeca no 1##
>
> print(paste("o nome do professor é: ",professores[1] ))
[1] "o nome do professor é:  Gobbato"
>
> for(pos in 1:length(professores)){
+     print(paste("o nome do professor é:", professores[pos]))
+ }
[1] "o nome do professor é: Gobbato"
[1] "o nome do professor é: Maito"
[1] "o nome do professor é: alcides"

> posicao <- 1

> while(posicao <= length(professores)){
+     print(paste("o nome do professor é:", professores[posicao]))
+     posicao <- posicao + 1 #incremento
+ }
[1] "o nome do professor é: Gobbato"
[1] "o nome do professor é: Maito"
[1] "o nome do professor é: alcides"

> ## UNIDADE 3 ##


#' @title
#' Predict the response trajectory
#'
#' @description
#' This function generates prediction of the functional response based on the fitting
#' results of the NRRR model and the given predictor trajectory. The functional
#' response is predicted at a given sequence of time points \code{tseq}.
#'
#' @usage
#' NRRR.pred(tseq, X, sseq, Ag, Bg, Al, Bl, phi)
#'
#' @param tseq a sequence of time points at which the prediction of the response
#'             trajectory is generated.
#' @param sseq a sequence of time points at which the predictor trajectory is observed.
#' @param X an array of dimension \code{(n, p, length(sseq))} where n is
#'          the sample size and p is the number of components in the
#'          multivariate predictor. It is the predictor trajectory observed at
#'          discrete time points \code{sseq}.
#' @param phi a matrix of dimension \code{length(sseq)}-by-jx. It is the set of
#'            basis functions to expand the predictor trajectory.
#' @param Ag the estimated matrix U in a NRRR model.
#' @param Bg the estimated matrix V in a NRRR model.
#' @param Al the estimated matrix A in a NRRR model.
#' @param Bl the estimated matrix B in a NRRR model.
#'
#'
#' @return This function returns a list:
#'   \item{Cstar}{the estimated coefficient matrix in equation (7) of the NRRR paper,
#'                i.e., \eqn{(U \otimes I_jy)A* B*^T(V \otimes I_jx)^T}.}
#'   \item{Ypred}{the predicted response trajectory which is an array of
#'           dimension \code{(n, d, length(tseq))}}
#'
#'
#' @references Liu, X., Ma, S., & Chen, K. (2020).
#' Multivariate Functional Regression via Nested Reduced-Rank Regularization.
#' arXiv: Methodology.
#'
#' @importFrom splines bs
#' @export
#' @examples
#' library(NRRR)
#' set.seed(3)
#' # Simulation setting 2 in NRRR paper
#' simDat <- NRRR.sim(n = 100, ns = 100, nt = 100, r = 3, rx = 3, ry = 3,
#'                    jx = 8, jy = 8, p = 20, d = 20, s2n = 1, rho_X = 0.5,
#'                    rho_E = 0, Sigma = "CorrAR")
#' fit_nrrr <- with(simDat, NRRR.ic(Yest, Xest, Ag0 = NULL, Bg0 = NULL,
#'                  jx = 8, jy = 8, p = 20, d = 20, n = 100,
#'                  maxiter = 300, conv = 1e-4, method = c("RRR", "RRS")[1],
#'                  lambda = 0, ic = c("BIC", "BICP", "AIC", "GCV")[1],
#'                  dimred = c(TRUE, TRUE, TRUE), rankfix = NULL))
#' Ypred_nrrr <- NRRR.pred(simDat$tseq, simDat$X, simDat$sseq,
#'                         fit_nrrr$Ag, fit_nrrr$Bg, fit_nrrr$Al,
#'                         fit_nrrr$Bl, simDat$phi)
NRRR.pred <- function(tseq,X,sseq,Ag,Bg,Al,Bl,phi){
  n <- nrow(X)

  p <- nrow(Bg)
  d <- nrow(Ag)
  rx <- ncol(Bg)
  ry <- ncol(Ag)

  jx <- nrow(Bl)/rx
  jy <- nrow(Al)/ry

  nt <- length(tseq)
  ns <- length(sseq)

  # Note that you can predict at different time
  psi <- splines::bs(c(0,tseq),df = jy)[-1,]
  Jpsi <- matrix(nrow=jy,ncol=jy,0)
  tdiff <- (tseq - c(0,tseq[-nt]))
  for(t in 1:nt) Jpsi <- Jpsi + psi[t,]%*%t(psi[t,])*tdiff[t]
  eJpsi <- eigen(Jpsi)
  Jpsihalf <- eJpsi$vectors%*%diag(sqrt(eJpsi$values))%*%t(eJpsi$vectors)
  Jpsihalfinv <- eJpsi$vectors%*%diag(1/sqrt(eJpsi$values))%*%t(eJpsi$vectors)

  # Compute Cstar from estimated C
  alindex <- rep(1:ry,jy)
  Alstar <- Al[order(alindex),]
  blindex <- rep(1:rx,jx)
  Blstar <- Bl[order(blindex),]
  # Adjust
  Alstar <- kronecker(diag(ry),Jpsihalfinv)%*%Alstar
  Cstar <- kronecker(Ag,diag(jy))%*%Alstar%*%t(Blstar)%*%kronecker(t(Bg),diag(jx))

  # Integrated X
  # phi <- splines::bs(c(0,sseq),df = jx)[-1,]
  Xint <- matrix(nrow=p*jx,ncol=n,0)
  sdiff <- (sseq - c(0,sseq[-ns]))
  for(s in 1:ns){
    Xint <- Xint + kronecker(diag(nrow=p,ncol=p),phi[s,])%*%t(X[,,s])*sdiff[s]
  }

  # Compute predicted values
  Ypred <- array(dim=c(n,d,nt),NA)
  for(t in 1:nt){
    Psit <- kronecker(diag(nrow=d,ncol=d),t(psi[t,]))
    Ypred[,,t] <- t(Psit%*%Cstar%*%Xint)
  }

  list(Jpsihalf=Jpsihalf,Cstar=Cstar,Ypred=Ypred)

}