transparently open compressed files ocaml (now with bz2 support)

Date Tags ocaml

A long time ago I wrote about how to handle compressed files in ocaml using extlib : http://mancoosi.org/~abate/transparently-open-compressed-files-ocaml

Today I got back to it and added bz2 support. The code is trivial. The only small problem to notice is that since the bz2 interface does not support a char input function, I’ve to simulate it using Bz2.read. A bit of a hack. I want to look at the bz2 bindings to fix this small shortfall. This is the code :

open ExtLib

let gzip_open_file file =
  let ch = Gzip.open_in file in
  let input_char ch = try Gzip.input_char ch with End_of_file -> raise IO.No_more_input in
  let read ch = try Gzip.input ch with End_of_file -> raise IO.No_more_input in
  IO.create_in
  ~read:(fun () -> input_char ch)
  ~input:(read ch)
  ~close:(fun () -> Gzip.close_in ch)
;;

let bzip_open_file file =
  let ch = Bz2.open_in (open_in file) in
  let input_char ch =
   (** XXX ugly ! *)
    try let s = " " in ignore (Bz2.read ch s 0 1) ; s.[0]
    with End_of_file -> raise IO.No_more_input
  in
  let read ch s pos len =
    try Bz2.read ch s pos len
    with End_of_file -> raise IO.No_more_input
  in
  IO.create_in
  ~read:(fun () -> input_char ch)
  ~input:(read ch)
  ~close:(fun () -> Bz2.close_in ch)
;;

let std_open_file file = IO.input_channel (open_in file)
let open_ch ch = IO.input_channel ch
let close_ch ch = IO.close_in ch

let open_file file =
  if Filename.check_suffix file ".gz" || Filename.check_suffix file ".cz" then
    gzip_open_file file
  else
  if Filename.check_suffix file ".bz2" then
    bzip_open_file file
  else
    std_open_file file
;;

let main () =
  let ch = open_file (Sys.argv.(1)) in
  try while true do print_string (IO.nread ch 10240) done
  with IO.No_more_input -> ()
;;

main ();;

github and debian

Note to Self

If you use github.com to host your projects these are two things to remember: * if you want a download url that is different from http://github.com/$user/$proj/tarball/master you can create a tag in your repo, push it to github and enjoy and new link in the download tab. Then you can download your project as http://github.com/$user/$proj/tarball/0.1 where 0.1 is the tag. Just for future ref : http://github.com/guides/push-tags-to-github

  • If you want to create a debian package from a github project you should use the excellent service provided by Gunnar Wolf. For example, this is the redirect for my project ocaml-buddy : http://githubredir.debian.net/githubredir.cgi?author=abate&project=ocaml-buddy .Then your watch file will look like:
version=3
http://githubredir.debian.net/github/abate/ocaml-buddy (.*).tar.gz

Many other things to remember, I’m sure, but I forgot them all :)


ocaml bindings for Buddy BDD

Date Tags bdd / ocaml

I’ve taken some time off to finish the ocaml bindings to Buddy BDD.

This code is a fork of the bindings downloaded from http://nicosia.is.s.u-tokyo.ac.jp/members/hagiya/xml/readme.htm#buddy .The original authors are Akihiko Tozawa and Masami Hagiya and they granted me - via personal communication - the right to release the software as open source.

I’ve added documentation to the .mli (mostly from the buddy website), few functions that were missed in the original work, the build system and an example.

I’ve released the code under GPLv3 . The code is available on github. This snapshot compiles cleanly on debian unstable with the package libbdd-dev installed. There is a micro example in the source. I plan to use the bindings with some real world data in the next few weeks. Debian package is work in progress.

Enjoy. As always feedback is welcome.


quotes of the day

Date Tags quotes

The First Rule of Program Optimization: Don’t do it.

The Second Rule of Program Optimization (for experts only!): Don’t do it yet.

— Michael Jackson


ocaml bindings for picosat

The code is on github . Get in touch if you find this useful.

ocaml bingings for picosat

The package provides an example, solver.ml, that reads from standard input a formula and print its satisfiability and a satisfying assignment (if any). A formula is a sequence of lines that either define a variable (‘v’ ), define a clause (‘c’ followed by a sequence of names, with a leading ‘-‘ if they are negated in the clause) and comments (starting with ‘#’). A couple of example formulas are available in the ‘examples/’ directory.

for documentation refer to picosat.h and picosat.mli

Install and use

To compile ocaml-picosat you need the picosat solver (compiled as a dynamic library) installed on the system.

The library assumes : /usr/include/picosat/picosat.h and /usr/lib/libpicosat.so.1.0.0

Picosat is a stateless module. I’ve also add an higher level api to add clauses and to generate a model and an unset core. It mimics a bit the same concept of the minisat bindings, but without the OO interface. We can set the number of variables, the trace (on by default and the picosat library must be compiled with -DTRACE) and the initial seed.

type var = int
type lit
type value = True | False | Unknown
type solution = SAT | UNSAT | UNKNOWN

val init : ?seed : int -> ?nvars : int -> ?trace : bool -> unit -> unit
external reset: unit -> unit = "caml_picosat_reset"

external model: unit -> var list = "caml_model"
external unsatcore : unit -> var list = "caml_unsatcore"

val add_clause : lit list -> unit

val solve : ?limit : int -> unit -> solution 
val solve_with_assumptions : ?limit : int  -> lit list -> solution 

val new_var : unit -> var
val value_of : var -> value

val pos_lit : var -> lit
val neg_lit : var -> lit

val string_of_value : value -> string

This is a snippet from the test file :

let solve file =
  Picosat.init ();
  let vars = process_file file in
  let revs =
    let acc = Hashtbl.create (Hashtbl.length vars) in
    Hashtbl.iter (fun name v -> Hashtbl.add acc v name) vars ;
    acc
  in
  match Picosat.solve () with
  | Picosat.UNKNOWN -> printf "Limit exausted\n"
  | Picosat.UNSAT ->
      begin
        printf "unsat\nunsat core : %s\n"
        (String.concat "," (List.map (fun i -> (Hashtbl.find revs i)) (Picosat.unsatcore ())))
      end
  | Picosat.SAT   ->
      begin
        printf "sat\nmodel : \n";
        List.iter (fun i ->
          printf "  %s=%s\n"
          (Hashtbl.find revs i)
          (Picosat.string_of_value (Picosat.value_of i))
        ) (Picosat.model ())
      end