Advertisement
Guest User

nnjmvmv

a guest
May 12th, 2017
113
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
OCaml 3.78 KB | None | 0 0
  1. (* wrapper around the fortan mvndst library from Genz. must be in $HOME/lib as
  2.  * a shared library *)
  3.  
  4. open Bigarray
  5. open Lacaml.D
  6. open Ctypes
  7. open Util
  8. open Containers
  9.  
  10. [@@@landmark "auto"]
  11. (*let integration = Landmark.register "integration"*)
  12.  
  13. let integer = Ctypes_static.int32_t   (* fortran integer type representation *)
  14.  
  15. let os =
  16.   assert (Sys.os_type = "Unix");
  17.   let ic = Unix.open_process_in "uname" in
  18.   let uname = input_line ic in
  19.   let () = close_in ic in
  20.   if uname = "Darwin" then `MacOs else `Linux
  21.  
  22. (* get the library *)
  23. let mvnd =
  24.   let filename = Sys.getenv "HOME" ^ "/lib/mvndst." ^
  25.                  (if os = `MacOs then "dylib" else "so") in
  26.   Dl.dlopen ~flags:[Dl.RTLD_LAZY] ~filename
  27.  
  28. (* the integration routine which gives the integral in value *)
  29. let integrate = Foreign.foreign ~from:mvnd "mvndst_"
  30.     (ptr integer @-> (* N *)
  31.      ptr double  @-> (* LOWER *)
  32.      ptr double  @-> (* UPPER *)
  33.      ptr integer @-> (* INFIN *)
  34.      ptr double  @-> (* CORREL *)
  35.      ptr integer @-> (* MAXPTS *)
  36.      ptr double  @-> (* ABSEPS *)
  37.      ptr double  @-> (* RELEPS *)
  38.      ptr double  @-> (* ERROR *)
  39.      ptr double  @-> (* VALUE *)
  40.      ptr integer @-> (* INFORM *)
  41.      returning void);;
  42.  
  43. (* c_layout arrays to get the start address *)
  44. let c_make0 n =
  45.   let a = Array1.create float64 c_layout n in
  46.   Array1.fill a 0.; a
  47.  
  48. let v2c fa =
  49.   fa |> genarray_of_array1
  50.   |> (fun fga -> Genarray.change_layout fga c_layout)
  51.   |> array1_of_genarray
  52.  
  53. (* arrange a symmetric positive matrix in the way the library expects *)
  54. let lower_vec mat =
  55.   let d = Mat.dim1 mat in
  56.   let v = Vec.create (d * (d - 1) / 2) in
  57.   for i = 1 to d do for j = 1 to i - 1 do
  58.       v.{j + (i-2)*(i-1)/2} <- mat.{i,j} done done;
  59.   v
  60.  
  61. (* correlation and variances *)
  62. let corr_vars ci =
  63.   let c = U.po_inv ci in                                (* covariance matrix *)
  64.   let vars = Mat.copy_diag c in
  65.   let istds =vars |> Vec.sqrt |> Vec.reci in
  66.   Mat.scal_cols c istds;
  67.   Mat.scal_rows istds c;
  68.   lower_vec c, vars
  69.  
  70. exception Integration_error of string
  71.  
  72. let log_gauss_integral
  73.     ?lower ?upper
  74.     ?infin
  75.     ?maxpts
  76.     ?releps ?abseps
  77.     ci =
  78.   let default_or default = Option.get_or ~default in
  79.   let n = Mat.dim1 ci in
  80.   let lower, upper =
  81.     default_or (Vec.make0 n) lower, default_or (Vec.make0 n) upper in
  82.   let () =
  83.     let test vec = if not (Vec.dim vec = n)
  84.       then raise (Invalid_argument "need full starting vector") in
  85.     test lower; test upper; () in
  86.   let infin = default_or
  87.       (let a = Lacaml.Common.create_int32_vec n in
  88.        Array1.fill a 1l; a)                (* default from lower to infinity *)
  89.       infin in
  90.   let maxpts = default_or (100*n) maxpts in
  91.   (*Printf.printf "maxpts %d%!" maxpts;*)
  92.   let releps = default_or (1e-2) releps in
  93.   let abseps = default_or (1e-2) abseps in
  94.   let correl, vars = corr_vars ci in
  95.   let jac_log_det = 0.5 *. (vars |> Vec.log |> Vec.sum) in
  96.   (* pointers *)
  97.   let ip k = allocate integer (Int32.of_int k) in
  98.   let fp f = allocate double f in
  99.   let ap v = bigarray_start array1 (v2c v) in
  100.   let _N = ip n in
  101.   let _LOWER, _UPPER, _INFIN = ap lower, ap upper, ap infin in
  102.   let _CORREL = ap correl in
  103.   let _MAXPTS, _ABSEPS, _RELEPS = ip maxpts, fp abseps, fp releps in
  104.   let _ERROR,  _VALUE, _INFORM = fp 0., fp 0., ip 0 in
  105.   (*Landmark.enter integration;*)
  106.   let integral = integrate                                         (* do it! *)
  107.       _N _LOWER _UPPER _INFIN _CORREL _MAXPTS _ABSEPS _RELEPS
  108.       _ERROR _VALUE _INFORM;
  109.     if (!@_INFORM <> 0l)
  110.     then raise (Integration_error
  111.                   (Printf.sprintf "integration problem %d, error estimate %f"
  112.                      (Int32.to_int !@_INFORM) !@_ERROR));
  113.     !@_VALUE in
  114.   (*Landmark.exit integration;*)
  115.   jac_log_det +. log integral
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement