sexta-feira, 25 de fevereiro de 2022

Calculando determinante de uma matriz pelo Teorema de Laplace - Parte III

Nos posts anteriores, implementamos o teorema de Laplace para calcular o determinante de uma matriz quadrada. Na Parte I construímos a função recursiva e, na Parte II, a função iterativa. Neste post, vamos comparar a eficiência das duas funções que criamos e com a função det embutida no R.

Para isso, vamos utilizar o pacote rbenchmark. Vamos testar nossas funções com uma matriz de ordem 5:

set.seed(7)
M = matrix(sample(1:100,size = 25,replace = F),ncol=5,byrow = T)

> M
     [,1] [,2] [,3] [,4] [,5]
[1,]   42   83   31   92   66
[2,]   15   90    8   67   88
[3,]   40   22   47   93   59
[4,]   12   51   20   94   98
[5,]   79    6   16   89   86

Vamos utilizar a função benchmark e fazer 1000 replicações. Vejamos:

> benchmark(det(M),calc_det(M),calc_det_laplace(M),replications = 1000,
+           columns = c("test", "replications", "elapsed","relative"))
                 test replications elapsed relative
2         calc_det(M)         1000    0.19    6.333
3 calc_det_laplace(M)         1000    0.25    8.333
1              det(M)         1000    0.03    1.000

Veja que a função det é muito mais eficiente que as nossas, o que era esperado, pois as funções do R já são otimizadas.

Agora perceba algo interessante: a função recursiva foi executada mais rápida que a iterativa. Isso ocorreu, provavelmente, pelo fato de construirmos e armazenamos a árvore de matrizes. Se fizermos a conta, o tempo de execução da função iterativa é 1,32 vezes o tempo da função recursiva.

Quanto maior a dimensão da matriz, mais custoso será para calcularmos seu determinante e será mais pesado para nossas funções. Por exemplo, considere a matriz de ordem 10 abaixo:

set.seed(7)
M = matrix(sample(1:100,size = 100,replace = F),ncol=10,byrow = T)

> M
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
 [1,]   42   83   31   92   66   15   90    8   67    88
 [2,]   40   22   47   93   59   12   51   20   94    98
 [3,]   79    6   16   89   86   21    4   11   26     2
 [4,]   38   43   36    3   53   41   96   77   87    45
 [5,]   91   65   81   34   32   85   75   62   24    10
 [6,]   46   82   48   23    5   56   70   97   76    78
 [7,]   64   28  100   18   29   84   30   63   55    80
 [8,]   74   44   17   73   13   61   60   52   37     1
 [9,]   39   54   25   27   68   71    9   35   19    49
[10,]   14   72   58   57   99   69    7   33   95    50

Para essa matriz, temos os seguintes tempos de execução:

> t1 = Sys.time()
> det(M)
[1] 1.197026e+18
> t2 = Sys.time()
> calc_det_laplace(M)
[1] 1.197026e+18
> t3 = Sys.time()
> calc_det(M)
[1] 1.197026e+18
> t4 = Sys.time()

> t2-t1
Time difference of 0.002995014 secs
> t3-t2
Time difference of 10.98335 secs
> t4-t3
Time difference of 6.374352 secs

Perceba que todas as funções apresentaram o mesmo resultado, como era de se esperar. Mas observe o tempo de execução. A função det não chegou a 0,1 segundo de execução, ao passo que nossas funções apresentam tempos bem maiores.

Isso nos mostra que é preferível utilizar as funções já otimizadas do R ao invés de implementá-las. É claro, nossa estratégia de pegar sempre a primeira linha da matriz é ingênua e o código não está otimizado, mas é fato que vale a pena implementar esse tipo de função se for melhor do que o R já disponibiliza.

O intuito com o exercício dessa série foi praticar a programação e utilizamos vários conceitos para isso. Logo, nossa missão foi cumprida.

Espero que tenha gostado da aula.

Até a próxima aula!

Nenhum comentário:

Postar um comentário