sorting vector in nimble

111 views
Skip to first unread message

MPrzys

unread,
Sep 23, 2021, 3:21:04 PM9/23/21
to nimble-users
Dear nimble-users,

I'm new to nimble. Recently, I used WinBUGS in my work,  but I saw that nimble has some nice features. However, when I looked into the manual I found out that there is no function for sorting a vector. In some applications this function is important. Using the manual, I tried to write my own nimbleFunction but apparently one can not use functions from other packages than nimble. Below, I enclose my script with my nimble function. 


library(nimble)

library(base)

n <- 10

set.seed(11)

x <- rnorm(n)


X.sort <- {x[1]}

for(i in 2:n){

  X.sort <- append(X.sort, x[i], after = sum(X.sort > x[i]))

}

X.sort

sort<-nimbleFunction(

run=function(x=double(1))

sort<-x[1]

for(i in 2:length(x)){

sort<-append(sort,x[i],after=sum(sort>x[i]))})

sort(x)

For this reason, I'd like to ask whether there is a method for sorting a vector? Or maybe You could help me and point out my mistakes in constructing the function. 


I would be grateful for help.

Best regards
Marcin

Sally paganin

unread,
Sep 24, 2021, 3:14:15 AM9/24/21
to MPrzys, nimble-users
Hi Marcin, 

great you are looking into nimble!  I can offer some help as I had a similar problem. It is possible to call an R function in nimble, but the function needs to be wrapped in a nimbleRcall. Here I made a little example using the R sort function but it can work also with append I guess.

library(nimble)

x <- c(9,2,5,6,1)
sort(x)
# 1 2 5 6 9

## make a function to call R sort function in nimble via nimbleRcall
sortR <- nimbleRcall(prototype   = function(x = double(1)) {},
                     Rfun       = "sort",
                     returnType = double(1))

sortR(x)
# 1 2 5 6 9


The wrapped function can then be used in compiled code, for example:

demoCode <- nimbleCode({
     for(i in 1:4) {x[i] ~ dnorm(0,1)}
     z[1:4] <- sortR(x[1:4])
 })

set.seed(42)
demoModel <- nimbleModel(demoCode, inits = list(x = rnorm(4)))

CdemoModel <- compileNimble(demoModel)
CdemoModel$x
## 1.3709584 -0.5646982  0.3631284  0.6328626
CdemoModel$z
## -0.5646982  0.3631284  0.6328626  1.3709584


Hope this helps!

Best regards,

Sally 

--
You received this message because you are subscribed to the Google Groups "nimble-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nimble-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/nimble-users/9efa2c7b-26ec-48da-87bd-2941d6fbdbb5n%40googlegroups.com.

David Pleydell

unread,
Sep 24, 2021, 1:05:28 PM9/24/21
to nimble-users
Hi Marcin
 
If you need a compiled version for speed, some years ago Soledad Castano and I wrote a function for finding a median that performed a bubble sort.  Here's our code, you could probably simplify it to fit you needs. 

Best regards
David

################################
## Performs bubble sort to find a median ##
################################
bubbleMedian <- nimbleFunction(
    setup = function(){ }, 
    run = function(x=double(1)) {
        lx      <- dim(x)[1]
        ## browser()
        x[1:lx] <- BubbleSort(x[1:lx])
        lx2     <- lx/2
        clx2    <- ceiling(lx2)
        flx2    <- floor(lx2+1)
        return((x[flx2] + x[clx2]) / 2)
        returnType(double())
    },
    methods = list(
        BubbleSort = function(X=double(1)) {
            lx      <- dim(X)[1]
            lxMin1  <- lx-1
            madeChange <- TRUE        
            while(madeChange) {
                madeChange <- FALSE
                for (ii in 1:lxMin1) {
                    ii1 <- ii+1
                    if (X[ii] > X[ii1]) {
                        tmp    <- X[ii]
                        X[ii]  <- X[ii1]
                        X[ii1] <- tmp
                        madeChange <- TRUE
                    }
                }
            }
            return(X)
            returnType(double(1))
        }
    )
)

## Set up
BubbleMedian <- bubbleMedian()

## Small example
x <- runif(20)
BubbleMedian$BubbleSort(x)
BubbleMedian$run(x)
median(x)

## Compile
cBubbleMedian <- compileNimble(BubbleMedian)

## Longer example
x <- runif(10*52)
median(x)
cBubbleMedian$run(x)
cBubbleMedian$BubbleSort(x)
system.time(median(x))
system.time(cBubbleMedian$run(x))

MPrzys

unread,
Sep 27, 2021, 3:29:02 AM9/27/21
to nimble-users
Dear Sally and David,

Thanks for quick response and for the tips.

Best regards
Marcin  

Reply all
Reply to author
Forward
0 new messages