Julia 编写 k 步前瞻函数的方法?
Julia way to write k-step look ahead function?
假设我有两个表示概率图的数组:
2
/ \
1 -> 4 -> 5 -> 6 -> 7
\ /
3
其中进入状态 2 的概率为 0.81
,进入状态 3 的概率为 (1-0.81) = 0.19
。我的数组代表状态的估计值以及奖励。 (注:数组的每个索引代表其各自的状态)
V = [0, 3, 8, 2, 1, 2, 0]
R = [0, 0, 0, 4, 1, 1, 1]
上下文并不重要,它只是让我知道我来自哪里。我需要编写一个 k 步前瞻函数,在其中我将奖励的折扣值相加并将其添加到第 k 个状态的估计值中。
到目前为止,我已经能够通过为向前看的每个步骤创建单独的函数来做到这一点。 我问这个问题的目的是弄清楚如何重构这段代码,这样我就不会重复自己并使用惯用的 Julia。
这是我所说的一个例子:
function E₁(R::Array{Float64,1}, V::Array{Float64, 1}, P::Float64)
V[1] + 0.81*(R[1] + V[2]) + 0.19*(R[2] + V[3])
end
function E₂(R::Array{Float64,1}, V::Array{Float64, 1}, P::Float64)
V[1] + 0.81*(R[1] + R[3]) + 0.19*(R[2] + R[4]) + V[4]
end
function E₃(R::Array{Float64,1}, V::Array{Float64, 1}, P::Float64)
V[1] + 0.81*(R[1] + R[3]) + 0.19*(R[2] + R[4]) + R[5] + V[5]
end
.
.
.
依此类推。似乎如果我要忽略 E₁()
这将非常容易重构。但是因为我必须对两个不同状态下的价值估计进行折扣,所以我很难想出一种方法来将其推广到 k 步。
我认为我显然可以编写一个函数,将整数作为值,然后使用一堆 if 语句,但这似乎不符合 Julia 的精神。关于如何重构这个的任何想法?某种关闭?存储 R 和 V 的不同数据类型?
看起来你基本上有一个离散的 Markov chain。所以标准方法是将图形存储为其转换矩阵:
T = zeros(7,7)
T[1,2] = 0.81
T[1,3] = 0.19
T[2,4] = 1
T[3,4] = 1
T[5,4] = 1
T[5,6] = 1
T[6,7] = 1
然后你可以通过从左边乘以 T'
来计算在每个状态结束的概率,给定一个初始分布(因为通常,转换矩阵是转置定义的):
julia> T' * [1,0,0,0,0,0,0] # starting from (1)
7-element Array{Float64,1}:
0.0
0.81
0.19
0.0
0.0
0.0
0.0
同样,在 k
步之后到达每个状态的概率可以使用 T'
:
的幂来计算
julia> T' * T' * [1,0,0,0,0,0,0]
7-element Array{Float64,1}:
0.0
0.0
0.0
1.0
0.0
0.0
0.0
既然您在 k
步之后有了所有概率,您也可以轻松计算期望值。也许将 T
定义为稀疏矩阵是值得的。
假设我有两个表示概率图的数组:
2
/ \
1 -> 4 -> 5 -> 6 -> 7
\ /
3
其中进入状态 2 的概率为 0.81
,进入状态 3 的概率为 (1-0.81) = 0.19
。我的数组代表状态的估计值以及奖励。 (注:数组的每个索引代表其各自的状态)
V = [0, 3, 8, 2, 1, 2, 0]
R = [0, 0, 0, 4, 1, 1, 1]
上下文并不重要,它只是让我知道我来自哪里。我需要编写一个 k 步前瞻函数,在其中我将奖励的折扣值相加并将其添加到第 k 个状态的估计值中。
到目前为止,我已经能够通过为向前看的每个步骤创建单独的函数来做到这一点。 我问这个问题的目的是弄清楚如何重构这段代码,这样我就不会重复自己并使用惯用的 Julia。
这是我所说的一个例子:
function E₁(R::Array{Float64,1}, V::Array{Float64, 1}, P::Float64)
V[1] + 0.81*(R[1] + V[2]) + 0.19*(R[2] + V[3])
end
function E₂(R::Array{Float64,1}, V::Array{Float64, 1}, P::Float64)
V[1] + 0.81*(R[1] + R[3]) + 0.19*(R[2] + R[4]) + V[4]
end
function E₃(R::Array{Float64,1}, V::Array{Float64, 1}, P::Float64)
V[1] + 0.81*(R[1] + R[3]) + 0.19*(R[2] + R[4]) + R[5] + V[5]
end
.
.
.
依此类推。似乎如果我要忽略 E₁()
这将非常容易重构。但是因为我必须对两个不同状态下的价值估计进行折扣,所以我很难想出一种方法来将其推广到 k 步。
我认为我显然可以编写一个函数,将整数作为值,然后使用一堆 if 语句,但这似乎不符合 Julia 的精神。关于如何重构这个的任何想法?某种关闭?存储 R 和 V 的不同数据类型?
看起来你基本上有一个离散的 Markov chain。所以标准方法是将图形存储为其转换矩阵:
T = zeros(7,7)
T[1,2] = 0.81
T[1,3] = 0.19
T[2,4] = 1
T[3,4] = 1
T[5,4] = 1
T[5,6] = 1
T[6,7] = 1
然后你可以通过从左边乘以 T'
来计算在每个状态结束的概率,给定一个初始分布(因为通常,转换矩阵是转置定义的):
julia> T' * [1,0,0,0,0,0,0] # starting from (1)
7-element Array{Float64,1}:
0.0
0.81
0.19
0.0
0.0
0.0
0.0
同样,在 k
步之后到达每个状态的概率可以使用 T'
:
julia> T' * T' * [1,0,0,0,0,0,0]
7-element Array{Float64,1}:
0.0
0.0
0.0
1.0
0.0
0.0
0.0
既然您在 k
步之后有了所有概率,您也可以轻松计算期望值。也许将 T
定义为稀疏矩阵是值得的。