Skip to content
Snippets Groups Projects
qmodel.R 8.99 KiB
Newer Older
  • Learn to ignore specific revisions
  • qmodel <- R6::R6Class("qmodel", public = list(
    
    hgb's avatar
    hgb committed
        ####### Store Data and information for algorithm #####
        info = list(),
        ####### Store Coefficients Data #######
        beta = list(),
        ####### Fixed Parameters ######
        ## Weighted
        W = NA,
        n_in_bin = NA,
        ## Number of predictiors
        K = NA,
        ## Quantiles
        tau = NA,
        ## Cold start size
        N1 = NA,
        debug = NA,
    
        ####### Quantile Information ########
        ## Index of the columns of the X matrix of Xny
        IX = NA,
        ## Index of the column of y
        Iy = NA,
        ## The design matrix
        X = list(), 
    
        ####### debug Information ########
        listIH = list(),
    
        ####### Forecast Information ########
        inputs = list(),
        kseq = NA,
        output = NA,
        prm = NA,
        regprmexpr = NA,
        regprm = NA,
        ## Offline parameters
        prmbounds = as.matrix(data.frame(lower=NA, init =NA, upper=NA)),
        datatr = NA,
        qrFIT = NA,
        maxlagAR = NA,
        yAR = NA,
        Ypred = NA,
    
    
        ## Initialise the model with the size of the cold start.
        ## We need some starting point for the iteration of the quantile fit, using simplex method.
        initialize = function(N1 = NULL, debug = FALSE){
            if(is.null(N1)) stop("The number of data points for the cold start needs to be defined")
            self$N1 <- N1
            self$debug <-  debug
        },
    
    
    ### Should be the same to forecastmodel.R.. maybe have an inheritance from that instead of rewrite.
    
    
    #----------------------------------------------------------------
        # Get the transformation parameters
        get_prmbounds = function(nm){
            if(nm == "init"){
                if(is.null(dim(self$prmbounds))){
                    val <- self$prmbounds[nm]
                }else{
                    val <- self$prmbounds[ ,nm]
                    if(is.null(nams(val))){
                        nams(val) <- rownames(self$prmbounds)
                    }
                }
            }
            if(nm == "lower"){
                if("lower" %in% nams(self$prmbounds)){
                    val <- self$prmbounds[,"lower"]
                    if(is.null(nams(val))){
                        nams(val) <- rownames(self$prmbounds)
                    }
                }else{
                    val <- -Inf
                }
            }
            if(nm == "upper"){
                if("upper" %in% nams(self$prmbounds)){
                    val <- self$prmbounds[,"upper"]
                    if(is.null(nams(val))){
                        nams(val) <- rownames(self$prmbounds)
                    }
                }else{
                    val <- Inf
                }
            }
            names(val) <- row.names(self$prmbounds)
            return(val)
        },
        #----------------------------------------------------------------
    
            #----------------------------------------------------------------
        # Add the transformation parameters and bounds for optimization
        add_prmbounds = function(...) {
            dots <- list(...)
            for (i in 1:length(dots)) {
                nm <- names(dots)[i]
                if (nm %in% rownames(self$prmbounds)) {
                    self$prmbounds[nm, ] <- dots[[i]]
                } else {
                    if(nrow(self$prmbounds) == 1 & is.na(self$prmbounds[1,2])){
                        self$prmbounds[1, ] <- dots[[i]]
                    }else{
                        self$prmbounds <- rbind(self$prmbounds, dots[[i]])
                    }
                    rownames(self$prmbounds)[nrow(self$prmbounds)] <- nm
                }
            }
        },
        #----------------------------------------------------------------
    
    
        #----------------------------------------------------------------
        # Resets the input states
        reset_state = function(){
            # Reset the inputs state
            lapply(self$inputs, function(input){
                input$state_reset()
            })
            # Reset stored data
            self$datatr <- NA
            #self$yAR <- NA
        },
        #----------------------------------------------------------------
    
    
    
    
          #----------------------------------------------------------------
        # Insert the transformation parameters prm in the input expressions and regression expressions, and keep them (simply string manipulation)
        insert_prm = function(prm){
            # If just NA or NULL given, then don't do anything
            if(is.null(prm) | (is.na(prm)[1] & length(prm) == 1)){
                return(NULL)
            }
            # MUST INCLUDE SOME checks here and print useful messages if something is not right
            if(any(is.na(prm))){ stop(pst("None of the parameters (in prm) must be NA: prm=",prm)) }
    
            # Keep the prm
            self$prm <- prm
            # Find if any opt parameters, first the one with "__" hence for the inputs
            pinputs <- prm[grep("__",nams(prm))]
            # If none found for inputs, then the rest must be for regression
            if (length(pinputs) == 0 & length(prm) > 0) {
                preg <- prm
            } else {
                preg <- prm[-grep("__",nams(prm))]
            }
            # ################
            # For the inputs, insert from prm if any found
            if (length(pinputs)) {
                pnms <- unlist(getse(strsplit(nams(pinputs),"__"), 1))
                pprm <- unlist(getse(strsplit(nams(pinputs),"__"), 2))
                #
                for(i in 1:length(self$inputs)){
                    for(ii in 1:length(pnms)){
                        # Find if the input i have prefix match with the opt. parameter ii
                        if(pnms[ii]==nams(self$inputs)[i]){
                            # if the opt. parameter is in the expr, then replace
                            self$inputs[[i]]$expr <- private$replace_value(name = pprm[ii],
                                                                           value = pinputs[ii],
                                                                           expr = self$inputs[[i]]$expr)
                        }
                    }
                }
            }
            # ################
            # For the fit parameters, insert from prm if any found
            if (length(preg) & any(!is.na(self$regprmexpr))) {
                nams(preg)
                for(i in 1:length(preg)){
                    # if the opt. parameter is in the expr, then replace
                    self$regprmexpr <- private$replace_value(name = nams(preg)[i],
                                                             value = preg[i],
                                                             expr = self$regprmexpr)
                }
            }
            self$regprm <- eval(parse(text = self$regprmexpr))
        },
        #----------------------------------------------------------------
    
          #----------------------------------------------------------------    
        # Add inputs to the model
        add_inputs = function(...){
            dots <- list(...)
            for (i in 1:length(dots)){
                self$inputs[[ nams(dots)[i] ]] <-  onlineforecast:::input_class$new(dots[[i]], model=self)
            }
        },
    
        #----------------------------------------------------------------
        # Add the expression (as character) which generates the regression parameters
        add_regprm = function(regprmexpr){
            self$regprmexpr <- regprmexpr
            self$regprm <- eval(parse(text = self$regprmexpr))
        },
        #----------------------------------------------------------------
    
    
    
    
          #----------------------------------------------------------------
        # Function for transforming the input data to the regression data
        transform_data = function(data){
            # Evaluate for each input the expresssion to generate the model input data
            L <- lapply(self$inputs, function(input){
                # Evaluate the expression (input$expr)
                L <- input$evaluate(data)
                # Must return a list
                if(class(L)[1]=="matrix"){ return(list(as.data.frame(L))) }
                if(class(L)[1]=="data.frame"){ return(list(L)) }
                if(class(L)[1]!="list"){ stop(pst("The value returned from evaluating: ",input$expr,", was not a matrix, data.frame or a list of them."))}
                if(class(L[[1]])[1]=="matrix"){ return(lapply(L, function(mat){ return(as.data.frame(mat)) })) }
                return(L)
            })
            # Put together in one data.list
            L <- structure(do.call(c, L), class="data.list")
            #
            return(L)
        }
    ),
    # Private functions
        private = list(
        #----------------------------------------------------------------
    
    
        #----------------------------------------------------------------
        # Replace the value in "name=value" in expr
        replace_value = function(name, value, expr){
            # First make regex
            pattern <- gsub("\\.", ".*", name)
            # Try to find it in the input
            pos <- regexpr(pattern, expr)
            # Only replace if prm was found
            if(pos>0){
                pos <- c(pos+attr(pos,"match.length"))
                # Find the substr to replace with the prm value
                (tmp <- substr(expr, pos, nchar(expr)))
                pos2 <- regexpr(",|)", tmp)
                # Insert the prm value and return
                expr <- pst(substr(expr,1,pos-1), "=", value, substr(expr,pos+pos2-1,nchar(expr)))
                # Print? Not used now
                #if(printout){ message(names(value),"=",value,", ",sep="")}
            }
            return(expr)
        }
        #----------------------------------------------------------------
    ))