mbu*_*nit 4 python algorithm ocaml matrix
我想知道是否有人可以帮助我调试以下OCaml代码,该代码应该计算正定矩阵的上三角cholesky分解.
我知道它不是很实用,而且非常厚实,所以我提前道歉.我在下面给出了一些理由.
无论如何这里去!
let rec calc_S m1 k i =
if k == i then
let float = sum_array m1.(i) in float
else
begin
m1.(k).(i) <- m1.(k).(i)**2.;
calc_S m1 (k+1) i;
end
;;
let rec calc_S1 m1 k i j len=
if k == len then
let float = sum_array m1.(i) in float
else
begin
m1.(k).(j) <- m1.(k).(i)*. m1.(k).(j);
calc_S1 m1 (k+1) i j len;
end
;;
let cholesky m1 =
let ztol = 1.0e-5 in
let result = zerof (dimx m1) (dimx m1) in
let range_xdim = (dimx m1) - 1 in
let s = ref 0.0 in
for i=0 to range_xdim do
begin
s := calc_S result 0 i;
let d = m1.(i).(i) -. !s in
if abs_float(d) < ztol then
result.(i).(i) <- 0.0
else
if d < 0.0 then
raise Matrix_not_positive_definite
else
result.(i).(i) <- sqrt d;
for j=(i+1) to range_xdim do
s:= calc_S1 result 0 i j range_xdim;
if abs_float (!s) < ztol then
s:= 0.0;
result.(i).(j) <- (m1.(i).(j) -. !s) /. result.(i).(i)
done
end
done;
result;;
Run Code Online (Sandbox Code Playgroud)
其中dimx,dimy是返回矩阵(2d-array)维度的简单函数,zerof生成具有适当维度的零浮点矩阵,sum_array是用于求和数组元素的简单函数,显然异常先前已定义.
由于某种原因,它会错误地计算以下内容[编辑:顶部循环被污染,添加了正确的错误计算]:
f;;
- : float array array =
[| 1.; 0.; 0.1; 0. |]
[| 0.; 1.; 0.; 0.1 |]
[| 0.; 0.; 1.; 0. |]
[| 0.; 0.; 0.; 1. |]
# cholesky f;;
- : float array array =
[| 1.; 0.; 0.; 0. |]
[| 0.; 1.; 0.; 0. |]
[| 0.; 0.; 1.; 0. |]
[| 0.; 0.; 0.; 1. |]
Run Code Online (Sandbox Code Playgroud)
这应该是根据python代码:
[1.0, 0.0, 0.1, 0.0]
[0, 1.0, 0.0, 0.1]
[0, 0, 0.99498743710662, 0.0]
[0, 0, 0, 0.99498743710662]
Run Code Online (Sandbox Code Playgroud)
但是得到以下权利:
# r;;
- : float array array =
[| 0.1; 0. |]
[| 0.; 0.1 |]
# cholesky r;;
- : float array array =
[| 0.316227766017; 0. |]
[| 0.; 0.316227766017 |]
Run Code Online (Sandbox Code Playgroud)
但是由于这个功能有很多指数,我的头开始旋转.我确信这是问题所在,或者是计算.有些东西肯定是错的;)
如果它有帮助,我可以附加我正在移植它的python代码,因为我试图保持尽可能接近原始,没有递归,因此在附加的OCaml版本中没有递归,因此也有一些尴尬(在OCaml).
[编辑:附加python代码]
def Cholesky(self, ztol=1.0e-5):
# Computes the upper triangular Cholesky factorization of
# a positive definite matrix.
res = matrix([[]])
res.zero(self.dimx, self.dimx)
for i in range(self.dimx):
S = sum([(res.value[k][i])**2 for k in range(i)])
d = self.value[i][i] - S
if abs(d) < ztol:
res.value[i][i] = 0.0
else:
if d < 0.0:
raise ValueError, "Matrix not positive-definite"
res.value[i][i] = sqrt(d)
for j in range(i+1, self.dimx):
S = sum([res.value[k][i] * res.value[k][j] for k in range(self.dimx)])
if abs(S) < ztol:
S = 0.0
res.value[i][j] = (self.value[i][j] - S)/res.value[i][i]
return res
Run Code Online (Sandbox Code Playgroud)
根据惊人的快速请求:)我很确定我搞砸了声明里面的总结如下:
S = sum([res.value[k][i] * res.value[k][j] for k in range(self.dimx)])
Run Code Online (Sandbox Code Playgroud)
一个绝对错误的事情是,你不应该修改m1中calc_S和calc_S1,这些功能假设只返回的款项.由于您没有提供完整的实现,这是解决它的一种方法:
let calc_S res i =
let sum = ref 0. in
for k = 0 to i-1 do
sum := !sum +. (res.[k].[i] ** 2.)
done;
!sum
let calc_S1 res i dim =
let sum = ref 0. in
for j = i+1 to dim-1 do
for k = 0 to dim-1 do
sum := !sum +. (res.[k].[i] *. res.[k].[j])
done
done;
!sum
Run Code Online (Sandbox Code Playgroud)
除了这个错误,代码的其余部分看起来对我来说.
| 归档时间: |
|
| 查看次数: |
398 次 |
| 最近记录: |