Nesta aula, vamos construir e visualizar diferentes maneiras de gerar sequências de valores que podem ser usadas como base para esquemas de reforço. A ideia central é simples: dependendo da distribuição ou regra usada para gerar os intervalos ou razões, obtemos propriedades distintas de variabilidade, previsibilidade e dispersão.
Ao longo do material, veremos:
em que cada \(x_i\) representa, por exemplo:
Ao longo da aula, veremos cinco estratégias principais:
Uma série aritmética cresce ou decresce por uma diferença constante. Seu formato geral é:
\[\begin{align} x_i = \bar{x} + \left(i - \frac{N+1}{2}\right)d \end{align}\]
em que:
## [1] 13.5 16.5 19.5 22.5 25.5 28.5 31.5 34.5 37.5 40.5 43.5 46.5
plot(x, type = "b", pch = 16,
xlab = "Posição na sequência",
ylab = "Valor",
main = "Série aritmética")
abline(h = mean(x), lty = 2)Essa função é útil quando queremos uma sequência perfeitamente previsível, simétrica em torno da média e com espaçamento constante entre valores.
Ela pode ser usada para construir listas didáticas de intervalos ou razões, mas não produz a irregularidade típica de um esquema variável real.
Em uma série geométrica, cada termo é obtido multiplicando o anterior por uma razão constante \(r\).
\[\begin{align} x_i = a r^{i-1} \end{align}\]
Quando queremos fixar a média da sequência, podemos resolver o valor inicial \(a\) a partir da soma total desejada.
## [1] 7.704551 9.245462 11.094554 13.313465 15.976158 19.171389 23.005667
## [8] 27.606801 33.128161 39.753793
## [1] 20
plot(x, type = "b", pch = 16,
xlab = "Posição na sequência",
ylab = "Valor",
main = "Série geométrica")
abline(h = mean(x), lty = 2)Comparada à série aritmética, a progressão geométrica produz uma expansão mais rápida entre valores sucessivos. Em esquemas de reforço, isso pode ser interessante quando se quer maior concentração de valores pequenos e poucos valores muito grandes, ou o oposto, dependendo da ordem da série.
Em alguns contextos, especialmente em esquemas VR ou VI discretizados em unidades inteiras, queremos sequências compostas apenas por números inteiros.
A função abaixo procura sequências geométricas inteiras cuja média seja um inteiro positivo especificado.
geometricas_inteiras = function(media, N_max = NULL, r_max = NULL) {
if (media %% 1 != 0 || media < 1) {
stop("A média deve ser um inteiro positivo.")
}
resultados = data.frame(
N = integer(),
r = integer(),
a = integer(),
soma = integer(),
stringsAsFactors = FALSE
)
series = list()
if (is.null(N_max)) {
N_max = 100
}
idx = 1
for (N in 2:N_max) {
soma_total = media * N
if (soma_total < (2^N - 1)) {
break
}
r = 2
while (TRUE) {
S = sum(r^(0:(N - 1)))
if (S > soma_total) {
break
}
a = soma_total / S
if (a %% 1 == 0 && a >= 1) {
serie = a * r^(0:(N - 1))
resultados[idx, ] = list(
N = N,
r = r,
a = a,
soma = sum(serie)
)
series[[idx]] = serie
idx = idx + 1
}
r = r + 1
if (!is.null(r_max) && r > r_max) {
break
}
}
}
if (nrow(resultados) == 0) {
return(list(resumo = NULL, series = NULL))
}
resultados$serie = vapply(series,
function(x) paste(x, collapse = ", "),
character(1))
list(
resumo = resultados,
series = series
)
}Vamos buscar séries inteiras com média 12:
## # A tibble: 4 × 5
## N r a soma serie
## <int> <dbl> <dbl> <dbl> <chr>
## 1 2 2 8 24 8, 16
## 2 2 3 6 24 6, 18
## 3 2 5 4 24 4, 20
## 4 2 7 3 24 3, 21
Se houver séries disponíveis, vamos inspecionar uma delas:
## [1] 8 16
Esse tipo de função é especialmente útil quando há restrições práticas: por exemplo, razões precisam ser inteiras e, ainda assim, queremos preservar certa estrutura geométrica.
Agora vamos construir uma amostra determinística inspirada na distribuição normal. A ideia é dividir a distribuição acumulada em fatias de mesma probabilidade e representar cada fatia por seu valor esperado condicional.
A distribuição normal com média \(\mu\) e desvio-padrão \(\sigma\) tem densidade:
\[\begin{align} f(x) = \frac{1}{\sigma\sqrt{2\pi}} \exp\left( -\frac{(x-\mu)^2}{2\sigma^2} \right) \end{align}\]
A função abaixo gera \(N\) valores que cobrem sistematicamente a distribuição.
normal_deterministica = function(N, mu = 0, sigma = 1, embaralhar = TRUE) {
p = seq(0, 1, length.out = N + 1)
z = qnorm(p)
x = numeric(N)
for (i in 1:N) {
a = z[i]
b = z[i + 1]
da = if (is.infinite(a)) 0 else dnorm(a)
db = if (is.infinite(b)) 0 else dnorm(b)
prob_fatia = pnorm(b) - pnorm(a)
x[i] = mu + sigma * (da - db) / prob_fatia
}
if (embaralhar) {
x = sample(x)
}
x
}## [1] 35.76604 25.31969 29.05377 32.27064 32.99160 26.21853 31.59435 27.72936
## [9] 22.76373 34.68031 37.23627 28.40565 29.68626 33.78147 24.23396 27.00840
## [17] 30.94623 40.31356 19.68644 30.31374
## [1] 30
## [1] 5.086893
plot(serie_normal,
type = "b",
pch = 16,
xlab = "Posição na sequência",
ylab = "Valor",
main = "Amostra determinística baseada na normal")
abline(h = mean(serie_normal), lty = 2)Veja também o histograma de valores:
Esse método é útil quando se quer cobrir o espaço de valores de forma regular, sem depender de amostragem puramente aleatória.
Fleshler e Hoffman propuseram uma progressão para distribuição de intervalos em esquemas variáveis, buscando evitar problemas associados a listas arbitrárias ou excessivamente irregulares.
A função abaixo implementa a forma contínua dessa progressão.
fleshler_hoffman = function(media, N) {
if (!is.numeric(media) || length(media) != 1 || media <= 0) {
stop("`media` deve ser um número positivo.")
}
if (!is.numeric(N) || length(N) != 1 || N < 1 || N %% 1 != 0) {
stop("`N` deve ser um inteiro positivo.")
}
t = numeric(N)
for (n in 1:N) {
if (n == N) {
t[n] = media * (1 + log(N))
} else {
t[n] = media * (
1 + log(N) +
(N - n) * log(N - n) -
(N - n + 1) * log(N - n + 1)
)
}
}
return(t)
}## [1] 0.7628222 2.3424993 4.0100244 5.7757494 7.6519720 9.6534561
## [7] 11.7981392 14.1081127 16.6110143 19.3420561 22.3470762 25.6873023
## [13] 29.4471295 33.7475414 38.7709506 44.8116047 52.3917509 62.5856931
## [19] 78.2831374 119.8719682
## [1] 30
Para esquemas de razão variável (VR), precisamos de valores inteiros e, além disso, razões não podem ser zero. A função abaixo adapta a sequência contínua de Fleshler e Hoffman para uma sequência inteira com média preservada.
fh_ratio = function(media, N, seed = NULL) {
if (!is.null(seed)) set.seed(seed)
x = fleshler_hoffman(media, N)
x_int = floor(x)
x_int[x_int < 1] = 1
soma_alvo = media * N
dif = soma_alvo - sum(x_int)
if (dif > 0) {
frac = x - x_int
idx = order(frac, decreasing = TRUE)
x_int[idx[1:dif]] = x_int[idx[1:dif]] + 1
} else if (dif < 0) {
frac = x - x_int
idx = order(frac)
for (i in idx) {
if (x_int[i] > 1) {
x_int[i] = x_int[i] - 1
dif = dif + 1
if (dif == 0) break
}
}
}
x_int = sample(x_int)
return(x_int)
}Vamos gerar um exemplo de VR 20 com 30 elementos.
## [1] 13 19 12 2 8 17 25 9 3 21 50 30 7 43 6 38 5 88 34 16 2 1 28 23 60
## [26] 11 14 1 10 4
## [1] 20
## [1] 600
plot(vr_fh,
type = "b",
pch = 16,
xlab = "Posição na lista",
ylab = "Razão",
main = "Lista VR inteira baseada em Fleshler-Hoffman")
abline(h = mean(vr_fh), lty = 2)Veja também o histograma
A vantagem dessa abordagem é combinar: