2013-12-08 2 views
0

Цель: создать набор прямоугольных ящиков и сгруппировать их на сетку 10x10. Моя функция getCoordinates генерирует numBoxes коробки случайного размера с целыми длинами от 1 до 10. Переменная gridTops отслеживает максимальную высоту, занимаемую каждой ячейкой сетки 10x10. Функция возвращает список двух элементов, содержащий матрицу с координатами уложенных блоков и gridTops.Как ускорить выполнение этого R-кода

getCoordinates<-function(numBoxes){ 
    # Generates numBoxes random sized boxes with integer dimensions between 1 and 10. 
    # Stacks them and returns results 
    boxes<-data.frame(boxId=1:numBoxes, 
        xDim=sample(10,numBoxes, replace=TRUE), 
        yDim=sample(10,numBoxes, replace=TRUE), 
        zDim=sample(10,numBoxes, replace=TRUE)) 
    gridTops<-matrix(0,nrow=10,ncol=10) 
    coordinates<-matrix(nrow=nrow(boxes), 
         ncol=6, 
         dimnames=list(boxes$boxId,c("x1","y1","z1","x8","y8","z8"))) 
    for(i in 1:nrow(boxes)){ 
    mylist<-addBox(boxes[i,], gridTops); 
    coordinates[i,]<-mylist[["coordinates"]]; 
    gridTops<-mylist[["gridTops"]]; 
    } 
    return(list(boxes=boxes, coordinates=coordinates)); 
} 

addBox<-function(boxDimensions, gridTops){ 
    #Returns a list of coordinates and the updated gridTops matrix 
    xd<-boxDimensions$xDim 
    yd<-boxDimensions$yDim 
    zd<-boxDimensions$zDim 
    x1<-0 
    y1<-0 
    z1<-max(gridTops[1:xd,1:yd]) 
    gridTops[1:xd,1:yd]<-(z1+zd) 
    coordinates<-c(x1,y1,z1,x1+xd,y1+yd,z1+zd) 
    return(list(coordinates=coordinates,gridTops=gridTops)) 
} 

В качестве примера,

test<-getCoordinates(5) 
test[["boxes"]] 
    boxId xDim yDim zDim 
1  1 5 2 4 
2  2 9 1 4 
3  3 1 7 7 
4  4 10 6 1 
5  5 5 8 10 
test[["coordinates"]] 
    x1 y1 z1 x2 y2 z2 
1 0 0 0 5 2 4 
2 0 0 4 9 1 8 
3 0 0 8 1 7 15 
4 0 0 15 10 6 16 
5 0 0 16 5 8 26 

Как вы можете видеть, мой метод укладки коробок просто положить один на вершине другого с одного угла на (х = 0, у = 0) клетка. Достаточно просто, но для укладки пакетов на 10000+ требуется много времени. Например

system.time(getCoordinates(10000)) 
user system elapsed 
2.755 0.414 3.169 

Я думаю, что мой цикл замедляет вещи вниз, но я не знаю, как применить применить функцию в этой ситуации. Как я могу ускорить это?

Редактировать: Метод addBox может быть изменен. Как я уже говорил, он просто складывает одну коробку прямо сверху. Это наивный алгоритм упаковки, но я написал его для иллюстративных целей.

+0

Когда я запускаю свой код, а затем ' test <-getCoordinates (5) ', test - это матрица координат, а не список (??). – jlhoward

+0

@jlhoward oops! См. Мой отредактированный код. Извини за это. – Ben

ответ

1

Изменение boxes от data.frame до matrix ускоряет его значительно для меня.

Я изменил

boxes<-data.frame(

в

boxes <- cbind(

и редактируются места, где вы доступ коробки в двух функций, пошел от:

R>system.time(getCoordinates(10000)) 
    user system elapsed 
    1.926 0.000 1.941 
R>getCoordinates <- edit(getCoordinates) 
R>addBox <- edit(addBox) 
R>system.time(getCoordinates(10000)) 
    user system elapsed 
    0.356 0.002 0.362 
+0

Как вы пропустили матрицу 'boxes'? Вы использовали цикл for как я или что-то еще? – Ben

+0

Да, я * только * изменил поля, чтобы быть матрицей. –

+1

Вам также нужно изменить такие вещи, как 'boxes $ boxId' на' boxes [, "boxId"] '. – flodel

Смежные вопросы