[Toss-devel-svn] SF.net SVN: toss:[1424] trunk/Toss
Status: Beta
Brought to you by:
lukaszkaiser
|
From: <luk...@us...> - 2011-04-28 22:09:13
|
Revision: 1424
http://toss.svn.sourceforge.net/toss/?rev=1424&view=rev
Author: lukaszkaiser
Date: 2011-04-28 22:09:04 +0000 (Thu, 28 Apr 2011)
Log Message:
-----------
Create structures from pictures, add SO variable variant, monadic and full least and greatest fixed-point variants, move (part of) ClassTest to OUnit.
Modified Paths:
--------------
trunk/Toss/Formula/BoolFunctionTest.ml
trunk/Toss/Formula/FFTNF.ml
trunk/Toss/Formula/Formula.ml
trunk/Toss/Formula/Formula.mli
trunk/Toss/Formula/FormulaTest.ml
trunk/Toss/Server/Makefile
trunk/Toss/Solver/Class.ml
trunk/Toss/Solver/ClassTest.ml
trunk/Toss/Solver/PresbTest.ml
trunk/Toss/TossTest.ml
Added Paths:
-----------
trunk/Toss/Server/Picture.ml
trunk/Toss/Server/Picture.mli
trunk/Toss/Server/PictureTest.ml
trunk/Toss/www/img/Breakthrough.ppm
Modified: trunk/Toss/Formula/BoolFunctionTest.ml
===================================================================
--- trunk/Toss/Formula/BoolFunctionTest.ml 2011-04-27 17:44:35 UTC (rev 1423)
+++ trunk/Toss/Formula/BoolFunctionTest.ml 2011-04-28 22:09:04 UTC (rev 1424)
@@ -14,7 +14,7 @@
let assert_eq_string arg msg x_in y_in =
let full_msg = msg ^ " (argument: " ^ arg ^ ")" in
- let ws = Str.regexp "[ ,\n,\t]+" in
+ let ws = Str.regexp "[ \n\t]+" in
let x = Str.global_replace ws " " (" " ^ x_in ^ " ") in
let y = Str.global_replace ws " " (" " ^ y_in ^ " ") in
assert_equal ~printer:(fun x -> x) ~msg:full_msg
Modified: trunk/Toss/Formula/FFTNF.ml
===================================================================
--- trunk/Toss/Formula/FFTNF.ml 2011-04-27 17:44:35 UTC (rev 1423)
+++ trunk/Toss/Formula/FFTNF.ml 2011-04-28 22:09:04 UTC (rev 1424)
@@ -172,6 +172,7 @@
List.map2 (fun v -> function
| `FO _ -> `FO v
| `MSO _ -> `MSO v
+ | `SO _ -> `SO v
| `Real _ -> `Real v) vs xs in
let update_sb vs vars sb =
Modified: trunk/Toss/Formula/Formula.ml
===================================================================
--- trunk/Toss/Formula/Formula.ml 2011-04-27 17:44:35 UTC (rev 1423)
+++ trunk/Toss/Formula/Formula.ml 2011-04-28 22:09:04 UTC (rev 1424)
@@ -1,16 +1,17 @@
(* Represent formulas with first-order, mso, and real variables - basic defs.*)
let debug_level = ref 0
-let set_debug_level i = Sat.set_debug_level (i-1); (debug_level := i)
+let set_debug_level i = ( Sat.set_debug_level (i-1); debug_level := i; )
(* ----------------------- BASIC TYPE DEFINITIONS -------------------------- *)
(* Our variables can be first-order, monadic second-order or reals. *)
-type var = [ `FO of string | `MSO of string | `Real of string ] ;;
-type fo_var = [ `FO of string ];;
-type mso_var = [ `MSO of string ];;
-type real_var = [ `Real of string ];;
+type var = [ `FO of string | `MSO of string | `SO of string | `Real of string ]
+type fo_var = [ `FO of string ]
+type mso_var = [ `MSO of string ]
+type so_var = [ `SO of string ]
+type real_var = [ `Real of string ]
(* We recognize if the variable is FO (x, y) or MSO (X, Y) or Real (r1, r2). *)
let var_of_string s : var =
@@ -18,27 +19,34 @@
failwith "empty strings not allowed as vars"
else if s.[0] = ':' then
`Real s
+ else if s.[0] = '|' then
+ `SO s
else if ((Char.uppercase s.[0]) = s.[0]) && (not (Aux.is_digit s.[0])) then
`MSO s
else `FO s
let fo_var_of_string s : fo_var =
match var_of_string s with
- `FO s -> `FO s
+ | `FO s -> `FO s
| _ -> failwith ("non first-order variable: " ^ s)
let mso_var_of_string s : mso_var =
match var_of_string s with
- `MSO s -> `MSO s
+ | `MSO s -> `MSO s
| _ -> failwith ("non MSO variable: " ^ s)
+let so_var_of_string s : so_var =
+ match var_of_string s with
+ | `SO s -> `SO s
+ | _ -> failwith ("non SO variable: " ^ s)
+
let real_var_of_string s : real_var =
match var_of_string s with
- `Real s -> `Real s
+ | `Real s -> `Real s
| _ -> failwith ("non real variable: " ^ s)
(* Print a variable as a string. *)
-let var_str = function `FO s -> s | `MSO s -> s | `Real s -> s
+let var_str = function `FO s -> s | `MSO s -> s | `SO s -> s | `Real s -> s
let print_var v = Format.print_string (var_str v)
(* Print a variable list/array as a string. *)
@@ -58,23 +66,24 @@
(* Check variable type. *)
let is_fo (v : var) = match v with `FO _ -> true | _ -> false
let is_mso (v : var) = match v with `MSO _ -> true | _ -> false
+let is_so (v : var) = match v with `SO _ -> true | _ -> false
let is_real (v : var) = match v with `Real _ -> true | _ -> false
(* Casts to particular variable types. *)
let to_fo (v : var) : fo_var = fo_var_of_string (var_str v)
let to_mso (v : var) : mso_var = mso_var_of_string (var_str v)
+let to_so (v : var) : so_var = so_var_of_string (var_str v)
let to_real (v : var) : real_var = real_var_of_string (var_str v)
(* Cast that is safe provided that tuples are not modified in-place. *)
-let var_tup (vs : [< var ] array) =
- (Obj.magic vs : var array)
+let var_tup (vs : [< var ] array) = (Obj.magic vs : var array)
(* Sign operands. *)
type sign_op = EQZero | GZero | LZero | GEQZero | LEQZero | NEQZero
(* Print a sign_op as string. *)
let sign_op_str = function
- EQZero -> " = 0"
+ | EQZero -> " = 0"
| GZero -> " > 0"
| LZero -> " < 0"
| GEQZero -> " >= 0"
@@ -85,7 +94,7 @@
(* This type describes formulas of relational logic with equality.
We allow only simple boolean junctors, other are resolved during parsing. *)
type formula =
- Rel of string * fo_var array
+ | Rel of string * fo_var array
| Eq of fo_var * fo_var
| In of fo_var * mso_var
| RealExpr of real_expr * sign_op
@@ -94,22 +103,26 @@
| Or of formula list
| Ex of var list * formula
| All of var list * formula
+ | MLfp of mso_var * fo_var * formula
+ | MGfp of mso_var * fo_var * formula
+ | Lfp of so_var * fo_var list * formula
+ | Gfp of so_var * fo_var list * formula
and real_expr =
- RVar of string
+ | RVar of string
| Const of float
| Times of real_expr * real_expr
| Plus of real_expr * real_expr
| Fun of string * fo_var
| Char of formula
| Sum of fo_var list * formula * real_expr
-;;
let is_atom = function
- Rel _ | Eq _ | In _ | RealExpr _ -> true
+ | Rel _ | Eq _ | In _ | RealExpr _ -> true
| _ -> false
+
(* Helper power function, used in parser. *)
let rec pow p n =
if n = 0 then Const 1. else if n = 1 then p else Times (p, pow p (n-1))
@@ -242,26 +255,28 @@
(* ------------------------ ORDER ON FORMULAS ------------------------------- *)
-(* Compare two variables. We assume that FO < MSO < Real. *)
+(* Compare two variables. We assume that FO < MSO < SO < Real. *)
let compare_vars x y =
- if x == y then 0 else
- match (x, y) with
- (`FO x, `FO y) -> String.compare x y
- | (`FO _, _) -> 1
- | (_, `FO _) -> -1
- | (`MSO x, `MSO y) -> String.compare x y
- | (`MSO _, _) -> 1
- | (_, `MSO _) -> -1
- | (`Real x, `Real y) -> String.compare x y
+ if x == y then 0 else match (x, y) with
+ | (`FO x, `FO y) -> String.compare x y
+ | (`FO _, _) -> 1
+ | (_, `FO _) -> -1
+ | (`MSO x, `MSO y) -> String.compare x y
+ | (`MSO _, _) -> 1
+ | (_, `MSO _) -> -1
+ | (`SO x, `SO y) -> String.compare x y
+ | (`SO _, _) -> 1
+ | (_, `SO _) -> -1
+ | (`Real x, `Real y) -> String.compare x y
(* Helper function: compare lists/arrays lexicographically by [cmp]. *)
let rec compare_lists_lex cmp = function
- ([], []) -> 0
+ | ([], []) -> 0
| ([], _) -> -1
| (_, []) -> 1
| (x :: xs, y :: ys) ->
- let c = cmp x y in
- if c <> 0 then c else compare_lists_lex cmp (xs, ys)
+ let c = cmp x y in
+ if c <> 0 then c else compare_lists_lex cmp (xs, ys)
let compare_arrays_lex cmp a b =
let res = ref (Array.length a - Array.length b) in
@@ -285,19 +300,18 @@
| Rel _ | Eq _ | In _ | RealExpr _ -> acc + 1
| Not phi | Ex (_, phi) | All (_, phi) -> size ~acc:(acc + 1) phi
| And flist | Or flist ->
- List.fold_left (fun i f -> size ~acc:i f) (acc + 1) flist
+ List.fold_left (fun i f -> size ~acc:i f) (acc + 1) flist
let rec rec_compare phi1 phi2 =
let cmp_lists = compare_lists_lex rec_compare in
match (phi1, phi2) with
- (Rel (r1, vs1), Rel (r2, vs2)) ->
- let c = compare_var_tups vs1
- vs2 in
- if c <> 0 then c else String.compare r1 r2
+ | (Rel (r1, vs1), Rel (r2, vs2)) ->
+ let c = compare_var_tups vs1 vs2 in
+ if c <> 0 then c else String.compare r1 r2
| (Rel (r, vs), Eq (x, y)) ->
- let c = compare_var_tups vs [|x; y|] in if c = 0 then -1 else c
+ let c = compare_var_tups vs [|x; y|] in if c = 0 then -1 else c
| (Eq (x, y), Rel (r, vs)) ->
- let c = compare_var_tups [|x; y|] vs in if c = 0 then 1 else c
+ let c = compare_var_tups [|x; y|] vs in if c = 0 then 1 else c
| (Eq (x1, y1), Eq (x2, y2)) -> compare_var_tups [|x1; y1|] [|x2; y2|]
| (Rel _, _) | (Eq _, _) -> -1
| (_, Rel _) | (_, Eq _) -> 1
@@ -307,8 +321,8 @@
| (In _, _) -> -1
| (_, In _) -> 1
| (RealExpr (re1, s1), RealExpr (re2, s2)) ->
- let c = rec_compare_re re1 re2 in
- if c <> 0 then c else Pervasives.compare s1 s2
+ let c = rec_compare_re re1 re2 in
+ if c <> 0 then c else Pervasives.compare s1 s2
| (RealExpr _, _) -> -1
| (_, RealExpr _) -> 1
| (Not psi1, Not psi2) -> rec_compare psi1 psi2
@@ -320,21 +334,21 @@
| (Or _, _) -> -1
| (_, Or _) -> 1
| (All (vs1, psi1), All (vs2, psi2)) | (Ex (vs1, psi1), Ex (vs2, psi2)) ->
- let c = compare_var_lists vs1 vs2 in
- if c <> 0 then c else rec_compare psi1 psi2
+ let c = compare_var_lists vs1 vs2 in
+ if c <> 0 then c else rec_compare psi1 psi2
| (All _, _) -> -1
| (_, All _) -> 1
and rec_compare_re re1 re2 =
match (re1, re2) with
- (Char phi1, Char phi2) -> rec_compare phi1 phi2
+ | (Char phi1, Char phi2) -> rec_compare phi1 phi2
| (Const x, Const y) -> Pervasives.compare x y
| _ -> Pervasives.compare re1 re2 (* TODO: improve this *)
let compare phi1 phi2 =
if phi1 == phi2 then 0 else
let (s1, s2) = (size phi1, size phi2) in
- if s1 <> s2 then s1 - s2 else rec_compare phi1 phi2
+ if s1 <> s2 then s1 - s2 else rec_compare phi1 phi2
(* --------------- BASIC HELPER FUNCTIONS USED IN PARSER ------------------- *)
Modified: trunk/Toss/Formula/Formula.mli
===================================================================
--- trunk/Toss/Formula/Formula.mli 2011-04-27 17:44:35 UTC (rev 1423)
+++ trunk/Toss/Formula/Formula.mli 2011-04-28 22:09:04 UTC (rev 1424)
@@ -3,35 +3,38 @@
(** {2 Basic Type Definitions.} *)
(** Our variables can be first-order, monadic second-order or reals. *)
-type var = [ `FO of string | `MSO of string | `Real of string ] ;;
-type fo_var = [ `FO of string ];;
-type mso_var = [ `MSO of string ];;
-type real_var = [ `Real of string ];;
+type var = [ `FO of string | `MSO of string | `SO of string | `Real of string ]
+type fo_var = [ `FO of string ]
+type mso_var = [ `MSO of string ]
+type so_var = [ `SO of string ]
+type real_var = [ `Real of string ]
-(** We recognize if the variable is FO (x, y) or MSO (X, Y) or Real (r1, r2). *)
+(** We recognize if the variable is FO (x), MSO (X), SO (|x) or Real (:x). *)
val var_of_string : string -> var
val fo_var_of_string : string -> fo_var
val mso_var_of_string : string -> mso_var
+val so_var_of_string : string -> so_var
val real_var_of_string : string -> real_var
(** Check variable type. *)
val is_fo : var -> bool
val is_mso : var -> bool
+val is_so : var -> bool
val is_real : var -> bool
(** Casts to particular variable types. *)
val to_fo : var -> fo_var
val to_mso : var -> mso_var
+val to_so : var -> so_var
val to_real : var -> real_var
val var_tup : [< var] array -> var array
-(** Compare two variables. We assume FO < MSO < Real. *)
+(** Compare two variables. We assume FO < MSO < SO < Real. *)
val compare_vars : ([< var ] as 'a) -> 'a -> int
val compare_var_lists : ([< var ] as 'a) list -> 'a list -> int
-val compare_var_tups :
- ([< var ] as 'a) array -> 'a array -> int
+val compare_var_tups : ([< var ] as 'a) array -> 'a array -> int
(** Sign operands. *)
type sign_op = EQZero | GZero | LZero | GEQZero | LEQZero | NEQZero
@@ -43,7 +46,7 @@
(** This type describes formulas of relational logic with equality.
We allow only simple boolean junctors, other are resolved during parsing. *)
type formula =
- Rel of string * fo_var array
+ | Rel of string * fo_var array
| Eq of fo_var * fo_var
| In of fo_var * mso_var
| RealExpr of real_expr * sign_op
@@ -52,10 +55,14 @@
| Or of formula list
| Ex of var list * formula
| All of var list * formula
+ | MLfp of mso_var * fo_var * formula
+ | MGfp of mso_var * fo_var * formula
+ | Lfp of so_var * fo_var list * formula
+ | Gfp of so_var * fo_var list * formula
-(** Real-valued terms allow counting, characteristic functions and arithmetic. *)
+(** Real-valued terms allow counting, characteristic functions, arithmetic. *)
and real_expr =
- RVar of string
+ | RVar of string
| Const of float
| Times of real_expr * real_expr
| Plus of real_expr * real_expr
@@ -75,11 +82,10 @@
(** {2 Printing Functions} *)
(** Print a variable as a string. *)
-val var_str : [< `FO of string | `MSO of string | `Real of string ] -> string
+val var_str : [< var] -> string
(** Print a variable list as a string. *)
-val var_list_str: [< `FO of string | `MSO of string | `Real of string ] list ->
- string
+val var_list_str: [< var] list -> string
(** Print a formula as a string. *)
val str : formula -> string
Modified: trunk/Toss/Formula/FormulaTest.ml
===================================================================
--- trunk/Toss/Formula/FormulaTest.ml 2011-04-27 17:44:35 UTC (rev 1423)
+++ trunk/Toss/Formula/FormulaTest.ml 2011-04-28 22:09:04 UTC (rev 1424)
@@ -1,7 +1,7 @@
open OUnit
-FormulaOps.set_debug_level 0 ;;
-BoolFormula.set_debug_level 0 ;;
+FormulaOps.set_debug_level 0;
+BoolFormula.set_debug_level 0
let tests = "Formula" >::: [
"basic flatten" >::
@@ -16,8 +16,7 @@
Formula.And [Formula.And [r "P"; r "Q"]; Formula.And [r "S"]]))
(Formula.And [r "P"; r "Q"; r "S"]);
);
-] ;;
+]
-let a =
- Aux.run_test_if_target "FormulaTest" tests
-;;
+
+let exec = Aux.run_test_if_target "FormulaTest" tests
Modified: trunk/Toss/Server/Makefile
===================================================================
--- trunk/Toss/Server/Makefile 2011-04-27 17:44:35 UTC (rev 1423)
+++ trunk/Toss/Server/Makefile 2011-04-28 22:09:04 UTC (rev 1424)
@@ -9,10 +9,12 @@
%TestDebug:
make -C .. Server/$@
+PictureTest:
+PictureTestProfile:
+PictureTestDebug:
+
ServerTest:
-
ServerTestProfile:
-
ServerTestDebug:
tests:
Added: trunk/Toss/Server/Picture.ml
===================================================================
--- trunk/Toss/Server/Picture.ml (rev 0)
+++ trunk/Toss/Server/Picture.ml 2011-04-28 22:09:04 UTC (rev 1424)
@@ -0,0 +1,235 @@
+(* Processing Pictures to create Structures *)
+
+let debug_level = ref 0
+let set_debug_level i = (debug_level := i;)
+
+
+(* --------- Basic Picture Functions --------- *)
+
+type picture = (int * int * int) array array
+
+(* Read a picture from a scanning buffer. *)
+let read_pic buf =
+ let (width, height) = Scanf.bscanf buf "P3 %d %d 255" (fun x y -> (x, y)) in
+ let pic = Array.make_matrix width height (0, 0, 0) in
+ for j = 0 to height-1 do
+ for i = 0 to width-1 do
+ pic.(i).(j) <- Scanf.bscanf buf " %d %d %d" (fun x y z -> (x, y, z))
+ done
+ done;
+ pic
+
+(* Print a matrix to the formatter [f], use [elem_f] for elements. *)
+let fprint_matrix f elem_f start mid m =
+ let (width, height) = (Array.length m, Array.length (m.(0))) in
+ Format.fprintf f "%s %d %d %s\n%!" start width height mid;
+ for j = 0 to height-1 do
+ for i = 0 to width-1 do
+ Format.fprintf f "%a" elem_f m.(i).(j);
+ done;
+ Format.fprintf f "\n%!";
+ done
+
+(* Print a picture in the simple PPM format to a formatter. *)
+let fprint_pic f pic =
+ let pr fmt (a, b, c) = Format.fprintf fmt " %d %d %d\n" a b c in
+ fprint_matrix f pr "P3" "255" pic
+
+(* Print a picture in the simple PPM format to standard output. *)
+let print_pic pic = fprint_pic Format.std_formatter pic
+
+
+(* Flip a picture. *)
+let flip pic =
+ let (width, height) = (Array.length pic, Array.length (pic.(0))) in
+ let flpic = Array.make_matrix height width (0, 0, 0) in
+ for i = 0 to width-1 do
+ for j = 0 to height-1 do
+ flpic.(j).(i) <- pic.(i).(j)
+ done
+ done;
+ flpic
+
+
+(* Cut a picture to the given rectangle. *)
+let cut (x1, y1) (x2, y2) pic =
+ let (orig_w, orig_h) = (Array.length pic, Array.length (pic.(0))) in
+ let x2 = if x2 <= 0 then orig_w + x2 - 1 else x2 in
+ let y2 = if y2 <= 0 then orig_h + y2 - 1 else y2 in
+ if x2 < x1+1 || y2 < y1+1 || orig_w<x2+1 || orig_h<y2+1 || x1<0 || y1<0 then
+ failwith (Printf.sprintf "cut: wrong dimensions %i %i %i %i" x1 x2 y1 y2);
+ let cutpic = Array.make_matrix (x2-x1+1) (y2-y1+1) (0, 0, 0) in
+ for i = 0 to x2-x1 do
+ for j = 0 to y2-y1 do
+ cutpic.(i).(j) <- pic.(i+x1).(j+y1)
+ done
+ done;
+ cutpic
+
+
+(* Apply the filter function [f] to each pixel in a picture. *)
+let apply_filter f pic =
+ let (width, height) = (Array.length pic, Array.length (pic.(0))) in
+ let fpic = Array.make_matrix width height (0, 0, 0) in
+ for i = 0 to width-1 do
+ for j = 0 to height-1 do
+ fpic.(i).(j) <- f i j width height pic
+ done
+ done;
+ fpic
+
+
+(* ------------ Change Detection ------------ *)
+
+let diff_filter maxdiff (distx, disty) x y w h pic =
+ let res = ref false in
+ for i = -distx to distx do
+ for j = -disty to disty do
+ if x+i >= 0 && x+i < w && y+j >= 0 && y+j < h then
+ let (r1, g1, b1) = pic.(x).(y) in
+ let (r2, g2, b2) = pic.(x+i).(y+j) in
+ let (rd, gd, bd) = maxdiff in
+ if rd >= abs (r1-r2) && gd >= abs (g1-g2) && bd >= abs (b1-b2) then
+ res := false
+ else res := true
+ done
+ done;
+ if !res then (255, 255, 255) else (0, 0, 0)
+
+(* Calculate color difference, accept maxdiff differences up to dist. *)
+let diff ?(maxdiff=(1,1,1)) ?(dist=(1,1)) =
+ apply_filter (diff_filter maxdiff dist)
+
+
+(* ------------ Simple Segmentation ------------ *)
+
+let all_in_color cl ((x1, y1), (x2, y2)) pic =
+ let (w, h) = (Array.length pic, Array.length (pic.(0))) in
+ if x2 < x1 || y2 < y1 || w < x2+1 || h < y2+1 || x1 < 0 || y1 < 0 then
+ failwith (Printf.sprintf "all_in_color: wrong dim %i %i %i %i" x1 y1 x2 y2);
+ let res = ref true in
+ for i = x1 to x2 do
+ for j = y1 to y2 do
+ if pic.(i).(j) <> cl then res := false
+ done
+ done;
+ !res
+
+let rec next_x cl i j w h pic =
+ if pic.(i).(j) = cl then (i, j) else
+ if i+1 < w then next_x cl (i+1) j w h pic else raise Not_found
+
+let rec next_y cl i j w h pic =
+ if pic.(i).(j) = cl then (i, j) else
+ if j+1 < h then next_y cl i (j+1) w h pic else raise Not_found
+
+let next_color cl i j w h pic =
+ try
+ let (i1, _) = next_x cl i j w h pic in
+ if i1+1 < w && pic.(i1+1).(j) = cl then (i1, j) else raise Not_found
+ with Not_found ->
+ let (_, j1) = next_y cl 0 (j+1) w h pic in
+ if j1+1 < h && pic.(i).(j1+1) = cl then (0, j1) else raise Not_found
+
+(* Make a row-first column-next black-white tour of a picture. *)
+let bw_tour pic =
+ let (width, height) = (Array.length pic, Array.length (pic.(0))) in
+ let (i, j, newi, newj) = (ref 0, ref 0, ref 0, ref 0) in
+ let (rects, intv) = (ref [], ref []) in
+ try
+ while true do
+ intv := [];
+ while !j = !newj do
+ let (ni, nj) = next_color (0, 0, 0) !i !j width height pic in
+ newi := ni;
+ let (nni, nnj) = next_color (255, 255, 255) ni nj width height pic in
+ if nnj = !j then intv := (ni, nni-1) :: !intv;
+ i := nni; j := !newj; newj := nnj;
+ done;
+ if !intv != [] then intv := (!newi, width-1) :: !intv;
+ rects := (List.map (fun v-> v, (!j,!newj-1)) !intv) @ !rects;
+ j := !newj; i := 0
+ done;
+ failwith "bw_tour: unreachable"
+ with Not_found ->
+ if !intv != [] then intv := (!newi, width-1) :: !intv;
+ rects := (List.map (fun v-> v, (!j,height-1)) !intv) @ !rects;
+ List.rev_map (fun ((a, b), (c, d)) -> (a, c), (b, d)) !rects
+
+let rect_dist ((x1, y1), (x2, y2)) ((a1, b1), (a2, b2)) pic =
+ let (w, h, d) = (min (x2-x1) (a2-a1), min (y2-y1) (b2-b1), ref 0) in
+ for i = 0 to w-1 do
+ for j = 0 to h-1 do
+ let (x, y, z), (a, b, c) = pic.(x1+i).(y1+j), pic.(a1+i).(b1+j) in
+ d := !d + (abs (x-a)) + (abs (y-b)) + (abs (z-c))
+ done
+ done;
+ (float !d) /. (float (w*h))
+
+let rect_dist_offset (x, y) ((x1, y1), (x2, y2)) ((a1, b1), (a2, b2)) pic =
+ rect_dist ((x1+x, y1+y), (x2+x, y2+y)) ((a1+x, b1+y), (a2+x, b2+y)) pic
+
+(* Very basic picture segmentation, should work for grids. *)
+let segment offset threshold pic =
+ let df = diff (cut (offset, offset) (-offset, -offset) pic) in
+ let rects = bw_tour df in
+ let assign_name (dict, i, bi) rect =
+ let (a, b), (c, d) = rect in
+ try
+ let (r, n) =
+ List.find (fun (r,_) ->
+ rect_dist_offset (offset, offset) r rect pic < threshold) dict in
+ if !debug_level > 0 then
+ Printf.printf " (%i, %i) - (%i, %i) %s found \n%!" a b c d n;
+ ((rect, n) :: dict, i, bi)
+ with Not_found ->
+ if all_in_color (0, 0, 0) rect df then (
+ let n = Printf.sprintf "B%i" bi in
+ if !debug_level > 0 then
+ Printf.printf " (%i, %i) - (%i, %i) %s assigned \n%!" a b c d n;
+ ((rect, n) :: dict, i, bi+1)
+ ) else (
+ let n = Printf.sprintf "P%i" i in
+ if !debug_level > 0 then
+ Printf.printf " (%i, %i) - (%i, %i) %s assigned \n%!" a b c d n;
+ ((rect, n) :: dict, i+1, bi)
+ ) in
+ let (res, _, _) = List.fold_left assign_name ([], 1, 0) rects in
+ List.rev res
+
+
+(* ------------- Structure from Segmented Data ------------ *)
+
+(* Create a structure from segmented data. *)
+let make_struc dict =
+ let (prev_ys, prev_xs, maxdx, maxdy) =
+ (ref (0, 0), ref (0, 0), ref 0, ref 0) in
+ let add_el (struc, i, j) (((x1, y1), (x2, y2)), pred) =
+ let (ni, nj) =
+ if (y1, y2) = !prev_ys then (
+ maxdx := max !maxdx (abs ((fst !prev_xs) - x1));
+ prev_xs := (x1, x2);
+ (i+1, j)
+ ) else (
+ maxdy := max !maxdy (abs ((fst !prev_ys) - y1));
+ prev_xs := (x1, x2);
+ prev_ys := (y1, y2);
+ (1, j+1)
+ ) in
+ let name = try Structure.board_coords_name (ni, nj) with Not_found ->
+ Printf.sprintf "e%i,%i" ni nj in
+ let (s1, elem) = Structure.add_new_elem struc ~name () in
+ let s2 = Structure.add_fun s1 "x" (elem, float (x1+x2) /. 2.) in
+ let s3 = Structure.add_fun s2 "y" (elem, float (y1+y2) /. (-2.)) in
+ let s4 = Structure.add_fun s3 "x1" (elem, float x1) in
+ let s5 = Structure.add_fun s4 "y1" (elem, float y1) in
+ let s6 = Structure.add_fun s5 "x2" (elem, float x2) in
+ let s7 = Structure.add_fun s6 "y2" (elem, float y2) in
+ let s8 = Structure.add_fun s7 "vx" (elem, 0.) in
+ let new_s = Structure.add_fun s8 "vy" (elem, 0.) in
+ if pred = "B0" then (new_s, ni, nj) else
+ (Structure.add_rel new_s pred [|elem|], ni, nj) in
+ let (s, _, _) =
+ List.fold_left add_el (Structure.empty_structure (), 1, 0) dict in
+ (s, !maxdx, !maxdy)
+
Added: trunk/Toss/Server/Picture.mli
===================================================================
--- trunk/Toss/Server/Picture.mli (rev 0)
+++ trunk/Toss/Server/Picture.mli 2011-04-28 22:09:04 UTC (rev 1424)
@@ -0,0 +1,50 @@
+(** Processing Pictures to create Structures *)
+
+(** {2 Debugging} *)
+
+val set_debug_level : int -> unit
+
+
+(** {2 Basic Picture Functions} *)
+
+type picture = (int * int * int) array array
+
+
+(** Read a picture from a scanning buffer. *)
+val read_pic : Scanf.Scanning.scanbuf -> picture
+
+(** Print a picture in the simple PPM format to a formatter. *)
+val fprint_pic : Format.formatter -> picture -> unit
+
+(** Print a picture in the simple PPM format to standard output. *)
+val print_pic : picture -> unit
+
+(** Flip a picture. *)
+val flip : picture -> picture
+
+(** Cut a picture to the given rectangle. *)
+val cut : int * int -> int * int -> picture -> picture
+
+(** Apply the filter function [f] to each pixel in a picture. *)
+val apply_filter : (int -> int -> int -> int -> picture -> int * int * int) ->
+ picture -> picture
+
+
+(** {2 Change Detection} *)
+
+(** Calculate color difference, accept maxdiff differences up to dist. *)
+val diff : ?maxdiff: int * int * int -> ?dist: int * int -> picture -> picture
+
+
+(** {2 Simple Segmentation} *)
+
+(** Very basic picture segmentation, should work for grids. *)
+val segment : int -> float -> picture ->
+ (((int * int) * (int * int)) * string) list
+
+
+(** {2 Structure from Segmented Data} *)
+
+(** Create a structure from segmented data. *)
+val make_struc : (((int * int) * (int * int)) * string) list ->
+ Structure.structure * int * int
Added: trunk/Toss/Server/PictureTest.ml
===================================================================
--- trunk/Toss/Server/PictureTest.ml (rev 0)
+++ trunk/Toss/Server/PictureTest.ml 2011-04-28 22:09:04 UTC (rev 1424)
@@ -0,0 +1,50 @@
+open OUnit
+
+Picture.set_debug_level 0
+
+let tests = "Picture" >::: [
+ "segmentation size for breakthrough" >::
+ (fun () ->
+ let fname = "./www/img/Breakthrough.ppm" in
+ let pic = Picture.read_pic (Scanf.Scanning.from_file fname) in
+ let seg = Picture.segment 2 40. pic in
+ assert_equal ~printer:string_of_int 64 (List.length seg)
+ );
+
+ "breakthrough structure P1 size" >::
+ (fun () ->
+ let fname = "./www/img/Breakthrough.ppm" in
+ let pic = Picture.read_pic (Scanf.Scanning.from_file fname) in
+ let seg = Picture.segment 2 40. pic in
+ let (struc, _, _) = Picture.make_struc seg in
+ assert_equal ~printer:string_of_int 16 (Structure.rel_size struc "P1")
+ );
+]
+
+
+let main () =
+ Gc.set { (Gc.get()) with
+ Gc.space_overhead = 300; (* 300% instead of 80% std *)
+ Gc.minor_heap_size = 160*1024; (* 4*std, opt ~= L2 cache/proc *)
+ Gc.major_heap_increment = 8*124*1024 (* 8*std ok *) };
+ let (file) = (ref "") in
+ let dbg_level i = (Picture.set_debug_level i) in
+ let opts = [
+ ("-v", Arg.Unit (fun () -> dbg_level 1), "be verbose");
+ ("-d", Arg.Int (fun i -> dbg_level i), "set debug level");
+ ("-f", Arg.String (fun s -> file := s), "process file");
+ ] in
+ Arg.parse opts (fun _ -> ()) "Try -help for help or one of the following.";
+ if !file = "" then ignore (OUnit.run_test_tt tests) else (
+ let pic = Picture.read_pic (Scanf.Scanning.from_file !file) in
+ let (struc, dx, dy) = Picture.make_struc (Picture.segment 2 40. pic) in
+ let formula_r = Printf.sprintf
+ ":y(a) = :y(b) and :x(a) < :x(b) and :x(b) < :x(a) + %i.8" dx in
+ let formula_c = Printf.sprintf
+ ":x(a) = :x(b) and :y(b) < :y(a) and :y(a) < :y(b) + %i.8" dy in
+ Printf.printf "MODEL \n %s \n with \n R(a, b) = %s;\n C(a, b) = %s\n\n%!"
+ (Structure.sprint struc) formula_r formula_c;
+ )
+
+
+let _ = Aux.run_if_target "PictureTest" main
Modified: trunk/Toss/Solver/Class.ml
===================================================================
--- trunk/Toss/Solver/Class.ml 2011-04-27 17:44:35 UTC (rev 1423)
+++ trunk/Toss/Solver/Class.ml 2011-04-28 22:09:04 UTC (rev 1424)
@@ -37,19 +37,19 @@
let struct_sum_str = function
Struct s -> Structure.str s
| Sum (comps, rdefs) ->
- let comps_s =
- String.concat " + " (List.map (fun (s, t) -> s ^ ": " ^ t) comps) in
- let defstr (rel, (vars, def)) =
- Formula.str (Rel (rel, Array.of_list vars)) ^
- " <- " ^ (Formula.str def)
- in
- if rdefs = [] then comps_s else
- comps_s ^ " with\n " ^
- (String.concat ";\n " (List.map defstr rdefs))
+ let pstr (s, t) = if s = "_" then t else s ^ ": " ^ t in
+ let comps_s = String.concat " + " (List.map pstr comps) in
+ let defstr (rel, (vars, def)) =
+ Formula.str (Rel (rel, Array.of_list vars)) ^
+ " <- " ^ (Formula.sprint def)
+ in
+ if rdefs = [] then comps_s else
+ comps_s ^ " with\n " ^
+ (String.concat ";\n " (List.map defstr rdefs)) ^ ";"
(* Print an inductive structure class as a string, using its definition. *)
let str cdefs =
- let cdef_s (id, alternatives) = "class " ^ id ^ " =\n " ^
+ let cdef_s (id, alternatives) = (* "class " ^ *) id ^ " =\n " ^
(String.concat "\n | " (List.map struct_sum_str alternatives))
in
String.concat "\nand " (List.map cdef_s cdefs)
@@ -69,36 +69,36 @@
| Sum (ids_l, rels_l) ->
let prefixes s = List.map (fun (i, _) -> s ^ ":" ^ i) ids_l in
let replace_in s = function
- In (fo_v, `MSO w) when w = s ->
- Or (List.map (fun ps -> In (fo_v, `MSO ps)) (prefixes s))
+ | In (fo_v, `MSO w) when w = s ->
+ Or (List.map (fun ps -> In (fo_v, `MSO ps)) (prefixes s))
| x -> x in
let rec split_formula = function
- Ex ([], phi) | All ([], phi) -> split_formula phi
+ | Ex ([], phi) | All ([], phi) -> split_formula phi
| Ex ([v], phi) -> (
- match v with
- `Real _ -> failwith "splitting reals not supported in ex"
- | `MSO s ->
- Ex (List.map (fun x -> `MSO x) (prefixes s),
- split_formula (map_to_atoms (replace_in s) phi))
- | `FO s ->
- let new_phi ps =
- Ex ([`FO ps], split_formula (subst_vars [(s, ps)] phi))
- in
- Or (List.map new_phi (prefixes s))
- )
+ match v with
+ | `Real _ -> failwith "splitting reals not supported (ex)"
+ | `SO _ -> failwith "splitting non-monadic SO not supported (ex)"
+ | `MSO s ->
+ Ex (List.map (fun x -> `MSO x) (prefixes s),
+ split_formula (map_to_atoms (replace_in s) phi))
+ | `FO s ->
+ let new_phi ps =
+ Ex ([`FO ps], split_formula (subst_vars [(s, ps)] phi)) in
+ Or (List.map new_phi (prefixes s))
+ )
| Ex (v::vs, phi) -> split_formula (Ex ([v], Ex (vs, phi)))
| All ([v], phi) -> (
- match v with
- `Real _ -> failwith "splitting reals not supported in forall"
- | `MSO s ->
- All (List.map (fun x -> `MSO x) (prefixes s),
- split_formula (map_to_atoms (replace_in s) phi))
- | `FO s ->
- let new_phi ps =
- All ([`FO ps], split_formula (subst_vars [(s, ps)] phi))
- in
- And (List.map new_phi (prefixes s))
- )
+ match v with
+ | `Real _ -> failwith "splitting reals not supported (all)"
+ | `SO _ -> failwith "splitting non-monadic SO not supported (all)"
+ | `MSO s ->
+ All (List.map (fun x -> `MSO x) (prefixes s),
+ split_formula (map_to_atoms (replace_in s) phi))
+ | `FO s ->
+ let new_phi ps =
+ All ([`FO ps], split_formula (subst_vars [(s, ps)] phi)) in
+ And (List.map new_phi (prefixes s))
+ )
| All (v::vs, phi) -> split_formula (All ([v], All (vs, phi)))
| Or (flist) -> Or (List.rev_map split_formula flist)
| And (flist) -> And (List.rev_map split_formula flist)
@@ -207,37 +207,44 @@
(* Compute a decomposition of a formula on a given class definition. *)
let decompose ?(get_ids=false) phi_in = function
- Struct s as cdef ->
- if !debug_level > 0 then print_endline ("Deciding " ^ (Formula.str phi_in) ^ " on struct");
- [[("", split phi_in cdef)]]
+ | Struct s as cdef ->
+ if !debug_level > 0 then
+ print_endline ("Deciding " ^ (Formula.str phi_in) ^ " on struct");
+ [[("", split phi_in cdef)]]
| Sum (ids_l, rels_r) as cdef ->
- let phi = class_tnf (simplify phi_in) in
- if !debug_level > 0 then
- print_endline ("Decomposing " ^ (Formula.str phi) ^ " on " ^ (struct_sum_str cdef));
- let phi_fv = free_vars phi in
- let split_phi = split (Ex (phi_fv, phi)) cdef in
- let (summand_ids, _) = List.split ids_l in
- let simp_split_phi = map_to_atoms (simplify_atom summand_ids) split_phi in
- match List.rev_map simplify (to_dnf (class_tnf (simplify (simp_split_phi)))) with
- [] -> [[("", Or [])]]
- | fl when List.mem (And []) fl -> [[("", And [])]]
- | fl ->
- let rec del_quant = (function
- Ex (vs, psi) ->
- let was_free v = List.mem v phi_fv in
- let ws= List.filter (fun x -> not (was_free x)) vs in
- if ws = [] then del_quant psi else Ex (ws, psi)
- | And flist -> And (List.map del_quant flist)
- | psi -> psi (* del_quant is applied to conjucts of DNF*) ) in
- let del_quants = List.rev_map (fun (s, f) -> (s, del_quant f)) in
- let process f = rename_extract_conjunction get_ids ids_l f in
- let decomp_lit_str (cid, phi) = "\nsome " ^ cid ^ " |= " ^ (Formula.str phi) in
- let decomp_tuple_str cj =
- "(" ^ String.concat " and " (List.map decomp_lit_str cj) ^ ")" in
- let decomp_str df = String.concat " or " (List.map decomp_tuple_str df) in
- let res = List.rev_map (fun f -> del_quants (process f)) fl in
- if (!debug_level > 1) then print_endline ("DECOMP: " ^ (decomp_str res));
- res
+ let phi = class_tnf (simplify phi_in) in
+ if !debug_level > 0 then
+ print_endline ("Decomposing " ^ (Formula.str phi) ^ " on " ^
+ (struct_sum_str cdef));
+ let phi_fv = free_vars phi in
+ let split_phi = split (Ex (phi_fv, phi)) cdef in
+ let (summand_ids, _) = List.split ids_l in
+ let simp_split_phi = map_to_atoms (simplify_atom summand_ids) split_phi in
+ match List.rev_map simplify
+ (to_dnf (class_tnf (simplify (simp_split_phi)))) with
+ | [] -> [[("", Or [])]]
+ | fl when List.mem (And []) fl -> [[("", And [])]]
+ | fl ->
+ let rec del_quant = (function
+ Ex (vs, psi) ->
+ let was_free v = List.mem v phi_fv in
+ let ws= List.filter (fun x -> not (was_free x)) vs in
+ if ws = [] then del_quant psi else Ex (ws, psi)
+ | And flist -> And (List.map del_quant flist)
+ | psi -> psi (* del_quant is applied to conjucts of DNF*) ) in
+ let del_quants = List.rev_map (fun (s, f) -> (s, del_quant f)) in
+ let process f = rename_extract_conjunction get_ids ids_l f in
+ let decomp_lit_str (cid, phi) =
+ "\nsome " ^ cid ^ " |= " ^ (Formula.str phi) in
+ let decomp_tuple_str cj =
+ "(" ^ String.concat " and " (List.map decomp_lit_str cj) ^ ")" in
+ let decomp_str df =
+ String.concat " or " (List.map decomp_tuple_str df) in
+ let fflat l = List.map (fun (s, f) -> (s, flatten f)) l in
+ let res = List.rev_map (fun f -> fflat (del_quants (process f))) fl in
+ if !debug_level > 1 then
+ print_endline ("DECOMP: " ^ (decomp_str res));
+ res
Modified: trunk/Toss/Solver/ClassTest.ml
===================================================================
--- trunk/Toss/Solver/ClassTest.ml 2011-04-27 17:44:35 UTC (rev 1423)
+++ trunk/Toss/Solver/ClassTest.ml 2011-04-28 22:09:04 UTC (rev 1424)
@@ -1,184 +1,251 @@
-Class.set_debug_level 0 ;;
+open OUnit
+Class.set_debug_level 0
+
let class_of_string s =
ClassParser.parse_class Lexer.lex (Lexing.from_string s)
-;;
+
let formula_of_string s =
FormulaParser.parse_formula Lexer.lex (Lexing.from_string s)
-;;
-let test_sum name f print_f class_str =
- let (_, suml) = List.hd (class_of_string class_str) in
- let sum = List.hd suml in
- print_endline (name ^ " on:\n" ^ (Class.struct_sum_str sum) ^ "\nis:");
- print_endline ((print_f (f sum)) ^"\n");
-;;
+let assert_eq_string arg msg x_in y_in =
+ let full_msg = msg ^ " (argument: " ^ arg ^ ")" in
+ let ws = Str.regexp "[ \n\t]+" in
+ let x = Str.global_replace ws " " (" " ^ x_in ^ " ") in
+ let y = Str.global_replace ws " " (" " ^ y_in ^ " ") in
+ assert_equal ~printer:(fun x -> x) ~msg:full_msg
+ ("\n" ^ x ^ "\n") ("\n" ^ y ^ "\n")
-let test name f print_f class_str =
- let cl = class_of_string class_str in
- print_endline (name ^ " on:\n" ^ (Class.str cl) ^ "\nis:");
- print_endline ((print_f (f cl)) ^"\n");
-;;
-(* ----------------- VARIOUS TREE CLASSES AND PARSING TESTS ----------------- *)
+(* ----------------- VARIOUS CLASSES ----------------- *)
let fin_tree_class =
"point =
- [x | Left:2 {} ; Right:2 {} ; Root { x } | ]
+ [x | Left:2 {}; Right:2 {}; Root (x) | ]
and tree =
point
| L: tree + N: point + R: tree with
- Left (x, y) <- Left (x, y) or (N (x) and L (y) and Root (y)) ;
- Right (x, y) <- Right (x, y) or (N(x) and R (y) and Root (y)) ;
- Root (x) <- N (x);"
-;;
+ Left(x, y) <- Left(x, y) or (N(x) and L(y) and Root(y));
+ Right(x, y) <- Right(x, y) or (N(x) and R(y) and Root(y));
+ Root(x) <- N(x);"
-test "Id" (fun x -> x) Class.str "point = [ x | | ]" ;;
-test "Id" (fun x -> x) Class.str fin_tree_class ;;
-
let inf_tree =
"tree =
L: tree + N: point + R: tree with
- Left (x, y) <- Left (x, y) or (N (x) and L (y) and Root (y)) ;
- Right (x, y) <- Right (x, y) or (N(x) and R (y) and Root (y)) ;
- Root (x) <- N (x);
+ Left(x, y) <- Left(x, y) or (N(x) and L(y) and Root(y));
+ Right(x, y) <- Right(x, y) or (N(x) and R(y) and Root(y));
+ Root(x) <- N(x);
and point =
- [x | Left:2 {} ; Right:2 {} ; Root { x } | ]"
-;;
+ [x | Left:2 {}; Right:2 {}; Root (x) | ]"
-test "Id" (fun x -> x) Class.str inf_tree ;;
-let omega =
- "omega =
- Z: point + S: omega with
- LessEq (x, y) <- LessEq (x, y) or Z (x) ;
- Succ (x, y) <- Succ (x, y) or (Z(x) and S (y) and Zero (y)) ;
- Zero (x) <- Z (x) ;
- and point =
- [x | LessEq { (x, x) } ; Succ:2 {} ; Zero { x } | ]"
-;;
-
-test "Id" (fun x -> x) Class.str inf_tree ;;
-test "Id" (fun x -> x) Class.str omega ;;
-
let inf_tree_lr =
"Ttree =
L: Ltree + N: point + R: Rtree with
- Pref (x, y) <- Pref (x, y) or (N(x) and (L(y) or R(y)));
- Left (x) <- Left (x);
- Right (x) <- Right (x);
- Root (x) <- N(x);
+ Pref(x, y) <- Pref(x, y) or (N(x) and (L(y) or R(y)));
+ Left(x) <- Left(x);
+ Right(x) <- Right(x);
+ Root(x) <- N(x);
and Ltree =
L: Ltree + N: point + R: Rtree with
- Pref (x, y) <- Pref (x, y) or (N(x) and (L(y) or R(y)));
- Left (x) <- Left (x) or N(x);
- Right (x) <- Right (x);
- Root (x) <- Root (x);
+ Pref(x, y) <- Pref(x, y) or (N(x) and (L(y) or R(y)));
+ Left(x) <- Left(x) or N(x);
+ Right(x) <- Right(x);
+ Root(x) <- Root(x);
and Rtree =
L: Ltree + N: point + R: Rtree with
- Pref (x, y) <- Pref (x, y) or (N(x) and (L(y) or R(y)));
- Left (x) <- Left (x);
- Right (x) <- Right (x) or N(x);
- Root (x) <- Root (x);
+ Pref(x, y) <- Pref(x, y) or (N(x) and (L(y) or R(y)));
+ Left(x) <- Left(x);
+ Right(x) <- Right(x) or N(x);
+ Root(x) <- Root(x);
and point =
- [x | Left:1 {} ; Right:1 {} ; Pref:2 {} ; Root:1 {} | ]"
-;;
+ [x | Left:1 {}; Pref:2 {}; Right:1 {}; Root:1 {} | ]"
-test "Id" (fun x -> x) Class.str inf_tree_lr ;;
+let omega =
+ "omega =
+ Z: point + S: omega with
+ LessEq(x, y) <- LessEq(x, y) or Z(x);
+ Succ(x, y) <- Succ(x, y) or (Z(x) and S(y) and Zero(y));
+ Zero(x) <- Z(x);
+ and point =
+ [x | LessEq (x, x); Succ:2 {}; Zero (x) | ]"
-(* ----------------------------- SPLIT TESTS -------------------------------- *)
-let test_split phi_s cs =
- let f = formula_of_string phi_s in
- let split_f s = Class.split f s in
- test_sum ("Split of " ^ phi_s) split_f Formula.str cs
-;;
-let test_split_simplify phi_s cs =
- let f = formula_of_string phi_s in
- let split_f s = Class.split_simplify f s in
- test_sum ("Simplified Split of " ^ phi_s) split_f Formula.str cs
-;;
+(* ------------------- UNIT TESTS ------------------- *)
-(* Splits on inf_tree. *)
+let test_sum name f print_f class_str res_str =
+ let (_, suml) = List.hd (class_of_string class_str) in
+ let sum = List.hd suml in
+ let sum_str = Class.struct_sum_str sum in
+ assert_eq_string sum_str name res_str (print_f (f sum))
-test_split "ex x Root (x)" inf_tree ;;
-test_split "ex x, y Left (x, y)" inf_tree ;;
+let tests = "Class" >::: [
+ "parsing and printing" >::
+ (fun () ->
+ let test name f print_f class_str res_str =
+ let cl = class_of_string class_str in
+ assert_eq_string class_str name res_str (print_f (f cl)) in
+ test "Id" (fun x -> x) Class.str "point = [ x | | ]" "point = [x | | ]";
+ test "Id" (fun x -> x) Class.str fin_tree_class fin_tree_class;
+ test "Id" (fun x -> x) Class.str inf_tree inf_tree;
+ test "Id" (fun x -> x) Class.str inf_tree_lr inf_tree_lr;
+ test "Id" (fun x -> x) Class.str omega omega;
+ );
-(* Y is contains all left-successors of X *)
-test_split "all X ex Y all x, y (x in X and Left (x, y) -> y in Y)" inf_tree ;;
+ "split" >::
+ (fun () ->
+ let test_split ?(do_simp=false) phi_s cs res =
+ let f = formula_of_string phi_s in
+ let split_f s =
+ if do_simp then Class.split_simplify f s else Class.split f s in
+ let name = if do_simp then "Simplified Split of " else "Split of " in
+ test_sum (name ^ phi_s) split_f Formula.str cs res in
+ test_split "ex x Root (x)" inf_tree
+ "(ex x:L (N(x:L)) or ex x:N (N(x:N)) or ex x:R (N(x:R)))";
+ test_split "ex x, y Left (x, y)" inf_tree
+ ("(ex x:L ((ex y:L ((Left(x:L, y:L) or ((N(x:L) and L(y:L)) and " ^
+ "Root(y:L)))) or ex y:N ((Left(x:L, y:N) or ((N(x:L) and L(y:N))" ^
+ " and Root(y:N)))) or ex y:R ((Left(x:L, y:R) or ((N(x:L) and " ^
+ "L(y:R)) and Root(y:R)))))) or ex x:N ((ex y:L ((Left(x:N, y:L) " ^
+ "or ((N(x:N) and L(y:L)) and Root(y:L)))) or ex y:N " ^
+ "((Left(x:N, y:N) or ((N(x:N) and L(y:N)) and Root(y:N)))) " ^
+ "or ex y:R ((Left(x:N, y:R) or ((N(x:N) and L(y:R)) and " ^
+ "Root(y:R)))))) or ex x:R ((ex y:L ((Left(x:R, y:L) or ((N(x:R) " ^
+ "and L(y:L)) and Root(y:L)))) or ex y:N ((Left(x:R, y:N) or " ^
+ "((N(x:R) and L(y:N)) and Root(y:N)))) or ex y:R ((Left(x:R, y:R)" ^
+ " or ((N(x:R) and L(y:R)) and Root(y:R)))))))");
+ test_split ~do_simp:true (* Y is contains all left-successors of X *)
+ "all X ex Y all x, y (x in X and Left (x, y) -> y in Y)" inf_tree
+ ("all X:L, X:N, X:R (ex Y:L, Y:N, Y:R ((all x:L (all y:L" ^
+ " (((y:L in Y:L) or (not (Left(x:L, y:L) and (x:L in X:L))))))" ^
+ " and all x:R (all y:R (((y:R in Y:R) or (not (Left(x:R, y:R) " ^
+ "and (x:R in X:R)))))) and all x:N ((all y:N (((y:N in Y:N) or" ^
+ " (not (Left(x:N, y:N) and (x:N in X:N))))) and all y:L " ^
+ "(((y:L in Y:L) or (not ((x:N in X:N) and Root(y:L))))))))))");
-(* Splits on inf_tree_lr. *)
+ test_split "ex x, y Pref (x, y)" inf_tree_lr
+ ("(ex x:L ((ex y:L ((Pref(x:L, y:L) or (N(x:L) and (L(y:L) or " ^
+ "R(y:L))))) or ex y:N ((Pref(x:L, y:N) or (N(x:L) and (L(y:N)" ^
+ " or R(y:N))))) or ex y:R ((Pref(x:L, y:R) or (N(x:L) and " ^
+ "(L(y:R) or R(y:R))))))) or ex x:N ((ex y:L ((Pref(x:N, y:L) or" ^
+ " (N(x:N) and (L(y:L) or R(y:L))))) or ex y:N ((Pref(x:N, y:N)" ^
+ " or (N(x:N) and (L(y:N) or R(y:N))))) or " ^
+ "ex y:R ((Pref(x:N, y:R) or (N(x:N) and (L(y:R) or R(y:R)))))))" ^
+ " or ex x:R ((ex y:L ((Pref(x:R, y:L) or (N(x:R) and (L(y:L) " ^
+ "or R(y:L))))) or ex y:N ((Pref(x:R, y:N) or (N(x:R) and " ^
+ "(L(y:N) or R(y:N))))) or ex y:R ((Pref(x:R, y:R) or (N(x:R) " ^
+ "and (L(y:R) or R(y:R))))))))");
+ test_split ~do_simp:true
+ ("ex X (all x (x in X -> (Left(x) and all y (Pref(y,x) -> " ^
+ "(Root(y) or Right(y))))))") inf_tree_lr
+ ("ex X:L, X:N, X:R ((all x:N ((Left(x:N) or (not (x:N in X:N)))) " ^
+ "and all x:L (((not (x:L in X:L)) or (Left(x:L) and all y:L " ^
+ "((Right(y:L) or (not Pref(y:L, x:L))))))) and all x:R (((not" ^
+ " (x:R in X:R)) or (Left(x:R) and all y:R ((Right(y:R) or " ^
+ "(not Pref(y:R, x:R)))))))))");
+ test_split ~do_simp:true
+ ("ex X (all x (x in X -> (Left(x) and all y (Pref(y,x) -> " ^
+ "(Root(y) or Right(y))))))") inf_tree_lr
+ ("ex X:L, X:N, X:R ((all x:N ((Left(x:N) or (not (x:N in X:N)))) " ^
+ "and all x:L (((not (x:L in X:L)) or (Left(x:L) and all y:L " ^
+ "((Right(y:L) or (not Pref(y:L, x:L))))))) and all x:R (((not" ^
+ " (x:R in X:R)) or (Left(x:R) and all y:R ((Right(y:R) " ^
+ "or (not Pref(y:R, x:R)))))))))");
+ );
-test_split "ex x, y Pref (x, y)" inf_tree_lr ;;
+ "decompose" >::
+ (fun () ->
+ let test_decompose ?(ids=true) phi_s cs res =
+ let f = formula_of_string phi_s in
+ let decompose_f s = Class.decompose ~get_ids:ids f s in
+ let decomp_lit_str (cid, phi) =
+ "Ex " ^ cid ^ " |= " ^ (Formula.sprint phi) in
+ let decomp_tuple_str cj =
+ "(" ^ String.concat " and " (List.map decomp_lit_str cj) ^ ")" in
+ let decomp_str df =
+ String.concat " or " (List.map decomp_tuple_str df) in
+ test_sum ("Decomposition of " ^ phi_s) decompose_f decomp_str cs res in
-test_split ("ex X (all x (x in X -> (Left(x) and all y (Pref(y,x) -> " ^
- "(Root(y) or Right(y))))))") inf_tree_lr ;;
+ (* On omega *)
+ test_decompose "ex x, y LessEq (x, y)" omega "(Ex |= true)";
+ test_decompose
+ ("ex Z (((not all s ((Zero(s) or (not (s in Z))))) and " ^
+ "ex C ((all s (((s in C) or (not Zero(s)))) and " ^
+ "all t (((t in C) or (not (t in Z)))) and " ^
+ "all t (((t in Z) or (not (t in C)))) and " ^
+ "all s (((not (s in C)) or all t ((not Succ(t, s))))) and all s " ^
+ "(((not (s in C)) or all t (((t in C) or (not Succ(t, s))))))))))")
+ omega
+ ("(Ex Z |= (all s, t not Succ(t, s) and ex Z, C (all s s in C and " ^
+ "all t t in C and all t t in Z)) and Ex S |= ex Z (not all s " ^
+ "not s in Z and ex C (all t (t in C or not t in Z) and all t " ^
+ "(t in Z or not t in C) and all s (not s in C or all t (t in C " ^
+ "or not Succ(t, s))) and all s (not s in C or (not Zero(s) and " ^
+ "all t not Succ(t, s)))))) or (Ex Z |= (all s, t not Succ(t, s) " ^
+ "and ex Z, C (all s s in C and all t t in Z)) and Ex S |= ex Z " ^
+ "(not all s not s in Z and ex C (all t (t in C or not t in Z) and" ^
+ " all t (t in Z or not t in C) and all s (not Zero(s) or " ^
+ "not s in C) and all s (not s in C or all t (t in C or not " ^
+ "Succ(t, s))) and all s (not s in C or (not Zero(s) and " ^
+ "all t not Succ(t, s))))))");
-test_split_simplify ("ex X (all x (x in X -> (Left(x) and all y (Pref(y,x) -> " ^
- "(Root(y) or Right(y))))))") inf_tree_lr ;;
+ (* On inf_tree *)
+ test_decompose "ex x Root (x)" inf_tree "(Ex |= true)";
+ test_decompose "x in X" inf_tree
+ "(Ex L |= x in X) or (Ex N |= x in X) or (Ex R |= x in X)";
+ test_decompose "ex x, y Left (x, y)" inf_tree
+ ("(Ex L |= ex x, y Left(x, y)) or (Ex N |= ex x, y Left(x, y))" ^
+ " or (Ex R |= ex x, y Left(x, y)) or (Ex L |= ex y Root(y))");
+ (* On inf_tree_lr *)
+ test_decompose ("ex X (all x (x in X -> (Left(x) and all y (Pref(y,x) " ^
+ "-> (Root(y) or Right(y))))))") inf_tree_lr
+ ("(Ex R |= ex X all x (not x in X or (Left(x) and all y (Right(y) or " ^
+ "not Pref(y, x)))) and Ex N |= ex X all x (Left(x) or not x in X)" ^
+ " and Ex L |= ex X all x (not x in X or (Left(x) and " ^
+ "all y (Right(y) or not Pref(y, x)))))");
+ test_decompose "Left(x) and Right(y)" inf_tree_lr
+ ("(Ex L |= (Left(x) and Right(y))) or (Ex N |= Right(y) and " ^
+ "Ex L |= Left(x)) or (Ex R |= Right(y) and Ex L |= Left(x)) or " ^
+ "(Ex N |= Left(x) and Ex L |= Right(y)) or (Ex N |= (Left(x) " ^
+ "and Right(y))) or (Ex R |= Right(y) and Ex N |= Left(x)) or " ^
+ "(Ex R |= Left(x) and Ex L |= Right(y)) or (Ex R |= Left(x) and " ^
+ "Ex N |= Right(y)) or (Ex R |= (Left(x) and Right(y)))");
+ test_decompose "ex x Left(x)" inf_tree_lr
+ ("(Ex L |= ex x Left(x)) or (Ex N |= ex x Left(x)) or" ^
+ " (Ex R |= ex x Left(x))");
+ test_decompose "Left(x)" inf_tree_lr
+ "(Ex L |= Left(x)) or (Ex N |= Left(x)) or (Ex R |= Left(x))";
+ test_decompose "all y (x=y or Pref(x,y))" inf_tree_lr
+ "(Ex N |= all y (Pref(x, y) or x = y))";
+ test_decompose "Left(x) and Right(y) and all z (Pref(z,x) and Pref(z,y))"
+ inf_tree_lr "(Ex |= false)";
+ test_decompose
+ "ex X ex y( y in X and all z( Pref(y,z) or z in X))" inf_tree_lr
+ ("(Ex N |= ex X, y (y in X and all z (Pref(y, z) or z in X))) or " ^
+ "(Ex R |= ex X, y (y in X and all z (Pref(y, z) or z in X)) and" ^
+ " Ex N |= ex X all z z in X and Ex L |= ex X all z z in X) or " ^
+ "(Ex R |= ex X all z z in X and Ex N |= ex X all z z in X and " ^
+ "Ex L |= ex X, y (y in X and all z (Pref(y, z) or z in X)))");
+ test_decompose
+ "all X ex y( y in X and all z( Pref(y,z) or z in X))" inf_tree_lr
+ ("(Ex N |= all X ex y (y in X and all z (Pref(y, z) or z in X))) or" ^
+ " (Ex L |= all X, z z in X) or (Ex R |= true and Ex L |= " ^
+ "all X, z z in X) or (Ex R |= all X, z z in X and Ex L |= true) " ^
+ "or (Ex R |= all X, z z in X)");
+ );
+]
-(* --------------------------- DECOMPOSE TESTS ------------------------------ *)
-let test_decompose ids phi_s cs =
- let f = formula_of_string phi_s in
- let decompose_f s = Class.decompose ~get_ids:ids f s in
- let decomp_lit_str (cid, phi) = "some " ^ cid ^ " |= " ^ (Formula.str phi) in
- let decomp_tuple_str cj =
- "(" ^ String.concat " and " (List.map decomp_lit_str cj) ^ ")" in
- let decomp_str df = String.concat " or " (List.map decomp_tuple_str df) in
- test_sum ("Decomposition of " ^ phi_s) decompose_f decomp_str cs
-;;
-
-
-(* Decompositions on omega. *)
-
-test_decompose true "ex x, y LessEq (x, y)" omega ;;
-
-
-(* Decompositions on inf_tree. *)
-
-test_decompose true "ex x Root (x)" inf_tree ;;
-
-test_decompose true "x in X" inf_tree ;;
-
-test_decompose true "ex x, y Left (x, y)" inf_tree ;;
-
-test_decompose true ("ex X (all x (x in X -> (Left(x) and all y (Pref(y,x) -> "^
- "(Root(y) or Right(y))))))") inf_tree_lr ;;
-
-test_decompose true "Left(x) and Right(y)" inf_tree_lr ;;
-
-test_decompose true "ex x Left(x)" inf_tree_lr ;;
-
-test_decompose true "Left(x)" inf_tree_lr ;;
-
-test_decompose true "all y (x=y or Pref(x,y))" inf_tree_lr ;;
-
-test_decompose true "Left(x) and Right(y) and all z (Pref(z,x) and Pref(z,y))" inf_tree_lr ;;
-
-
-(* ------------ There is some bug... --------------- *)
-
-(* "ex X ..." works *)
-test_decompose true "ex X ex y( y in X and all z( Pref(y,z) or z in X))" inf_tree_lr ;;
-
-(* but "all X ..." does not *)
-Class.set_debug_level 2 ;;
-test_decompose true "all X ex y( y in X and all z( Pref(y,z) or z in X))" inf_tree_lr ;;
-
-
-
-
(* ------------------------- MODEL CHECKING TESTS -------------------------- *)
let test_check phi_s id cs =
@@ -188,7 +255,6 @@
print_endline "";
;;
-Class.set_debug_level 0 ;;
test_check "all x, y LessEq (x, y)" "omega" omega ;;
@@ -334,16 +400,6 @@
;;
-test_decompose true
- "ex Z (((not all s ((Zero(s) or (not (s in Z))))) and
- ex C ((all s (((s in C) or (not Zero(s)))) and
- all t (((t in C) or (not (t in Z)))) and
- all t (((t in Z) or (not (t in C)))) and
- all s (((not (s in C)) or all t ((not Succ(t, s)))))
- and all s (((not (s in C)) or all t (((t in C) or (not Succ(t, s))))))))))"
- omega ;;
-
-
(* ------------ HORN FORMULA TESTS ------------------ *)
@@ -358,10 +414,6 @@
"ex X (" ^ quant ^ "(" ^ clauses ^ "))"
;;
-FormulaOps.set_debug_level 0 ;;
-Sat.set_debug_level 0;;
-Class.set_debug_level 1 ;;
-
let horn_f = horn 10 ;;
print_endline ("Horn: " ^ horn_f);
@@ -372,7 +424,6 @@
-BoolFormula.set_simplification 6 ;;
(*
print_endline ("Checking non-TNF Horn...");;
@@ -385,9 +436,4 @@
print_endline ("Checking TNF Horn...");;
test_check horn_tnf "omega" omega ;;
-
-let s = Gc.stat () in
-let alloc_w = s.Gc.minor_words +. s.Gc.major_words -. s.Gc.promoted_words in
-print_endline ("Alloc B: " ^ (string_of_float (4. *. alloc_w)));
-print_endline ("Alloc KB: " ^ (string_of_float (alloc_w /. 256. )));
-print_endline ("Alloc MB: " ^ (string_of_float (alloc_w /. (1024. *. 256.))));
+let exec = Aux.run_test_if_target "ClassTest" tests ;;
Modified: trunk/Toss/Solver/PresbTest.ml
===================================================================
--- trunk/Toss/Solver/PresbTest.ml 2011-04-27 17:44:35 UTC (rev 1423)
+++ trunk/Toss/Solver/PresbTest.ml 2011-04-28 22:09:04 UTC (rev 1424)
@@ -129,7 +129,7 @@
BoolFormula.set_debug_level 0 ;;
BoolFormula.set_simplification 6 ;;
-Class.set_debug_level 1;;
+Class.set_debug_level 0;;
test_check eq "omega" omega ;;
Modified: trunk/Toss/TossTest.ml
===================================================================
--- trunk/Toss/TossTest.ml 2011-04-27 17:44:35 UTC (rev 1423)
+++ trunk/Toss/TossTest.ml 2011-04-28 22:09:04 UTC (rev 1424)
@@ -14,6 +14,7 @@
StructureTest.tests;
AssignmentsTest.tests;
SolverTest.tests;
+ ClassTest.tests;
]
let arena_tests = "Arena" >::: [
@@ -36,6 +37,7 @@
]
let server_tests = "Server" >::: [
+ PictureTest.tests;
ServerTest.tests;
]
Added: trunk/Toss/www/img/Breakthrough.ppm
===================================================================
--- trunk/Toss/www/img/Breakthrough.ppm (rev 0)
+++ trunk/Toss/www/img/Breakthrough.ppm 2011-04-28 22:09:04 UTC (rev 1424)
@@ -0,0 +1,120003 @@
+P3
+200 200
+255
+0
+0
+0
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+43
+0
+21
+47
+0
+19
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+44
+0
+18
+49
+0
+12
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+40
+0
+13
+41
+0
+16
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+41
+0
+20
+41
+0
+20
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+41
+0
+16
+40
+0
+13
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+49
+0
+12
+44
+0
+18
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+47
+0
+19
+43
+0
+21
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+45
+0
+15
+0
+0
+0
+26
+0
+26
+38
+3
+20
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+40
+6
+21
+43
+8
+24
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+52
+17
+30
+44
+9
+24
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+9
+25
+39
+4
+21
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+40
+5
+21
+41
+7
+22
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+48
+13
+27
+45
+10
+25
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+43
+8
+23
+40
+6
+22
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+49
+14
+27
+44
+8
+23
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+45
+11
+26
+38
+3
+20
+26
+0
+26
+26
+0
+26
+39
+4
+21
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+113
+82
+73
+112
+80
+71
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+57
+22
+33
+200
+171
+132
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+197
+167
+130
+54
+20
+31
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+228
+170
+255
+22...
[truncated message content] |