toss-devel-svn Mailing List for Toss (Page 18)
Status: Beta
Brought to you by:
lukaszkaiser
You can subscribe to this list here.
2010 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(25) |
Dec
(62) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2011 |
Jan
(26) |
Feb
(38) |
Mar
(67) |
Apr
(22) |
May
(41) |
Jun
(30) |
Jul
(24) |
Aug
(32) |
Sep
(29) |
Oct
(34) |
Nov
(18) |
Dec
(2) |
2012 |
Jan
(19) |
Feb
(25) |
Mar
(16) |
Apr
(2) |
May
(18) |
Jun
(21) |
Jul
(11) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <luk...@us...> - 2011-02-19 17:22:47
|
Revision: 1323 http://toss.svn.sourceforge.net/toss/?rev=1323&view=rev Author: lukaszkaiser Date: 2011-02-19 17:22:41 +0000 (Sat, 19 Feb 2011) Log Message: ----------- Separate small file for move handling in Play. Modified Paths: -------------- trunk/Toss/Makefile trunk/Toss/Play/Game.ml trunk/Toss/Play/Game.mli trunk/Toss/Play/GameTest.ml trunk/Toss/Play/Makefile trunk/Toss/Server/Server.ml trunk/Toss/TossTest.ml Added Paths: ----------- trunk/Toss/Play/Move.ml trunk/Toss/Play/Move.mli trunk/Toss/Play/MoveTest.ml Modified: trunk/Toss/Makefile =================================================================== --- trunk/Toss/Makefile 2011-02-19 16:03:31 UTC (rev 1322) +++ trunk/Toss/Makefile 2011-02-19 17:22:41 UTC (rev 1323) @@ -119,6 +119,7 @@ # Play tests Play_tests: \ Play/HeuristicTest \ + Play/MoveTest \ Play/GameTest # GGP tests Modified: trunk/Toss/Play/Game.ml =================================================================== --- trunk/Toss/Play/Game.ml 2011-02-19 16:03:31 UTC (rev 1322) +++ trunk/Toss/Play/Game.ml 2011-02-19 17:22:41 UTC (rev 1323) @@ -2,10 +2,6 @@ open Printf -(* TODO: Sampling grid size fixed until doing more work with - continuous games. *) -let cGRID_SIZE = 5 - let debug_level = ref 0 let set_debug_level i = (debug_level := i) @@ -36,7 +32,6 @@ Sys.set_signal Sys.sigalrm (Sys.Signal_handle (fun _ -> timeout := true)) - type f_table = float array (* Cumulative score of players for computing value estimate. *) @@ -65,16 +60,6 @@ Array.map (fun payoff -> (0.5 +. 1./.((float_of_int n) +. 2.)) *. payoff) payoffs -(* Data to return a move as a suggestion rather than directly - following it. *) -type move = { - mv_time : float ; - parameters : (string * float) list ; - rule : string ; - next_loc : int ; (* next location in the arena *) - embedding : (int * int) list ; -} - (* Analogous to {!Arena.game_state}, but without the game component. *) type game_state = { struc : Structure.structure ; (* structure state *) @@ -82,6 +67,11 @@ loc : int ; (* positin in the game graph *) } +let gen_models rules models time moves = + let (mv, a) = Move.gen_models rules models time moves in + (mv, Array.map (fun (l, m, t) -> {struc=m; time=t; loc=l}) a) + + type uctree_node = { node_state : game_state ; node_stats : score ; (* playout statistic *) @@ -208,25 +198,7 @@ delta : float ; (* expected width of payoffs *) } -(* Print a move as string. - TODO: perhaps find a nicer syntax? See {!TestGame.move_str}. *) -let move_str rules struc move = - let r = List.assoc move.rule rules in - let rhs_struc = r.ContinuousRule.discrete.DiscreteRule.rhs_struc in - let fpstr (f, fv) = - f ^ ": " ^ (string_of_float fv) in - let par_str = if move.parameters = [] then " " else - ", " ^ (String.concat ", " (List.map fpstr move.parameters)) in - let p_name (r, e) = - Structure.elem_str rhs_struc r ^": "^ Structure.elem_str struc e in - let emb = String.concat ", " (List.map p_name move.embedding) in - (move.rule) ^ "; " ^ emb ^ "; " ^ fpstr ("t", move.mv_time) ^ par_str ^ - "; " ^ (string_of_int move.next_loc) - -let move_gs_str game_state move = - move_str game_state.Arena.game.Arena.rules game_state.Arena.struc move - let default_params = { cUCB = 1.0 ; cLCB = Some 1.0 ; @@ -533,65 +505,6 @@ randbest else bestsc_table, randbest -let gen_moves grid_size rules model loc = - let matchings = - Aux.concat_map - (fun (label,next_loc) -> - let rule = List.assoc label.Arena.rule rules in - List.map (fun emb -> label,next_loc,emb) - (ContinuousRule.matches model rule)) - loc.Arena.moves in - if matchings = [] then [| |] - else ( - (* generating the grid *) - Array.concat - (List.map (fun (label,next_loc,emb) -> - (* not searching through time *) - let t_l, t_r = label.Arena.time_in in - let t = (t_r +. t_l) /. 2. in - if label.Arena.parameters_in = [] then - [| { - mv_time = t; - parameters = []; - rule = label.Arena.rule; - next_loc = next_loc; - embedding = emb - } |] - else - let param_names, params_in = - List.split label.Arena.parameters_in in - let axes = List.map (fun (f_l,f_r) -> - if grid_size < 2 then - [(f_r +. f_l) /. 2.] - else - let df = (f_r -. f_l) /. float_of_int (grid_size - 1) in - Array.to_list - (Array.init grid_size - (fun i -> f_l +. float_of_int i *. df)) - ) params_in in - let grid = Aux.product axes in - Aux.array_map_of_list (fun params -> { - mv_time = t; - parameters = List.combine param_names params; - rule = label.Arena.rule; - next_loc = next_loc; - embedding = emb} - ) grid - ) matchings)) - -let gen_models rules defined_rels model time moves = - let res = - Aux.map_some (fun mv -> - let rule = List.assoc mv.rule rules in - Aux.map_option - (fun (model, time, _) -> - (* ignoring shifts, i.e. animation steps *) - mv, {loc=mv.next_loc; struc=model; time=time}) - (ContinuousRule.rewrite_single model time mv.embedding - rule mv.mv_time mv.parameters)) (Array.to_list moves) in - let moves, models = List.split res in - Array.of_list moves, Array.of_list models - let debug_count = ref 0 (* Generate evaluation game score (the whole payoff table). *) @@ -615,7 +528,7 @@ and gen_scores grid_size subgames moves models loc = Array.mapi (fun pos mv -> let {struc=model; time=time} = models.(pos) in - play_evgame grid_size model time subgames.(mv.next_loc) + play_evgame grid_size model time subgames.(mv.Move.next_loc) ) moves @@ -635,7 +548,7 @@ let loc = graph.(state.loc) in let moves = if just_payoffs then [| |] - else gen_moves grid_size rules state.struc loc in + else Move.gen_moves grid_size rules state.struc loc in (* Don't forget to check after generating models as well -- postconditions! *) if moves = [| |] then @@ -657,14 +570,14 @@ let nstate = ref None in while !nstate = None && (!pos <> init_pos || !pos < mlen) do let mv = moves.(!pos mod mlen) in - let rule = List.assoc mv.rule rules in + let rule = List.assoc mv.Move.rule rules in nstate := Aux.map_option (fun (model, time, _) -> (* ignoring shifts, i.e. animation steps *) - {loc=mv.next_loc; struc=model; time=time}) + {loc=mv.Move.next_loc; struc=model; time=time}) (ContinuousRule.rewrite_single state.struc state.time - mv.embedding rule mv.mv_time mv.parameters); + mv.Move.embedding rule mv.Move.mv_time mv.Move.parameters); incr pos done; (match !nstate with @@ -731,7 +644,7 @@ ) else let location = graph.(loc) in let moves = - gen_moves grid_size rules model location in + Move.gen_moves grid_size rules model location in if moves = [| |] then (* terminal position *) let res = (* *) @@ -753,8 +666,7 @@ else if !timeout then Array.map (fun _ -> 0.) graph.(loc).Arena.payoffs else - let moves, models = - gen_models rules defined_rels model time moves in + let moves, models = gen_models rules model time moves in let n = Array.length models in if !timeout then Array.map (fun _ -> 0.) graph.(loc).Arena.payoffs @@ -835,8 +747,7 @@ aux alphas 0 in let betas = Array.make num_players infinity in let player = loc.Arena.player in - let moves, models = - gen_models rules defined_rels state.struc state.time moves in + let moves, models = gen_models rules state.struc state.time moves in if models = [| |] then let payoff = Array.map (fun expr -> @@ -982,8 +893,7 @@ (* {{{ log entry *) if !debug_level > 3 then printf "toss: external\n"; (* }}} *) - let moves, models = - gen_models rules defined_rels state.struc state.time moves in + let moves, models = gen_models rules state.struc state.time moves in if models = [| |] then let payoff = Array.map (fun expr -> @@ -1127,7 +1037,7 @@ state ?score subgames evgame_horizon heur_effect heuristic horizon cooperative player = let location = graph.(state.loc) in - let moves = gen_moves grid_size rules state.struc location in + let moves = Move.gen_moves grid_size rules state.struc location in if moves = [| |] then let payoff = Array.map (fun expr -> @@ -1137,8 +1047,7 @@ upscore, Terminal (state, upscore, heuristic, payoff) else - let moves, models = - gen_models rules defined_rels state.struc state.time moves in + let moves, models = gen_models rules state.struc state.time moves in if models = [| |] then let payoff = Array.map (fun expr -> @@ -1336,7 +1245,7 @@ if !debug_level > 2 then printf "\nsuggest:\n%!"; (* }}} *) (match - toss ~grid_size:cGRID_SIZE play play_state + toss ~grid_size:Move.cGRID_SIZE play play_state with | Aux.Left (bpos, moves, memory, _) -> (* [suggest] does not update the state, rule application Modified: trunk/Toss/Play/Game.mli =================================================================== --- trunk/Toss/Play/Game.mli 2011-02-19 16:03:31 UTC (rev 1322) +++ trunk/Toss/Play/Game.mli 2011-02-19 17:22:41 UTC (rev 1323) @@ -110,22 +110,6 @@ {!Arena.game}. *) val initial_state : ?loc:int -> play -> Structure.structure -> play_state -(** Data to return a move as a suggestion rather than directly - following it. *) -type move = { - mv_time : float ; - parameters : (string * float) list ; - rule : string ; - next_loc : int ; (** next location in the arena *) - embedding : (int * int) list ; -} - -val move_str : - (string * ContinuousRule.rule) list -> - Structure.structure -> move -> string - -val move_gs_str : Arena.game_state -> move -> string - val default_params : uct_params (** An UCT-based agent that uses either random playouts (when @@ -147,16 +131,6 @@ Arena.game -> agent -(** Default number of sample points per parameter in tree - search. TODO: fixed for now. *) -val cGRID_SIZE : int - -(** Generate moves available from a state, as an array ordered - deterministically. *) -val gen_moves : - int -> (string * ContinuousRule.rule) list -> - Structure.structure -> Arena.location -> move array - (** Update "memory" assuming that the position given corresponds to a move selected, as generated by {!gen_moves}. With tree search, selects the corresponding subtree of a tree. *) @@ -174,7 +148,7 @@ val toss : grid_size:int -> ?just_payoffs:bool -> play -> play_state -> - (int * move array * memory array * play_state, + (int * Move.move array * memory array * play_state, float array) Aux.choice (** Play a play, by applying {!toss}, till the end. Return the final @@ -210,7 +184,7 @@ state but with accrued computation (i.e. bigger stored search trees). *) val suggest : ?effort:int -> - play -> play_state -> (move * play_state) option + play -> play_state -> (Move.move * play_state) option (* ------------------------- DEBUGGING ------------------------------------- *) Modified: trunk/Toss/Play/GameTest.ml =================================================================== --- trunk/Toss/Play/GameTest.ml 2011-02-19 16:03:31 UTC (rev 1322) +++ trunk/Toss/Play/GameTest.ml 2011-02-19 17:22:41 UTC (rev 1323) @@ -42,20 +42,9 @@ module StrMap = Structure.StringMap module IntMap = Structure.IntMap -(* Like {!Game.move_str}, but simplified (less data, shorter form). *) -let move_str rules struc move = - (* let r = List.assoc move.Game.rule rules in *) - (* let rhs_struc = r.ContinuousRule.discrete.DiscreteRule.rhs_struc in *) - let p_name (r, e) = - (* Structure.elem_str rhs_struc r *) - string_of_int r ^ ":" ^ Structure.elem_str struc e in - let emb = String.concat ", " - (List.map p_name (List.sort Pervasives.compare move.Game.embedding)) in - move.Game.rule ^ "{" ^ emb ^ "}" +let move_str r s m = Move.move_str_short s m +let move_gs_str = Move.move_gs_str_short -let move_gs_str state move = - move_str state.Arena.game.Arena.rules state.Arena.struc move - let update_game ?(defs=false) (lazy (horizon, adv_ratio, game)) state cur_loc = let state = @@ -311,7 +300,7 @@ delta = 2.0} in (* FIXME: give/calc delta *) let init_state = Game.initial_state play struc in (* let endstate,payoff = *) - ignore (Game.play ~grid_size:Game.cGRID_SIZE + ignore (Game.play ~grid_size:Move.cGRID_SIZE ~set_timer:360 ~horizon:30 play init_state) (* in *) (* nothing to assert -- just check halting without exceptions *) (* @@ -348,7 +337,7 @@ ~loc:0 ~effort:2 ~heuristic:breakthrough_heur ~search_method:"alpha_beta_ord" () in - Game.toss ~grid_size:Game.cGRID_SIZE p ps) in + Game.toss ~grid_size:Move.cGRID_SIZE p ps) in assert_equal ~msg:"black wins: suggest" ~printer:(function | Aux.Left (bpos, moves, _, _) -> "game not over: "^move_gs_str state moves.(bpos) @@ -409,7 +398,7 @@ ~heur_adv_ratio ?horizon ~loc:0 ~effort:1 ~search_method:"alpha_beta_ord" () in - Game.toss ~grid_size:Game.cGRID_SIZE p ps) in + Game.toss ~grid_size:Move.cGRID_SIZE p ps) in assert_equal ~msg:"draw (white no move): suggest" ~printer:(function | Aux.Left (bpos, moves, _, _) -> "game not over: "^move_gs_str state moves.(bpos) @@ -943,7 +932,7 @@ for i = 1 to n do Printf.printf "Experiment: Game nr %d of %d\n%!" i n; let _,payoff = - Game.play ~grid_size:Game.cGRID_SIZE ~set_timer:3600 + Game.play ~grid_size:Move.cGRID_SIZE ~set_timer:3600 ?horizon play init_state in if payoff.(0) > 0.0 then incr winsW; if payoff.(1) > 0.0 then incr winsB; Modified: trunk/Toss/Play/Makefile =================================================================== --- trunk/Toss/Play/Makefile 2011-02-19 16:03:31 UTC (rev 1322) +++ trunk/Toss/Play/Makefile 2011-02-19 17:22:41 UTC (rev 1323) @@ -10,12 +10,15 @@ make -C .. Play/$@ HeuristicTest: +MoveTest: GameTest: HeuristicTestProfile: +MoveTestProfile: GameTestProfile: HeuristicTestDebug: +MoveTestDebug: GameTestDebug: tests: Added: trunk/Toss/Play/Move.ml =================================================================== --- trunk/Toss/Play/Move.ml (rev 0) +++ trunk/Toss/Play/Move.ml 2011-02-19 17:22:41 UTC (rev 1323) @@ -0,0 +1,108 @@ +(* Move definition, generation and helper functions. *) + + +(* TODO: Sampling grid size fixed until doing more with continuous games. *) +let cGRID_SIZE = 5 + + +(* Data to return a move as a suggestion rather than directly. *) +type move = { + mv_time : float ; + parameters : (string * float) list ; + rule : string ; + next_loc : int ; (* next location in the arena *) + embedding : (int * int) list ; +} + + +(* Print a move as string. + TODO: perhaps find a nicer syntax? See {!TestGame.move_str}. *) +let move_str rules struc move = + let r = List.assoc move.rule rules in + let rhs_struc = r.ContinuousRule.discrete.DiscreteRule.rhs_struc in + let fpstr (f, fv) = + f ^ ": " ^ (string_of_float fv) in + let par_str = if move.parameters = [] then " " else + ", " ^ (String.concat ", " (List.map fpstr move.parameters)) in + let p_name (r, e) = + Structure.elem_str rhs_struc r ^": "^ Structure.elem_str struc e in + let emb = String.concat ", " (List.map p_name move.embedding) in + (move.rule) ^ "; " ^ emb ^ "; " ^ fpstr ("t", move.mv_time) ^ par_str ^ + "; " ^ (string_of_int move.next_loc) + +let move_gs_str game_state move = + move_str game_state.Arena.game.Arena.rules game_state.Arena.struc move + + +(* Like move_str but simplified (less data, shorter form). *) +let move_str_short struc move = + let p_name (r, e) = + string_of_int r ^ ":" ^ Structure.elem_str struc e in + let emb = String.concat ", " + (List.map p_name (List.sort Pervasives.compare move.embedding)) in + move.rule ^ "{" ^ emb ^ "}" + +let move_gs_str_short state move = move_str_short state.Arena.struc move + + +(* Generate moves available from a state, as an array, in fixed order. *) +let gen_moves grid_size rules model loc = + let matchings = + Aux.concat_map + (fun (label,next_loc) -> + let rule = List.assoc label.Arena.rule rules in + List.map (fun emb -> label,next_loc,emb) + (ContinuousRule.matches model rule)) + loc.Arena.moves in + if matchings = [] then [| |] + else ( + (* generating the grid *) + Array.concat + (List.map (fun (label,next_loc,emb) -> + (* not searching through time *) + let t_l, t_r = label.Arena.time_in in + let t = (t_r +. t_l) /. 2. in + if label.Arena.parameters_in = [] then + [| { + mv_time = t; + parameters = []; + rule = label.Arena.rule; + next_loc = next_loc; + embedding = emb + } |] + else + let param_names, params_in = + List.split label.Arena.parameters_in in + let axes = List.map (fun (f_l,f_r) -> + if grid_size < 2 then + [(f_r +. f_l) /. 2.] + else + let df = (f_r -. f_l) /. float_of_int (grid_size - 1) in + Array.to_list + (Array.init grid_size + (fun i -> f_l +. float_of_int i *. df)) + ) params_in in + let grid = Aux.product axes in + Aux.array_map_of_list (fun params -> { + mv_time = t; + parameters = List.combine param_names params; + rule = label.Arena.rule; + next_loc = next_loc; + embedding = emb} + ) grid + ) matchings)) + + + +let gen_models rules model time moves = + let res = + Aux.map_some (fun mv -> + let rule = List.assoc mv.rule rules in + Aux.map_option + (fun (model, time, _) -> (* ignoring shifts, i.e. animation steps *) + (mv, (mv.next_loc, model, time))) + (ContinuousRule.rewrite_single model time mv.embedding + rule mv.mv_time mv.parameters)) (Array.to_list moves) in + let moves, models = List.split res in + Array.of_list moves, Array.of_list models + Added: trunk/Toss/Play/Move.mli =================================================================== --- trunk/Toss/Play/Move.mli (rev 0) +++ trunk/Toss/Play/Move.mli 2011-02-19 17:22:41 UTC (rev 1323) @@ -0,0 +1,30 @@ +(** Move definition, generation and helper functions. *) + +(** Data to return a move as a suggestion rather than directly. *) +type move = { + mv_time : float ; + parameters : (string * float) list ; + rule : string ; + next_loc : int ; (** next location in the arena *) + embedding : (int * int) list ; +} + +val move_str : (string * ContinuousRule.rule) list -> + Structure.structure -> move -> string +val move_gs_str : Arena.game_state -> move -> string + +val move_str_short : Structure.structure -> move -> string +val move_gs_str_short : Arena.game_state -> move -> string + + + +(** Default number of sample points per parameter in tree search. + TODO: fixed for now. *) +val cGRID_SIZE : int + +(** Generate moves available from a state, as an array, in fixed order. *) +val gen_moves : int -> (string * ContinuousRule.rule) list -> + Structure.structure -> Arena.location -> move array + +val gen_models : (string * ContinuousRule.rule) list -> Structure.structure -> + float -> move array -> move array * (int * Structure.structure * float) array Added: trunk/Toss/Play/MoveTest.ml =================================================================== --- trunk/Toss/Play/MoveTest.ml (rev 0) +++ trunk/Toss/Play/MoveTest.ml 2011-02-19 17:22:41 UTC (rev 1323) @@ -0,0 +1,21 @@ +open OUnit + +let tests = "Move" >::: [ + "move to string" >:: + (fun () -> + let mv = { + Move.mv_time = 0.; + Move.parameters = []; + Move.rule = "rule"; + Move.next_loc = 1; + Move.embedding = [(1, 1)]; + } in + let s = Structure.empty_structure () in + assert_equal ~printer:(fun x -> x) (Move.move_str_short s mv) + "rule{1:1}" + ); +] ;; + +let a = + Aux.run_test_if_target "MoveTest" tests +;; Modified: trunk/Toss/Server/Server.ml =================================================================== --- trunk/Toss/Server/Server.ml 2011-02-19 16:03:31 UTC (rev 1322) +++ trunk/Toss/Server/Server.ml 2011-02-19 17:22:41 UTC (rev 1323) @@ -185,7 +185,7 @@ match res with | Some (move, new_state) -> play_state := Some new_state; - Game.move_gs_str !state move + Move.move_gs_str !state move | None -> "None" ) @@ -205,23 +205,23 @@ let m = List.map (fun (l, s) -> (fn lhs l, fn struc s)) mtch in let moves = - Game.gen_moves Game.cGRID_SIZE rules + Move.gen_moves Move.cGRID_SIZE rules !state.Arena.struc graph.(!state.Arena.cur_loc) in try for i = 0 to Array.length moves - 1 do (* FIXME: handle time and params! *) let mov = moves.(i) in if - r_name = mov.Game.rule && + r_name = mov.Move.rule && (* t = mov.Game.time && *) (* something wrong with this: List.for_all (fun (pn, pv) -> pv = List.assoc pn mov.Game.parameters) p && *) List.for_all (fun (e, f) -> - f = List.assoc e mov.Game.embedding) m + f = List.assoc e mov.Move.embedding) m (* TODO: handle location matching *) then ( - expected_location := mov.Game.next_loc; + expected_location := mov.Move.next_loc; let _ = if !debug_level > 2 then Printf.printf "expected_location = %d\n%!" !expected_location in @@ -247,10 +247,10 @@ | _ -> failwith "req_handle: impossible" in (* Rewriting doesn't handle location update. *) state := - {new_state with Arena.cur_loc = moves.(pos).Game.next_loc}; + {new_state with Arena.cur_loc = moves.(pos).Move.next_loc}; let new_game_state = { Game.struc = new_state.Arena.struc; - loc = moves.(pos).Game.next_loc; + loc = moves.(pos).Move.next_loc; time = new_state.Arena.time; } in play_state := Some { @@ -300,7 +300,7 @@ let m = List.map (fun (l, s) -> (fn lhs l, fn struc s)) mtch in let moves = - Game.gen_moves Game.cGRID_SIZE rules + Move.gen_moves Move.cGRID_SIZE rules !state.Arena.struc graph.(!state.Arena.cur_loc) in let pos = (try @@ -310,20 +310,20 @@ (* {{{ log entry *) if !debug_level > 3 then ( Printf.printf "GDL: for %s considering move %s\n%!" - r_name (Game.move_gs_str !state mov) + r_name (Move.move_gs_str !state mov) ); (* }}} *) if - r_name = mov.Game.rule && + r_name = mov.Move.rule && (* t = mov.Game.time && *) (* something wrong with this: List.for_all (fun (pn, pv) -> pv = List.assoc pn mov.Game.parameters) p && *) List.for_all (fun (e, f) -> - f = List.assoc e mov.Game.embedding) m + f = List.assoc e mov.Move.embedding) m (* TODO: handle location matching *) then ( - expected_location := mov.Game.next_loc; + expected_location := mov.Move.next_loc; let _ = if !debug_level > 2 then Printf.printf "expected_location = %d\n%!" !expected_location in @@ -348,10 +348,10 @@ | _ -> failwith "req_handle: impossible" in (* Rewriting doesn't handle location update. *) state := - {new_state with Arena.cur_loc = moves.(pos).Game.next_loc}; + {new_state with Arena.cur_loc = moves.(pos).Move.next_loc}; let new_game_state = { Game.struc = new_state.Arena.struc; - loc = moves.(pos).Game.next_loc; + loc = moves.(pos).Move.next_loc; time = new_state.Arena.time; } in play_state := Some { @@ -374,7 +374,7 @@ match res with | Some (move, new_state) -> (* Do not change state yet! *) - GDL.translate_move move.Game.rule move.Game.embedding + GDL.translate_move move.Move.rule move.Move.embedding !state | None -> "NOOP" in let msg_len = String.length mov_msg in @@ -401,7 +401,7 @@ let m = List.map (fun (l, s) -> (fn lhs l, fn struc s)) mtch in let moves = - Game.gen_moves Game.cGRID_SIZE rules + Move.gen_moves Move.cGRID_SIZE rules !state.Arena.struc graph.(!state.Arena.cur_loc) in let pos = (try @@ -411,20 +411,20 @@ (* {{{ log entry *) if !debug_level > 3 then ( Printf.printf "GDL: for %s considering move %s\n%!" - r_name (Game.move_gs_str !state mov) + r_name (Move.move_gs_str !state mov) ); (* }}} *) if - r_name = mov.Game.rule && + r_name = mov.Move.rule && (* t = mov.Game.time && *) (* something wrong with this: List.for_all (fun (pn, pv) -> pv = List.assoc pn mov.Game.parameters) p && *) List.for_all (fun (e, f) -> - f = List.assoc e mov.Game.embedding) m + f = List.assoc e mov.Move.embedding) m (* TODO: handle location matching *) then ( - expected_location := mov.Game.next_loc; + expected_location := mov.Move.next_loc; let _ = if !debug_level > 2 then Printf.printf "expected_location = %d\n%!" !expected_location in @@ -449,10 +449,10 @@ | _ -> failwith "req_handle: impossible" in (* Rewriting doesn't handle location update. *) state := - {new_state with Arena.cur_loc = moves.(pos).Game.next_loc}; + {new_state with Arena.cur_loc = moves.(pos).Move.next_loc}; let new_game_state = { Game.struc = new_state.Arena.struc; - loc = moves.(pos).Game.next_loc; + loc = moves.(pos).Move.next_loc; time = new_state.Arena.time; } in play_state := Some { @@ -561,7 +561,7 @@ for i = 1 to n do ( Random.self_init (); Printf.printf "Experiment: Game nr %d of %d\n%!" i n; - let _,payoff = Game.play ~grid_size:Game.cGRID_SIZE ~set_timer:3600 + let _,payoff = Game.play ~grid_size:Move.cGRID_SIZE ~set_timer:3600 ?horizon play init_state in Printf.printf "Game %d payoffs %f, %f\n" i payoff.(0) payoff.(1); aggr_payoff_w := !aggr_payoff_w +. payoff.(0); Modified: trunk/Toss/TossTest.ml =================================================================== --- trunk/Toss/TossTest.ml 2011-02-19 16:03:31 UTC (rev 1322) +++ trunk/Toss/TossTest.ml 2011-02-19 17:22:41 UTC (rev 1323) @@ -22,6 +22,7 @@ let play_tests = "Play" >::: [ HeuristicTest.tests; + MoveTest.tests; GameTest.tests; ] This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2011-02-19 16:03:38
|
Revision: 1322 http://toss.svn.sourceforge.net/toss/?rev=1322&view=rev Author: lukaszkaiser Date: 2011-02-19 16:03:31 +0000 (Sat, 19 Feb 2011) Log Message: ----------- Moving heuristic generation from Game to Heuristic ml. Modified Paths: -------------- trunk/Toss/GGP/GDL.ml trunk/Toss/Play/Game.ml trunk/Toss/Play/Game.mli trunk/Toss/Play/GameTest.ml trunk/Toss/Play/Heuristic.ml trunk/Toss/Play/Heuristic.mli trunk/Toss/Server/Server.ml Modified: trunk/Toss/GGP/GDL.ml =================================================================== --- trunk/Toss/GGP/GDL.ml 2011-02-17 21:59:46 UTC (rev 1321) +++ trunk/Toss/GGP/GDL.ml 2011-02-19 16:03:31 UTC (rev 1322) @@ -2671,7 +2671,7 @@ playing_as := player; game_description := game_descr; player_name_terms := [|Const "X"; Const "O"|]; - Game.use_monotonic := true; + Heuristic.use_monotonic := true; let effort, horizon, heur_adv_ratio = 4, 100, 4.0 in effort, horizon, heur_adv_ratio @@ -2681,7 +2681,7 @@ playing_as := player; game_description := game_descr; player_name_terms := [|Const "WHITE"; Const "RED"|]; - Game.use_monotonic := false; + Heuristic.use_monotonic := false; let effort, horizon, heur_adv_ratio = 10, 100, 4.0 in effort, horizon, heur_adv_ratio Modified: trunk/Toss/Play/Game.ml =================================================================== --- trunk/Toss/Play/Game.ml 2011-02-17 21:59:46 UTC (rev 1321) +++ trunk/Toss/Play/Game.ml 2011-02-19 16:03:31 UTC (rev 1322) @@ -1,5 +1,3 @@ - -(* -*- folded-file: t; -*- *) (* Game-related definitions. The UCTS algorithm. *) open Printf @@ -12,7 +10,6 @@ let set_debug_level i = (debug_level := i) let deterministic_suggest = ref false -let use_monotonic = ref true (* A global "hurry up!" switch triggered by the timer alarm. *) let timeout = ref false @@ -242,84 +239,8 @@ let default_adv_ratio = 2.0 +let default_heuristic = Heuristic.default_heuristic -let default_heuristic_old ?struc advance_ratio - {Arena.rules=rules; Arena.graph=graph} = - (* TODO: cache the default heuristic in game definition or state *) - let drules = - List.map (fun r -> (snd r).ContinuousRule.compiled) rules in - let fluents = Aux.concat_map DiscreteRule.fluents drules in - let frels = Aux.strings_of_list fluents in - let monotonic = !use_monotonic && - List.for_all DiscreteRule.monotonic drules in - let signat_struc = - match struc with Some struc -> struc - | None -> - (snd (List.hd - rules)).ContinuousRule.discrete.DiscreteRule.rhs_struc in - let signat rel = - Structure.StringMap.find rel signat_struc.Structure.rel_signature in - let fluent_preconds = - if monotonic then - Some (DiscreteRule.fluent_preconds drules signat fluents) - else None in - Array.mapi (fun i node -> Array.map - (fun payoff -> - (* {{{ log entry *) - if !debug_level > (* 5 *) 1 then ( - Printf.printf - "default_heuristic: Computing for loc %d of payoff %s...\n%!" - i (Formula.sprint_real payoff); - ); - if !debug_level = 5 then ( - Printf.printf - "default_heuristic: Computing for loc %d\n%!" i; - ); - (* }}} *) - let res = - Heuristic.of_payoff ?struc ?fluent_preconds advance_ratio - frels payoff in - (* {{{ log entry *) - if !debug_level > (* 6 *) 1 then ( - Printf.printf "default_heuristic: %s\n%!" - (Formula.sprint_real res) - ); - (* }}} *) - res) - node.Arena.payoffs) graph - -let fluents_heuristic game = - let (no_players, rules) = (game.Arena.num_players, game.Arena.rules) in - let pl_rules = Array.mapi - (fun i _ -> Arena.rules_for_player i game) (Array.create no_players 1) in - let pos_fluents_of_rule rname = - let drule = (List.assoc rname rules).ContinuousRule.compiled in - let list_upto_one s i = - let vx = Formula.fo_var_of_string "x" in - if i = 0 then Formula.Const (0.) else if i = 1 then - Formula.Sum ([vx], Formula.Rel (s, [|vx|]), Formula.Const (1.)) - else Formula.Const (0.) in - DiscreteRule.fluents_make ~only_pos:true list_upto_one drule in - let pl_fluents = Array.map (Aux.concat_map pos_fluents_of_rule) pl_rules in - let sums = Array.map (fun fl -> - List.fold_left (fun s n-> Formula.Plus (n, s)) (Formula.Const (0.)) - (Aux.unique_sorted fl)) pl_fluents in - let sum_all = - Array.fold_left (fun s n-> Formula.Plus (n, s)) (Formula.Const (0.)) sums in - let heurs = Array.map (fun f -> - Formula.Plus (Formula.Times (Formula.Const (2.), f), - Formula.Times (Formula.Const (-1.), sum_all))) sums in - Array.map (fun _ -> heurs) game.Arena.graph - - -let mix_heur h1 factor h2 = - Array.mapi (fun i a -> Array.mapi (fun j p -> - Formula.Plus (p, Formula.Times (Formula.Const factor, h2.(i).(j)))) a) h1 - -let default_heuristic ?struc advr g = - mix_heur (default_heuristic_old ?struc advr g) 0.2 (fluents_heuristic g) - - (* The UCB1-TUNED estimate, modified to extend to the zero- and one-observation cases. *) let ucb1_tuned ?(lower_bound=false) Modified: trunk/Toss/Play/Game.mli =================================================================== --- trunk/Toss/Play/Game.mli 2011-02-17 21:59:46 UTC (rev 1321) +++ trunk/Toss/Play/Game.mli 2011-02-19 16:03:31 UTC (rev 1322) @@ -4,7 +4,6 @@ (** A global "hurry up!" switch triggered by the timer alarm. *) val get_timeout : unit -> bool val cancel_timeout : unit -> unit -val use_monotonic : bool ref (** History stored for a play, including caching of computations for further use. *) @@ -213,19 +212,7 @@ val suggest : ?effort:int -> play -> play_state -> (move * play_state) option -(** Various constructed heuristics. *) -val mix_heur : Formula.real_expr array array -> float -> - Formula.real_expr array array -> Formula.real_expr array array -val default_heuristic : ?struc:Structure.structure -> float -> - Arena.game -> Formula.real_expr array array - -val default_heuristic_old : ?struc:Structure.structure -> float -> - Arena.game -> Formula.real_expr array array - -val fluents_heuristic : Arena.game -> Formula.real_expr array array - - (* ------------------------- DEBUGGING ------------------------------------- *) (** Debugging information. At level 0 nothing is printed out. Modified: trunk/Toss/Play/GameTest.ml =================================================================== --- trunk/Toss/Play/GameTest.ml 2011-02-17 21:59:46 UTC (rev 1321) +++ trunk/Toss/Play/GameTest.ml 2011-02-19 16:03:31 UTC (rev 1322) @@ -850,10 +850,10 @@ P Q Q +Q . . . \" with DiagA (x, y) = ex u (R(x, u) and C(u, y)) ; DiagB (x, y) = ex u (R(x, u) and C(y, u))" 0 in - Game.use_monotonic := false; + Heuristic.use_monotonic := false; easy_case state 0 "should attack" (fun mov_s -> "Cross{1:a4}" = mov_s); - Game.use_monotonic := true; + Heuristic.use_monotonic := true; ); "connect4 avoid losing" >:: @@ -874,10 +874,10 @@ ... Q..P P..P Q.. \" with DiagA (x, y) = ex u (R(x, u) and C(u, y)) ; DiagB (x, y) = ex u (R(x, u) and C(y, u))" 0 in - Game.use_monotonic := false; + Heuristic.use_monotonic := false; hard_case state 0 "should not attack" (fun mov_s -> "Cross{1:f3}" <> mov_s); - Game.use_monotonic := true; + Heuristic.use_monotonic := true; ); @@ -899,10 +899,10 @@ P P P Q Q . . \" with DiagA (x, y) = ex u (R(x, u) and C(u, y)) ; DiagB (x, y) = ex u (R(x, u) and C(y, u))" 0 in - Game.use_monotonic := false; + Heuristic.use_monotonic := false; hard_case state 0 "should defend" (fun mov_s -> "Cross{1:e2}" = mov_s); - Game.use_monotonic := true + Heuristic.use_monotonic := true ); @@ -966,7 +966,7 @@ let a () = Game.set_debug_level 10 -let a () = Game.use_monotonic := false +let a () = Heuristic.use_monotonic := false let a () = match test_filter Modified: trunk/Toss/Play/Heuristic.ml =================================================================== --- trunk/Toss/Play/Heuristic.ml 2011-02-17 21:59:46 UTC (rev 1321) +++ trunk/Toss/Play/Heuristic.ml 2011-02-19 16:03:31 UTC (rev 1322) @@ -949,3 +949,83 @@ Printf.printf "Heuristic.of_payoff %s =\n%s\n%!" (real_str expr) (real_str res); res + + +(* ------------ HEURISTICS FINAL GENERATION ------------- *) + +let use_monotonic = ref true + +let default_heuristic_old ?struc advance_ratio + {Arena.rules=rules; Arena.graph=graph} = + (* TODO: cache the default heuristic in game definition or state *) + let drules = + List.map (fun r -> (snd r).ContinuousRule.compiled) rules in + let fluents = Aux.concat_map DiscreteRule.fluents drules in + let frels = Aux.strings_of_list fluents in + let monotonic = !use_monotonic && + List.for_all DiscreteRule.monotonic drules in + let signat_struc = + match struc with Some struc -> struc + | None -> + (snd (List.hd + rules)).ContinuousRule.discrete.DiscreteRule.rhs_struc in + let signat rel = + Structure.StringMap.find rel signat_struc.Structure.rel_signature in + let fluent_preconds = + if monotonic then + Some (DiscreteRule.fluent_preconds drules signat fluents) + else None in + Array.mapi (fun i node -> Array.map + (fun payoff -> + (* {{{ log entry *) + if !debug_level > (* 5 *) 1 then ( + Printf.printf + "default_heuristic: Computing for loc %d of payoff %s...\n%!" + i (Formula.sprint_real payoff); + ); + if !debug_level = 5 then ( + Printf.printf + "default_heuristic: Computing for loc %d\n%!" i; + ); + (* }}} *) + let res = + of_payoff ?struc ?fluent_preconds advance_ratio frels payoff in + (* {{{ log entry *) + if !debug_level > (* 6 *) 1 then ( + Printf.printf "default_heuristic: %s\n%!" + (Formula.sprint_real res) + ); + (* }}} *) + res) + node.Arena.payoffs) graph + +let fluents_heuristic game = + let (no_players, rules) = (game.Arena.num_players, game.Arena.rules) in + let pl_rules = Array.mapi + (fun i _ -> Arena.rules_for_player i game) (Array.create no_players 1) in + let pos_fluents_of_rule rname = + let drule = (List.assoc rname rules).ContinuousRule.compiled in + let list_upto_one s i = + let vx = Formula.fo_var_of_string "x" in + if i = 0 then Formula.Const (0.) else if i = 1 then + Formula.Sum ([vx], Formula.Rel (s, [|vx|]), Formula.Const (1.)) + else Formula.Const (0.) in + DiscreteRule.fluents_make ~only_pos:true list_upto_one drule in + let pl_fluents = Array.map (Aux.concat_map pos_fluents_of_rule) pl_rules in + let sums = Array.map (fun fl -> + List.fold_left (fun s n-> Formula.Plus (n, s)) (Formula.Const (0.)) + (Aux.unique_sorted fl)) pl_fluents in + let sum_all = + Array.fold_left (fun s n-> Formula.Plus (n, s)) (Formula.Const (0.)) sums in + let heurs = Array.map (fun f -> + Formula.Plus (Formula.Times (Formula.Const (2.), f), + Formula.Times (Formula.Const (-1.), sum_all))) sums in + Array.map (fun _ -> heurs) game.Arena.graph + + +let mix_heur h1 factor h2 = + Array.mapi (fun i a -> Array.mapi (fun j p -> + Formula.Plus (p, Formula.Times (Formula.Const factor, h2.(i).(j)))) a) h1 + +let default_heuristic ?struc advr g = + mix_heur (default_heuristic_old ?struc advr g) 0.2 (fluents_heuristic g) Modified: trunk/Toss/Play/Heuristic.mli =================================================================== --- trunk/Toss/Play/Heuristic.mli 2011-02-17 21:59:46 UTC (rev 1321) +++ trunk/Toss/Play/Heuristic.mli 2011-02-19 16:03:31 UTC (rev 1322) @@ -1,3 +1,5 @@ +val use_monotonic : bool ref + (** Generate a heuristic from a payoff. Input: a set of relations F whose instances can be altered duirng a @@ -90,3 +92,16 @@ (** Rewrite numeric constants inside an expression. *) val map_constants : (float -> float) -> Formula.real_expr -> Formula.real_expr + + +(** Various constructed heuristics. *) +val mix_heur : Formula.real_expr array array -> float -> + Formula.real_expr array array -> Formula.real_expr array array + +val default_heuristic : ?struc:Structure.structure -> float -> + Arena.game -> Formula.real_expr array array + +val default_heuristic_old : ?struc:Structure.structure -> float -> + Arena.game -> Formula.real_expr array array + +val fluents_heuristic : Arena.game -> Formula.real_expr array array Modified: trunk/Toss/Server/Server.ml =================================================================== --- trunk/Toss/Server/Server.ml 2011-02-17 21:59:46 UTC (rev 1321) +++ trunk/Toss/Server/Server.ml 2011-02-19 16:03:31 UTC (rev 1322) @@ -531,22 +531,22 @@ let game = !state.Arena.game in let heur1 = if (!heur_val_white1 = "MIX" || !heur_val_black1 = "MIX") then - Game.default_heuristic ~struc:!state.Arena.struc heur_adv_ratio game + Heuristic.default_heuristic ~struc:!state.Arena.struc heur_adv_ratio game else if (!heur_val_white1 = "FLUENT" || !heur_val_black1 = "FLUENT") then - Game.fluents_heuristic game + Heuristic.fluents_heuristic game else if (!heur_val_white1 <> "" && !heur_val_black1 <> "") then heur_of_vals !heur_val_white1 !heur_val_black1 else - Game.default_heuristic_old ~struc:!state.Arena.struc heur_adv_ratio game in + Heuristic.default_heuristic_old ~struc:!state.Arena.struc heur_adv_ratio game in let heur2 = if (!heur_val_white2 = "MIX" || !heur_val_black2 = "MIX") then - Game.default_heuristic ~struc:!state.Arena.struc heur_adv_ratio game + Heuristic.default_heuristic ~struc:!state.Arena.struc heur_adv_ratio game else if (!heur_val_white2 = "FLUENT" || !heur_val_black2 = "FLUENT") then - Game.fluents_heuristic game + Heuristic.fluents_heuristic game else if (!heur_val_white2 <> "" && !heur_val_black2 <> "") then heur_of_vals !heur_val_white2 !heur_val_black2 else - Game.default_heuristic_old ~struc:!state.Arena.struc heur_adv_ratio game in + Heuristic.default_heuristic_old ~struc:!state.Arena.struc heur_adv_ratio game in if !debug_level > 0 then (print_heur "1" heur1; print_heur "2" heur2); let play = {Game.game = game; agents= [| Game.default_maximax !state.Arena.struc ~depth:depth1 @@ -589,7 +589,7 @@ GDL.manual_game := s; GDL.manual_translation := true), " GDL game for manual (i.e. hard-coded) translation (tictactoe, breakthrough, etc.)"); ("-f", Arg.String (fun s -> set_state_from_file s), " open file"); - ("-nm", Arg.Unit (fun () -> Game.use_monotonic := false), " turn monotonicity off"); + ("-nm", Arg.Unit (fun () -> Heuristic.use_monotonic := false), " turn monotonicity off"); ("-p", Arg.Int (fun i -> (port := i)), " port number (default: 8110)"); ("-t", Arg.Int (fun i -> (dtimeout := i)), " timeout (default: none)"); ("-heur-white-1", Arg.String (fun s -> heur_val_white1 := s), This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2011-02-17 21:59:52
|
Revision: 1321 http://toss.svn.sourceforge.net/toss/?rev=1321&view=rev Author: lukaszkaiser Date: 2011-02-17 21:59:46 +0000 (Thu, 17 Feb 2011) Log Message: ----------- Change default heuristic to mix strength and the old default. Modified Paths: -------------- trunk/Toss/Play/Game.ml trunk/Toss/Play/Game.mli trunk/Toss/Server/Server.ml Modified: trunk/Toss/Play/Game.ml =================================================================== --- trunk/Toss/Play/Game.ml 2011-02-13 23:17:36 UTC (rev 1320) +++ trunk/Toss/Play/Game.ml 2011-02-17 21:59:46 UTC (rev 1321) @@ -1,3 +1,4 @@ + (* -*- folded-file: t; -*- *) (* Game-related definitions. The UCTS algorithm. *) @@ -242,7 +243,7 @@ let default_adv_ratio = 2.0 -let default_heuristic ?struc advance_ratio +let default_heuristic_old ?struc advance_ratio {Arena.rules=rules; Arena.graph=graph} = (* TODO: cache the default heuristic in game definition or state *) let drules = @@ -310,6 +311,15 @@ Formula.Times (Formula.Const (-1.), sum_all))) sums in Array.map (fun _ -> heurs) game.Arena.graph + +let mix_heur h1 factor h2 = + Array.mapi (fun i a -> Array.mapi (fun j p -> + Formula.Plus (p, Formula.Times (Formula.Const factor, h2.(i).(j)))) a) h1 + +let default_heuristic ?struc advr g = + mix_heur (default_heuristic_old ?struc advr g) 0.2 (fluents_heuristic g) + + (* The UCB1-TUNED estimate, modified to extend to the zero- and one-observation cases. *) let ucb1_tuned ?(lower_bound=false) Modified: trunk/Toss/Play/Game.mli =================================================================== --- trunk/Toss/Play/Game.mli 2011-02-13 23:17:36 UTC (rev 1320) +++ trunk/Toss/Play/Game.mli 2011-02-17 21:59:46 UTC (rev 1321) @@ -214,9 +214,15 @@ play -> play_state -> (move * play_state) option (** Various constructed heuristics. *) +val mix_heur : Formula.real_expr array array -> float -> + Formula.real_expr array array -> Formula.real_expr array array + val default_heuristic : ?struc:Structure.structure -> float -> Arena.game -> Formula.real_expr array array +val default_heuristic_old : ?struc:Structure.structure -> float -> + Arena.game -> Formula.real_expr array array + val fluents_heuristic : Arena.game -> Formula.real_expr array array Modified: trunk/Toss/Server/Server.ml =================================================================== --- trunk/Toss/Server/Server.ml 2011-02-13 23:17:36 UTC (rev 1320) +++ trunk/Toss/Server/Server.ml 2011-02-17 21:59:46 UTC (rev 1321) @@ -525,37 +525,28 @@ print_heur_arr harr;) heur ;; -let add_heur h1 factor h2 = - Array.mapi (fun i a -> Array.mapi (fun j p -> - Formula.Plus (p, Formula.Times (Formula.Const factor, h2.(i).(j)))) a) h1 -;; - let run_test n depth1 depth2 = let (horizon, heur_adv_ratio) = (Some 400, 2.0) in let struc = !state.Arena.struc in let game = !state.Arena.game in let heur1 = if (!heur_val_white1 = "MIX" || !heur_val_black1 = "MIX") then - let dh = - Game.default_heuristic ~struc:!state.Arena.struc heur_adv_ratio game in - add_heur dh 0.2 (Game.fluents_heuristic game) + Game.default_heuristic ~struc:!state.Arena.struc heur_adv_ratio game else if (!heur_val_white1 = "FLUENT" || !heur_val_black1 = "FLUENT") then Game.fluents_heuristic game else if (!heur_val_white1 <> "" && !heur_val_black1 <> "") then heur_of_vals !heur_val_white1 !heur_val_black1 else - Game.default_heuristic ~struc:!state.Arena.struc heur_adv_ratio game in + Game.default_heuristic_old ~struc:!state.Arena.struc heur_adv_ratio game in let heur2 = if (!heur_val_white2 = "MIX" || !heur_val_black2 = "MIX") then - let dh = - Game.default_heuristic ~struc:!state.Arena.struc heur_adv_ratio game in - add_heur dh 0.2 (Game.fluents_heuristic game) + Game.default_heuristic ~struc:!state.Arena.struc heur_adv_ratio game else if (!heur_val_white2 = "FLUENT" || !heur_val_black2 = "FLUENT") then Game.fluents_heuristic game else if (!heur_val_white2 <> "" && !heur_val_black2 <> "") then heur_of_vals !heur_val_white2 !heur_val_black2 else - Game.default_heuristic ~struc:!state.Arena.struc heur_adv_ratio game in + Game.default_heuristic_old ~struc:!state.Arena.struc heur_adv_ratio game in if !debug_level > 0 then (print_heur "1" heur1; print_heur "2" heur2); let play = {Game.game = game; agents= [| Game.default_maximax !state.Arena.struc ~depth:depth1 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2011-02-13 23:17:43
|
Revision: 1320 http://toss.svn.sourceforge.net/toss/?rev=1320&view=rev Author: lukaszkaiser Date: 2011-02-13 23:17:36 +0000 (Sun, 13 Feb 2011) Log Message: ----------- Fluents heuristic, ability to run experiments from server. Modified Paths: -------------- trunk/Toss/Arena/Arena.ml trunk/Toss/Arena/Arena.mli trunk/Toss/Arena/DiscreteRule.ml trunk/Toss/Arena/DiscreteRule.mli trunk/Toss/Play/Game.ml trunk/Toss/Play/Game.mli trunk/Toss/Server/Server.ml Modified: trunk/Toss/Arena/Arena.ml =================================================================== --- trunk/Toss/Arena/Arena.ml 2011-02-13 17:46:00 UTC (rev 1319) +++ trunk/Toss/Arena/Arena.ml 2011-02-13 23:17:36 UTC (rev 1320) @@ -69,6 +69,14 @@ (* -------------------- PARSER HELPER ------------------------------ *) +(* Rules with which a player with given number can move. *) +let rules_for_player player_no game = + let rules_of_loc l = + if l.player = player_no then + Some (List.map (fun (lab, _) -> lab.rule) l.moves) + else None in + List.concat (Aux.map_some rules_of_loc (Array.to_list game.graph)) + (* Add a defined relation to a structure. *) let add_def_rel_single struc (r_name, vars, def_phi) = let def_asg = Solver.M.evaluate struc Modified: trunk/Toss/Arena/Arena.mli =================================================================== --- trunk/Toss/Arena/Arena.mli 2011-02-13 17:46:00 UTC (rev 1319) +++ trunk/Toss/Arena/Arena.mli 2011-02-13 23:17:36 UTC (rev 1320) @@ -43,6 +43,9 @@ val empty_state : game_state +(** Rules with which a player with given number can move. *) +val rules_for_player : int -> game -> string list + val add_def_rels : Structure.structure -> (string * string list * Formula.formula) list -> Structure.structure Modified: trunk/Toss/Arena/DiscreteRule.ml =================================================================== --- trunk/Toss/Arena/DiscreteRule.ml 2011-02-13 17:46:00 UTC (rev 1319) +++ trunk/Toss/Arena/DiscreteRule.ml 2011-02-13 23:17:36 UTC (rev 1320) @@ -47,7 +47,15 @@ } (* We call fluents the relations that can be modified by a rule. *) -let fluents r = +let fluents_make ?(only_pos=false) f r = + let fl_make (s, tp) = + if tp = [] then None else + Some (f s (Array.length (List.hd tp))) in + if only_pos then + Aux.map_some fl_make r.rhs_pos_tuples + else Aux.map_some fl_make (r.rhs_pos_tuples @ r.rhs_neg_tuples) + +let fluents r = let map_rels = Aux.map_some (fun (rel,tups)->if tups=[] then None else Some rel) in map_rels r.rhs_pos_tuples @ map_rels r.rhs_neg_tuples Modified: trunk/Toss/Arena/DiscreteRule.mli =================================================================== --- trunk/Toss/Arena/DiscreteRule.mli 2011-02-13 17:46:00 UTC (rev 1319) +++ trunk/Toss/Arena/DiscreteRule.mli 2011-02-13 23:17:36 UTC (rev 1320) @@ -44,6 +44,8 @@ (* We call fluents the relations that can be modified by a rule. *) val fluents : rule_obj -> string list +val fluents_make : ?only_pos : bool -> (string -> int -> 'a) -> + rule_obj -> 'a list (* A relation is monotonic if it cannot remove tuples. *) val monotonic : rule_obj -> bool Modified: trunk/Toss/Play/Game.ml =================================================================== --- trunk/Toss/Play/Game.ml 2011-02-13 17:46:00 UTC (rev 1319) +++ trunk/Toss/Play/Game.ml 2011-02-13 23:17:36 UTC (rev 1320) @@ -287,6 +287,28 @@ res) node.Arena.payoffs) graph +let fluents_heuristic game = + let (no_players, rules) = (game.Arena.num_players, game.Arena.rules) in + let pl_rules = Array.mapi + (fun i _ -> Arena.rules_for_player i game) (Array.create no_players 1) in + let pos_fluents_of_rule rname = + let drule = (List.assoc rname rules).ContinuousRule.compiled in + let list_upto_one s i = + let vx = Formula.fo_var_of_string "x" in + if i = 0 then Formula.Const (0.) else if i = 1 then + Formula.Sum ([vx], Formula.Rel (s, [|vx|]), Formula.Const (1.)) + else Formula.Const (0.) in + DiscreteRule.fluents_make ~only_pos:true list_upto_one drule in + let pl_fluents = Array.map (Aux.concat_map pos_fluents_of_rule) pl_rules in + let sums = Array.map (fun fl -> + List.fold_left (fun s n-> Formula.Plus (n, s)) (Formula.Const (0.)) + (Aux.unique_sorted fl)) pl_fluents in + let sum_all = + Array.fold_left (fun s n-> Formula.Plus (n, s)) (Formula.Const (0.)) sums in + let heurs = Array.map (fun f -> + Formula.Plus (Formula.Times (Formula.Const (2.), f), + Formula.Times (Formula.Const (-1.), sum_all))) sums in + Array.map (fun _ -> heurs) game.Arena.graph (* The UCB1-TUNED estimate, modified to extend to the zero- and one-observation cases. *) @@ -1072,7 +1094,7 @@ match res with | Aux.Left (_,_,_,state) -> (* {{{ log entry *) - if !debug_level > 5 || (!debug_level > 1 && set_timer <> None) then + if !debug_level > 5 || (!debug_level > 0 && set_timer <> None) then printf "step-state:\n%s\n%!" (Structure.str state.game_state.struc); (* }}} *) play ~grid_size ?set_timer ?horizon ~plys:(plys+1) play_def state Modified: trunk/Toss/Play/Game.mli =================================================================== --- trunk/Toss/Play/Game.mli 2011-02-13 17:46:00 UTC (rev 1319) +++ trunk/Toss/Play/Game.mli 2011-02-13 23:17:36 UTC (rev 1320) @@ -213,7 +213,13 @@ val suggest : ?effort:int -> play -> play_state -> (move * play_state) option +(** Various constructed heuristics. *) +val default_heuristic : ?struc:Structure.structure -> float -> + Arena.game -> Formula.real_expr array array +val fluents_heuristic : Arena.game -> Formula.real_expr array array + + (* ------------------------- DEBUGGING ------------------------------------- *) (** Debugging information. At level 0 nothing is printed out. Modified: trunk/Toss/Server/Server.ml =================================================================== --- trunk/Toss/Server/Server.ml 2011-02-13 17:46:00 UTC (rev 1319) +++ trunk/Toss/Server/Server.ml 2011-02-13 23:17:36 UTC (rev 1320) @@ -268,7 +268,7 @@ | Aux.Right (GDL.Start (_, player, game_descr, startcl, playcl)) -> (* GDL will store the player and the game in its state. *) - Random.init 1234; (* for repeatablity *) + Random.self_init (); (* Random.init 1234; for repeatablity *) let effort, horizon, heur_adv_ratio = GDL.initialize_game state player game_descr startcl in (* TODO: handle timer (startclock) in Game.initialize_default*) @@ -490,6 +490,96 @@ output_string out_ch ("ERR internal error -- see server stdout\n") +let set_state_from_file fn = + Printf.printf "Loading file %s...\n%!" fn; + let f = open_in fn in + let s = ArenaParser.parse_game_state Lexer.lex (Lexing.from_channel f) in + Printf.printf "File %s loaded.\n%!" fn; + game_modified := true; + state := s; +;; + +let heur_val_white1 = ref "";; +let heur_val_black1 = ref "";; +let heur_val_white2 = ref "";; +let heur_val_black2 = ref "";; + +let heur_of_vals white_val black_val = + let real_expr_of_str s = + FormulaParser.parse_real_expr Lexer.lex (Lexing.from_string s) in + let white_heur = + real_expr_of_str ("("^white_val^") - ("^black_val^")") in + let black_heur = + real_expr_of_str ("("^black_val^") - ("^white_val^")") in + let heuristic = [|white_heur; black_heur|] in + Array.make (Array.length !state.Arena.game.Arena.graph) heuristic +;; + +let print_heur pl heur = + print_endline ("\nAll-Heuristics for player " ^ pl); + let print_heur_arr = Array.iteri (fun i heur -> + print_endline ("\n for player " ^ (string_of_int i)); + print_endline (" " ^ Formula.sprint_real heur);) in + Array.iteri (fun i harr -> + print_endline ("\nHeuristic for location " ^ (string_of_int i)); + print_heur_arr harr;) heur +;; + +let add_heur h1 factor h2 = + Array.mapi (fun i a -> Array.mapi (fun j p -> + Formula.Plus (p, Formula.Times (Formula.Const factor, h2.(i).(j)))) a) h1 +;; + +let run_test n depth1 depth2 = + let (horizon, heur_adv_ratio) = (Some 400, 2.0) in + let struc = !state.Arena.struc in + let game = !state.Arena.game in + let heur1 = + if (!heur_val_white1 = "MIX" || !heur_val_black1 = "MIX") then + let dh = + Game.default_heuristic ~struc:!state.Arena.struc heur_adv_ratio game in + add_heur dh 0.2 (Game.fluents_heuristic game) + else if (!heur_val_white1 = "FLUENT" || !heur_val_black1 = "FLUENT") then + Game.fluents_heuristic game + else if (!heur_val_white1 <> "" && !heur_val_black1 <> "") then + heur_of_vals !heur_val_white1 !heur_val_black1 + else + Game.default_heuristic ~struc:!state.Arena.struc heur_adv_ratio game in + let heur2 = + if (!heur_val_white2 = "MIX" || !heur_val_black2 = "MIX") then + let dh = + Game.default_heuristic ~struc:!state.Arena.struc heur_adv_ratio game in + add_heur dh 0.2 (Game.fluents_heuristic game) + else if (!heur_val_white2 = "FLUENT" || !heur_val_black2 = "FLUENT") then + Game.fluents_heuristic game + else if (!heur_val_white2 <> "" && !heur_val_black2 <> "") then + heur_of_vals !heur_val_white2 !heur_val_black2 + else + Game.default_heuristic ~struc:!state.Arena.struc heur_adv_ratio game in + if !debug_level > 0 then (print_heur "1" heur1; print_heur "2" heur2); + let play = {Game.game = game; agents= + [| Game.default_maximax !state.Arena.struc ~depth:depth1 + ~heuristic:heur1 ~heur_adv_ratio ~pruning:true game; + Game.default_maximax !state.Arena.struc ~depth:depth2 + ~heuristic:heur2 ~heur_adv_ratio ~pruning:true game; + |]; delta = 2.0} in (* FIXME: give/calc delta *) + let init_state = Game.initial_state play struc in + Game.set_debug_level 1; + let (aggr_payoff_w, aggr_payoff_b) = (ref 0., ref 0.) in + Printf.printf "Experiment -- running test!\n"; + for i = 1 to n do ( + Random.self_init (); + Printf.printf "Experiment: Game nr %d of %d\n%!" i n; + let _,payoff = Game.play ~grid_size:Game.cGRID_SIZE ~set_timer:3600 + ?horizon play init_state in + Printf.printf "Game %d payoffs %f, %f\n" i payoff.(0) payoff.(1); + aggr_payoff_w := !aggr_payoff_w +. payoff.(0); + aggr_payoff_b := !aggr_payoff_b +. payoff.(1); + Printf.printf "Aggregate payoffs %f, %f\n" !aggr_payoff_w !aggr_payoff_b; + ) done; +;; + + (* ----------------------- START SERVER WHEN CALLED ------------------------- *) let main () = @@ -498,6 +588,7 @@ Gc.minor_heap_size = 80*1024; (* 2*std, opt ~= L2 cache/proc *) Gc.major_heap_increment = 8*124*1024 (* 8*std ok *) }; let (server, port) = (ref "localhost", ref 8110) in + let (experiment, e_len, e_d1, e_d2) = (ref false, ref 1, ref 2, ref 2) in let opts = [ ("-v", Arg.Unit (fun () -> set_debug_level 1), " make Toss server verbose"); ("-vv", Arg.Unit (fun () -> set_debug_level 2), " make Toss server very verbose"); @@ -506,12 +597,27 @@ ("-gdl", Arg.String (fun s -> GDL.manual_game := s; GDL.manual_translation := true), " GDL game for manual (i.e. hard-coded) translation (tictactoe, breakthrough, etc.)"); + ("-f", Arg.String (fun s -> set_state_from_file s), " open file"); ("-nm", Arg.Unit (fun () -> Game.use_monotonic := false), " turn monotonicity off"); ("-p", Arg.Int (fun i -> (port := i)), " port number (default: 8110)"); ("-t", Arg.Int (fun i -> (dtimeout := i)), " timeout (default: none)"); + ("-heur-white-1", Arg.String (fun s -> heur_val_white1 := s), + "white (=first) player heuristic for use by the first player in tests"); + ("-heur-black-1", Arg.String (fun s -> heur_val_black1 := s), + "black (=second) player heuristic for use by the first player in tests"); + ("-heur-white-2", Arg.String (fun s -> heur_val_white2 := s), + "white (=first) player heuristic for use by the second player in tests"); + ("-heur-black-2", Arg.String (fun s -> heur_val_black2 := s), + "black (=second) player heuristic for use by the second player in tests"); + ("-experiment", + Arg.Tuple [Arg.Int (fun i -> experiment := true; e_len := i); + Arg.Int (fun d1 -> e_d1 := d1); Arg.Int (fun d2 -> e_d2 := d2)], + "run experiment on the open file [i] times with depth [d1, d2]") ] in Arg.parse opts (fun _ -> ()) "Try -help for help or one of the following."; - try + if !experiment then + run_test !e_len !e_d1 !e_d2 + else try start_server req_handle !port !server with Host_not_found -> print_endline "The host you specified was not found." ;; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2011-02-13 17:46:06
|
Revision: 1319 http://toss.svn.sourceforge.net/toss/?rev=1319&view=rev Author: lukaszkaiser Date: 2011-02-13 17:46:00 +0000 (Sun, 13 Feb 2011) Log Message: ----------- Small change to non-monotonic heuristic to correct Connect4 with Diags in the structure. Modified Paths: -------------- trunk/Toss/Play/GameTest.ml trunk/Toss/Play/Heuristic.ml trunk/Toss/examples/Gomoku.toss Modified: trunk/Toss/Play/GameTest.ml =================================================================== --- trunk/Toss/Play/GameTest.ml 2011-02-12 17:32:53 UTC (rev 1318) +++ trunk/Toss/Play/GameTest.ml 2011-02-13 17:46:00 UTC (rev 1319) @@ -703,8 +703,8 @@ "gomoku8x8 avoid endgame" >:: (fun () -> - let state = update_game gomoku8x8_game -"[ | | ] \" + let state = update_game ~defs:true gomoku8x8_game +"MODEL [ | | ] \" ... ... ... ... ... ... ... ... ... ... ... ... @@ -721,12 +721,13 @@ Q.. ... ... ... ... ... ... ... ... ... ... ... -\"" 0 in +\" with DiagA (x, y) = ex u (R(x, u) and C(u, y)) ; + DiagB (x, y) = ex u (R(x, u) and C(y, u))" 0 in easy_big_case state 0 "P should block" (fun mov_s -> "Cross{1:b5}" = mov_s); - let state = update_game gomoku8x8_game -"[ | | ] \" + let state = update_game ~defs:true gomoku8x8_game +"MODEL [ | | ] \" ... ... ... ... ... ... ... ... ... ... ... ... @@ -743,7 +744,8 @@ ... ... ... ... ... ... ... ... ... ... ... ... -\"" 0 in +\" with DiagA (x, y) = ex u (R(x, u) and C(u, y)) ; + DiagB (x, y) = ex u (R(x, u) and C(y, u))" 0 in easy_big_case state 0 "P should block with line" (fun mov_s -> "Cross{1:f7}" = mov_s); @@ -752,8 +754,8 @@ "gomoku8x8 block gameover" >:: (fun () -> - let state = update_game gomoku8x8_game -"[ | | ] \" + let state = update_game ~defs:true gomoku8x8_game +"MODEL [ | | ] \" ... ... ... ... ... ... ... ... ... ... ... ... @@ -770,7 +772,8 @@ ... ... ... ... ... ... ... ... ... ... ... ... -\"" 0 in +\" with DiagA (x, y) = ex u (R(x, u) and C(u, y)) ; + DiagB (x, y) = ex u (R(x, u) and C(y, u))" 0 in easy_big_case state 0 "P should block" (fun mov_s -> "Cross{1:a3}" = mov_s); @@ -779,8 +782,8 @@ "gomoku8x8 more pieces" >:: (fun () -> - let state = update_game gomoku8x8_game -"[ | | ] \" + let state = update_game ~defs:true gomoku8x8_game +"MODEL [ | | ] \" ... ... ... ... P ... ... ... ... ... ... ... ... @@ -797,15 +800,16 @@ ...P ... P.. ... ... ... ... ... ... ... ...Q ... -\"" 0 in - easy_big_case state 0 "should block the open line" - (fun mov_s -> "Cross{1:e7}" = mov_s); +\" with DiagA (x, y) = ex u (R(x, u) and C(u, y)) ; + DiagB (x, y) = ex u (R(x, u) and C(y, u))" 0 in + easy_big_case state 0 "should block the open line" + (fun mov_s -> "Cross{1:e7}" = mov_s); ); "gomoku8x8 attack" >:: (fun () -> - let state = update_game gomoku8x8_game -"[ | | ] \" + let state = update_game ~defs:true gomoku8x8_game +"MODEL [ | | ] \" ... ... ... ... ... ... ... ... ... ... ... ... @@ -822,9 +826,10 @@ ... Q.. P.. ... ... ... ... ... ... ... Q.. ... -\"" 0 in - easy_big_case state 0 "should attack the diagonal" - (fun mov_s -> "Cross{1:d4}" = mov_s); +\" with DiagA (x, y) = ex u (R(x, u) and C(u, y)) ; + DiagB (x, y) = ex u (R(x, u) and C(y, u))" 0 in + easy_big_case state 0 "should attack the diagonal" + (fun mov_s -> "Cross{1:d4}" = mov_s); ); "connect4 simple" >:: Modified: trunk/Toss/Play/Heuristic.ml =================================================================== --- trunk/Toss/Play/Heuristic.ml 2011-02-12 17:32:53 UTC (rev 1318) +++ trunk/Toss/Play/Heuristic.ml 2011-02-13 17:46:00 UTC (rev 1319) @@ -624,8 +624,10 @@ let rels = List.filter (fun (rel,_) -> not (Strings.mem rel frels)) rels in let rec aux all_vars = function + | Rel _ | Eq _ | In _ as phi -> phi + | Not psi -> aux all_vars (FormulaOps.nnf ~neg:true psi) | Or phis -> Or (List.map (aux all_vars) phis) - | And phis as phi when has_rels frels phi -> + | And phis (* as phi when (has_rels frels phi) *) -> And (List.map (aux all_vars) phis) | Ex (vs, phi) when has_rels frels phi -> Ex (vs, aux (add_strings (List.map var_str vs) all_vars) phi) @@ -882,7 +884,8 @@ (* }}} *) let phi'' = if parsimony_level > 0 then phi - else FFTNF.ff_tnf (FFTNF.promote_rels frels) phi in + else phi + (* FFTNF.ff_tnf (FFTNF.promote_rels frels) phi *) in (* {{{ log entry *) if !debug_level > 2 then ( Printf.printf Modified: trunk/Toss/examples/Gomoku.toss =================================================================== --- trunk/Toss/examples/Gomoku.toss 2011-02-12 17:32:53 UTC (rev 1318) +++ trunk/Toss/examples/Gomoku.toss 2011-02-13 17:46:00 UTC (rev 1319) @@ -1,7 +1,5 @@ PLAYERS 1, 2 DATA r1: circle, r2: line, adv_ratio: 4, depth: 2 -REL DiagA (x, y) = ex u (R(x, u) and C(u, y)) -REL DiagB (x, y) = ex u (R(x, u) and C(y, u)) REL Row5 (x, y, z, v, w) = R(x, y) and R(y, z) and R(z, v) and R(v, w) REL Col5 (x, y, z, v, w) = C(x, y) and C(y, z) and C(z, v) and C(v, w) REL DiagA5 (x, y, z, v, w) = @@ -58,4 +56,5 @@ ... ... ... ... ... ... ... ... ... ... ... ... -" +" with DiagA (x, y) = ex u (R(x, u) and C(u, y)); + DiagB (x, y) = ex u (R(x, u) and C(y, u)) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2011-02-12 17:33:00
|
Revision: 1318 http://toss.svn.sourceforge.net/toss/?rev=1318&view=rev Author: lukstafi Date: 2011-02-12 17:32:53 +0000 (Sat, 12 Feb 2011) Log Message: ----------- GDL game translation (no action translation yet). Server GDL tictactoe test fix. Game connect-4 tests fix. Several helper functions. Modified Paths: -------------- trunk/Toss/Arena/Arena.ml trunk/Toss/Arena/ArenaParser.mly trunk/Toss/Arena/DiscreteRule.ml trunk/Toss/Arena/DiscreteRule.mli trunk/Toss/Arena/DiscreteRuleTest.ml trunk/Toss/Formula/FormulaOps.ml trunk/Toss/Formula/FormulaOps.mli trunk/Toss/GGP/GDL.ml trunk/Toss/GGP/GDL.mli trunk/Toss/Play/GameTest.ml trunk/Toss/Server/ServerGDLTest.in trunk/Toss/Server/ServerGDLTest.out trunk/Toss/Solver/Structure.ml trunk/Toss/Solver/Structure.mli Modified: trunk/Toss/Arena/Arena.ml =================================================================== --- trunk/Toss/Arena/Arena.ml 2011-02-10 17:40:57 UTC (rev 1317) +++ trunk/Toss/Arena/Arena.ml 2011-02-12 17:32:53 UTC (rev 1318) @@ -222,8 +222,7 @@ Array.to_list (Array.mapi (fun i pname->pname, i) (Array.of_list players)) in let num_players = List.length player_names in - let signature = Structure.StringMap.fold - (fun rel ar si -> (rel, ar)::si) state.Structure.rel_signature [] in + let signature = Structure.rel_signature state in (* {{{ log entry *) if !debug_level > 2 then ( printf "process_definition: parsing new rules...%!"; @@ -486,9 +485,7 @@ | Left rn -> ( try let r = (List.assoc rn state.game.rules) in - let signat = Structure.StringMap.fold - (fun r ar si -> (r,ar)::si) - state.struc.Structure.rel_signature [] in + let signat = Structure.rel_signature state.struc in let defs = List.map (fun (drel, (args, body, _)) -> drel,(args,body)) state.game.defined_rels in @@ -502,9 +499,7 @@ | Right rn -> try let r = (List.assoc rn state.game.rules) in - let signat = Structure.StringMap.fold - (fun r ar si -> (r,ar)::si) - state.struc.Structure.rel_signature [] in + let signat = Structure.rel_signature state.struc in let defs = List.map (fun (drel, (args, body, _)) -> drel,(args,body)) state.game.defined_rels in @@ -714,9 +709,7 @@ | EvalRealExpr (rexpr) -> (state, "ERR eval real not yet implemented") | SetRule (r_name, r) -> ( try - let signat = Structure.StringMap.fold - (fun r ar si -> (r,ar)::si) - state.struc.Structure.rel_signature [] in + let signat = Structure.rel_signature state.struc in let defs = List.map (fun (drel, (args, body, _)) -> drel,(args,body)) state.game.defined_rels in @@ -761,9 +754,7 @@ let set_cond r = let d = r.ContinuousRule.discrete in let (dyn, upd)=(r.ContinuousRule.dynamics, r.ContinuousRule.update) in - let signat = Structure.StringMap.fold - (fun r ar si -> (r,ar)::si) - state.struc.Structure.rel_signature [] in + let signat = Structure.rel_signature state.struc in let defs = List.map (fun (drel, (args, body, _)) -> drel,(args,body)) state.game.defined_rels in @@ -786,9 +777,7 @@ let pre = r.ContinuousRule.discrete.DiscreteRule.pre and inv = r.ContinuousRule.inv and post = r.ContinuousRule.post in - let signat = Structure.StringMap.fold - (fun r ar si -> (r,ar)::si) - state.struc.Structure.rel_signature [] in + let signat = Structure.rel_signature state.struc in let defs = List.map (fun (drel, (args, body, _)) -> drel,(args,body)) state.game.defined_rels in @@ -814,9 +803,7 @@ let pre = r.ContinuousRule.discrete.DiscreteRule.pre and inv = r.ContinuousRule.inv and post = r.ContinuousRule.post in - let signat = Structure.StringMap.fold - (fun r ar si -> (r,ar)::si) - state.struc.Structure.rel_signature [] in + let signat = Structure.rel_signature state.struc in let defs = List.map (fun (drel, (args, body, _)) -> drel,(args,body)) state.game.defined_rels in Modified: trunk/Toss/Arena/ArenaParser.mly =================================================================== --- trunk/Toss/Arena/ArenaParser.mly 2011-02-10 17:40:57 UTC (rev 1317) +++ trunk/Toss/Arena/ArenaParser.mly 2011-02-12 17:32:53 UTC (rev 1318) @@ -9,10 +9,11 @@ %} -%start parse_game_state parse_request +%start parse_game_defs parse_game_state parse_request %type <Arena.request> parse_request request %type <Arena.struct_loc> struct_location %type <(string * int) list -> Arena.location> location +%type <Arena.definition> parse_game_defs %type <Arena.game_state> parse_game_state game_state %type <Arena.game_state -> Arena.game_state> extend_game_state @@ -239,6 +240,9 @@ | error { raise (Lexer.Parsing_error "Syntax error in Server request.") } +parse_game_defs: + game_defs EOF { $1 }; + parse_game_state: game_state EOF { $1 }; Modified: trunk/Toss/Arena/DiscreteRule.ml =================================================================== --- trunk/Toss/Arena/DiscreteRule.ml 2011-02-10 17:40:57 UTC (rev 1317) +++ trunk/Toss/Arena/DiscreteRule.ml 2011-02-12 17:32:53 UTC (rev 1318) @@ -857,6 +857,64 @@ List.map fst rels1 @ List.map fst rels2 @ acc)[] rules +let translate_from_precond ~precond ~add ~del = + let diff a b = List.filter (fun e -> not (List.mem e b)) a in + let del = diff del add in + let rhs_names = Aux.unique_sorted + (Aux.concat_map (fun (_,arg) -> Array.to_list arg) (add @ del)) in + let rewritable args = + Aux.array_for_all (fun v -> List.mem (Formula.var_str v) rhs_names) + args in + let conjs = FormulaOps.flatten_ands precond in + let literals, conjs = Aux.partition_map (function + | Formula.Rel (rel, args) when rewritable args -> + Left (Left (rel,args)) + | Not (Formula.Rel (rel, args)) when rewritable args -> + Left (Right (rel,args)) + | phi -> Right phi) conjs in + let posi, nega = Aux.partition_choice literals in + let precond = Formula.And conjs in + let fvars = FormulaOps.free_vars precond in + let local_vars = + List.filter (fun v-> + not (List.mem (Formula.var_str v) rhs_names)) fvars in + let precond = + if local_vars = [] then precond + else Formula.Ex (local_vars, precond) in + let emb_rels = Aux.unique_sorted + (List.map fst (add @ del) @ List.map fst nega) in + let posi_s = + List.map (fun (rel, args) -> rel, Array.map Formula.var_str args) + posi in + let nega_s = + List.map (fun (rel, args) -> rel, Array.map Formula.var_str args) + nega in + let posi_emb = + List.filter (fun (rel,_) -> List.mem rel emb_rels) posi_s in + let del = List.filter (fun d -> not (List.mem d nega_s)) del in + let rhs_struc, rhs_names = + List.fold_left (fun (rhs_struc, rhs_names) name -> + let rhs_struc, elem = + Structure.add_new_elem rhs_struc ~name () in + rhs_struc, (name, elem)::rhs_names) + (Structure.empty_structure (), []) rhs_names in + let add_rels = List.fold_left (fun struc (rel, args) -> + Structure.add_rel struc rel + (Array.map (fun n -> List.assoc n rhs_names) args)) in + let lhs_struc = rhs_struc in + let rhs_struc = add_rels rhs_struc (add @ diff posi_emb del) in + let lhs_struc = add_rels lhs_struc posi_s in + let lhs_struc = add_rels lhs_struc + (List.map (fun (rel,args) -> "_opt_"^rel, args) + (diff del (posi_emb @ nega_s))) in + { + lhs_struc = lhs_struc; + rhs_struc = rhs_struc; + emb_rels = emb_rels; + rule_s = []; + pre = precond; + } + (** {2 Printing and parsing.} *) let matching_str matching = Modified: trunk/Toss/Arena/DiscreteRule.mli =================================================================== --- trunk/Toss/Arena/DiscreteRule.mli 2011-02-10 17:40:57 UTC (rev 1317) +++ trunk/Toss/Arena/DiscreteRule.mli 2011-02-12 17:32:53 UTC (rev 1318) @@ -112,6 +112,10 @@ val changeable_rels : rule_obj list -> string list +val translate_from_precond : + precond:Formula.formula -> add:(string * string array) list -> + del:(string * string array) list -> rule + (** {2 Printing.} *) val matching_str : matching -> string val matching_str_py : matching -> string Modified: trunk/Toss/Arena/DiscreteRuleTest.ml =================================================================== --- trunk/Toss/Arena/DiscreteRuleTest.ml 2011-02-10 17:40:57 UTC (rev 1317) +++ trunk/Toss/Arena/DiscreteRuleTest.ml 2011-02-12 17:32:53 UTC (rev 1318) @@ -64,8 +64,7 @@ struc_of_str "[ | P:1 {}; R:2 {}; Q{a} | ]" in let lhs_struc = struc_of_str "[ e | | ]" in let rhs_struc = struc_of_str "[ b, c | P{ (b) } | ]" in - let signat = Structure.StringMap.fold - (fun r ar si -> (r,ar)::si) model.Structure.rel_signature [] in + let signat = Structure.rel_signature model in let rule_obj = compile_rule signat [] {lhs_struc = lhs_struc; rhs_struc = rhs_struc; @@ -84,8 +83,7 @@ struc_of_str "[ | P{d}; Q{a} | ]" in let lhs_struc = struc_of_str "[ | Q{e} | ]" in let rhs_struc = struc_of_str "[ b, c | Q:1{}; _opt_Q{c}; P{b} | ]" in - let signat = Structure.StringMap.fold - (fun r ar si -> (r,ar)::si) model.Structure.rel_signature [] in + let signat = Structure.rel_signature model in let rule_obj = compile_rule signat [] {lhs_struc = lhs_struc; rhs_struc = rhs_struc; @@ -105,8 +103,7 @@ let lhs_struc = struc_of_str "[ | Q{e} | ]" in let rhs_struc = struc_of_str "[ b, c | Q:1{}; P{b} | ]" in - let signat = Structure.StringMap.fold - (fun r ar si -> (r,ar)::si) model.Structure.rel_signature [] in + let signat = Structure.rel_signature model in let rule_obj = compile_rule signat [] {lhs_struc = lhs_struc; rhs_struc = rhs_struc; @@ -125,8 +122,7 @@ struc_of_str "[ | P:1{ }; R{(a,b)}; C{(b,c)}; D{(a,c)} | ]" in let lhs_struc = struc_of_str "[ a,e | R{ (e,a) } | ]" in let rhs_struc = struc_of_str "[ a,b,c | P{ (b) }; R:2{}; _opt_R { (a,a); (a,b); (a,c); (b,b); (b,c); (c,b); (c,c) } | ]" in - let signat = Structure.StringMap.fold - (fun r ar si -> (r,ar)::si) model.Structure.rel_signature [] in + let signat = Structure.rel_signature model in let rule_obj = compile_rule signat [] {lhs_struc = lhs_struc; rhs_struc = rhs_struc; @@ -151,8 +147,7 @@ struc_of_str "[ | P:1 {}; R:2 {}; Q{1} | ]" in let lhs_struc = struc_of_str "[ 1 | | ]" in let rhs_struc = struc_of_str "[ 1, 2 | P{ (1) } | ]" in - let signat = Structure.StringMap.fold - (fun r ar si -> (r,ar)::si) model.Structure.rel_signature [] in + let signat = Structure.rel_signature model in let rule_obj = compile_rule signat [] {lhs_struc = lhs_struc; rhs_struc = rhs_struc; @@ -171,8 +166,7 @@ struc_of_str "[ | P{2}; Q{1} | ]" in let lhs_struc = struc_of_str "[ | Q{1} | ]" in let rhs_struc = struc_of_str "[ 1, 2 | Q:1{}; _opt_Q{2}; P{1} | ]" in - let signat = Structure.StringMap.fold - (fun r ar si -> (r,ar)::si) model.Structure.rel_signature [] in + let signat = Structure.rel_signature model in let rule_obj = compile_rule signat [] {lhs_struc = lhs_struc; rhs_struc = rhs_struc; @@ -192,8 +186,7 @@ let lhs_struc = struc_of_str "[ | Q{1} | ]" in let rhs_struc = struc_of_str "[ 1, 2 | Q:1{}; P{1} | ]" in - let signat = Structure.StringMap.fold - (fun r ar si -> (r,ar)::si) model.Structure.rel_signature [] in + let signat = Structure.rel_signature model in let rule_obj = compile_rule signat [] {lhs_struc = lhs_struc; rhs_struc = rhs_struc; @@ -212,8 +205,7 @@ struc_of_str "[ | P:1{ }; R{(1,2)}; C{(2,3)}; D{(1,3)} | ]" in let lhs_struc = struc_of_str "[ 1,2 | R{ (2,1) } | ]" in let rhs_struc = struc_of_str "[ 1,2,3 | P{ (2) }; R:2{}; _opt_R { (1,1); (1,2); (1,3); (2,2); (2,3); (3,2); (3,3) } | ]" in - let signat = Structure.StringMap.fold - (fun r ar si -> (r,ar)::si) model.Structure.rel_signature [] in + let signat = Structure.rel_signature model in let rule_obj = compile_rule signat [] {lhs_struc = lhs_struc; rhs_struc = rhs_struc; @@ -238,8 +230,7 @@ struc_of_str "[ | P{a}; Q{a} | ]" in let lhs_struc = struc_of_str "[ e | | ]" in let rhs_struc = struc_of_str "[ b,c | P{ (b) } | ]" in - let signat = Structure.StringMap.fold - (fun r ar si -> (r,ar)::si) model.Structure.rel_signature [] in + let signat = Structure.rel_signature model in let rule_obj = compile_rule signat [] {lhs_struc = lhs_struc; rhs_struc = rhs_struc; @@ -259,8 +250,7 @@ let lhs_struc = struc_of_str "[ | P{e} | ]" in let rhs_struc = struc_of_str "[ b,c | P{ (b) }; _opt_P{ (c) }; Q:1{}; _opt_Q{ (b) } | ]" in - let signat = Structure.StringMap.fold - (fun r ar si -> (r,ar)::si) model.Structure.rel_signature [] in + let signat = Structure.rel_signature model in let rule_obj = compile_rule signat [] {lhs_struc = lhs_struc; rhs_struc = rhs_struc; @@ -284,8 +274,7 @@ struc_of_str "[ | Q{a}; P:1{ }; R:2{}; D:2{} | ]" in let lhs_struc = struc_of_str "[ b | | ]" in let rhs_struc = struc_of_str "[ | P{ (b) } | ]" in - let signat = Structure.StringMap.fold - (fun r ar si -> (r,ar)::si) model.Structure.rel_signature [] in + let signat = Structure.rel_signature model in let rule_obj = compile_rule signat [] {lhs_struc = lhs_struc; rhs_struc = rhs_struc; @@ -304,8 +293,7 @@ struc_of_str "[ | P{d}; Q{a}; R:2{}; D:2{} | ]" in let lhs_struc = struc_of_str "[ | Q{e} | ]" in let rhs_struc = struc_of_str "[ | P{ (e) }; Q:1{} | ]" in - let signat = Structure.StringMap.fold - (fun r ar si -> (r,ar)::si) model.Structure.rel_signature [] in + let signat = Structure.rel_signature model in let rule_obj = compile_rule signat [] {lhs_struc = lhs_struc; rhs_struc = rhs_struc; @@ -329,8 +317,7 @@ let lhs_struc = struc_of_str "[ b | | ]" in let rhs_struc = struc_of_str "[ b | P{ (b) }; Q{ (b) } | ]" in - let signat = Structure.StringMap.fold - (fun r ar si -> (r,ar)::si) model.Structure.rel_signature [] in + let signat = Structure.rel_signature model in let rule_obj = compile_rule signat [] {lhs_struc = lhs_struc; rhs_struc = rhs_struc; @@ -350,8 +337,7 @@ let lhs_struc = struc_of_str "[ | P{ (b) } | ]" in let rhs_struc = struc_of_str "[ | P{ (b) } | ]" in - let signat = Structure.StringMap.fold - (fun r ar si -> (r,ar)::si) model.Structure.rel_signature [] in + let signat = Structure.rel_signature model in let rule_obj = compile_rule signat [] {lhs_struc = lhs_struc; rhs_struc = rhs_struc; @@ -376,8 +362,7 @@ let lhs_struc = struc_of_str "[ b | P{b} | ]" in let rhs_struc = struc_of_str "[ b,c | _opt_P{c} | ]" in - let signat = Structure.StringMap.fold - (fun r ar si -> (r,ar)::si) model.Structure.rel_signature [] in + let signat = Structure.rel_signature model in let rule_obj = compile_rule signat [] {lhs_struc = lhs_struc; rhs_struc = rhs_struc; @@ -401,8 +386,7 @@ let lhs_struc = struc_of_str "[ a | P {a} | ]" in let rhs_struc = struc_of_str "[ b | P:1{}; Q {b} | ]" in - let signat = Structure.StringMap.fold - (fun r ar si -> (r,ar)::si) model.Structure.rel_signature [] in + let signat = Structure.rel_signature model in let rule_obj = compile_rule signat [] {lhs_struc = lhs_struc; rhs_struc = rhs_struc; @@ -421,8 +405,7 @@ let lhs_struc = struc_of_str "[ a,b | C {(a,b)} | ]" in let rhs_struc = struc_of_str "[ c,d | C:2{}; D {(c,d)} | ]" in - let signat = Structure.StringMap.fold - (fun r ar si -> (r,ar)::si) model.Structure.rel_signature [] in + let signat = Structure.rel_signature model in let rule_obj = compile_rule signat [] {lhs_struc = lhs_struc; rhs_struc = rhs_struc; @@ -447,8 +430,7 @@ let lhs_struc = struc_of_str "[ a | P {a} | ]" in let rhs_struc = struc_of_str "[ b,c | P:1{}; Q {b}; R{(b,c)} | ]" in - let signat = Structure.StringMap.fold - (fun r ar si -> (r,ar)::si) model.Structure.rel_signature [] in + let signat = Structure.rel_signature model in let rule_obj = compile_rule signat [] {lhs_struc = lhs_struc; rhs_struc = rhs_struc; @@ -468,8 +450,7 @@ let lhs_struc = struc_of_str "[ a,b | C {(a,b)} | ]" in let rhs_struc = struc_of_str "[ c | P {c} | ]" in - let signat = Structure.StringMap.fold - (fun r ar si -> (r,ar)::si) model.Structure.rel_signature [] in + let signat = Structure.rel_signature model in let rule_obj = compile_rule signat [] {lhs_struc = lhs_struc; rhs_struc = rhs_struc; @@ -489,8 +470,7 @@ let lhs_struc = struc_of_str "[ a,b | C {(a,b)} | ]" in let rhs_struc = struc_of_str "[ c,d | C:2{}; D {(c,d)} | ]" in - let signat = Structure.StringMap.fold - (fun r ar si -> (r,ar)::si) model.Structure.rel_signature [] in + let signat = Structure.rel_signature model in let rule_obj = compile_rule signat [] {lhs_struc = lhs_struc; rhs_struc = rhs_struc; @@ -514,8 +494,7 @@ struc_of_str "[ | P:1{};Q:1{};R{(a,a)} | ]" in let lhs_struc = struc_of_str "[ a,e | R{ (e,a) } | ]" in let rhs_struc = struc_of_str "[ a,e | R { (a,e) } | ]" in - let signat = Structure.StringMap.fold - (fun r ar si -> (r,ar)::si) model.Structure.rel_signature [] in + let signat = Structure.rel_signature model in let rule_obj = compile_rule signat [] {lhs_struc = lhs_struc; rhs_struc = rhs_struc; @@ -540,8 +519,7 @@ struc_of_str "[ | P{e}; Q:1{}; C{e} | ]" in let lhs_struc = struc_of_str "[ | P{a} | ]" in let rhs_struc = struc_of_str "[ | P:1{}; Q{b} | ]" in - let signat = Structure.StringMap.fold - (fun r ar si -> (r,ar)::si) model.Structure.rel_signature [] in + let signat = Structure.rel_signature model in let rule_obj = compile_rule signat [] {lhs_struc = lhs_struc; rhs_struc = rhs_struc; @@ -559,8 +537,7 @@ let lhs_struc = struc_of_str "[ | P{a} | ]" in let rhs_struc = struc_of_str "[ | P:1{}; Q{b} | ]" in - let signat = Structure.StringMap.fold - (fun r ar si -> (r,ar)::si) model.Structure.rel_signature [] in + let signat = Structure.rel_signature model in let rule_obj = compile_rule signat [] {lhs_struc = lhs_struc; rhs_struc = rhs_struc; @@ -582,8 +559,7 @@ let lhs_struc = struc_of_str "[a,b | P{a;b} | ]" in let rhs_struc = struc_of_str "[ | P:1{}; Q{c} | ]" in - let signat = Structure.StringMap.fold - (fun r ar si -> (r,ar)::si) model.Structure.rel_signature [] in + let signat = Structure.rel_signature model in let rule_obj = compile_rule signat [] {lhs_struc = lhs_struc; rhs_struc = rhs_struc; Modified: trunk/Toss/Formula/FormulaOps.ml =================================================================== --- trunk/Toss/Formula/FormulaOps.ml 2011-02-10 17:40:57 UTC (rev 1317) +++ trunk/Toss/Formula/FormulaOps.ml 2011-02-12 17:32:53 UTC (rev 1318) @@ -627,6 +627,12 @@ | Not phi -> Not (flatten_formula phi) | (Rel _ | Eq _ | In _ | RealExpr _) as atom -> atom +(* Formula as a list of conjuncts. *) +let rec flatten_ands = function + | Formula.And conjs -> Aux.concat_map flatten_ands conjs + | phi -> [phi] + + (* Compute size of a formula (currently w/o descending the real part). *) let rec size = function | Or js | And js -> List.fold_left (+) 1 (List.map size js) Modified: trunk/Toss/Formula/FormulaOps.mli =================================================================== --- trunk/Toss/Formula/FormulaOps.mli 2011-02-10 17:40:57 UTC (rev 1317) +++ trunk/Toss/Formula/FormulaOps.mli 2011-02-12 17:32:53 UTC (rev 1318) @@ -74,6 +74,9 @@ (** Flatten "and"s and "or"s in a formula -- i.e. associativity. *) val flatten_formula : formula -> formula +(** Formula as a list of conjuncts. *) +val flatten_ands : formula -> formula list + (** Compute size of a formula (currently w/o descending the real part). *) val size : formula -> int Modified: trunk/Toss/GGP/GDL.ml =================================================================== --- trunk/Toss/GGP/GDL.ml 2011-02-10 17:40:57 UTC (rev 1317) +++ trunk/Toss/GGP/GDL.ml 2011-02-12 17:32:53 UTC (rev 1318) @@ -412,13 +412,16 @@ by all values in its domain (for example, as gathered from the aggregate playout), and expanding all atoms that contained value variables (both static and dynamic) using (6); fail if a goal - value cannot be determined. The payoff formula is the sum of - "goal" value times the characterisic function of the "goal" - body. We do not translate the body if the value is zero (we drop - the zero goal branches from the definition). Translate the body - using (7h)-(7m), but treating "goal" branches separately -- when - (7k) duplicates a branch, new branches add new sum elements. + value cannot be determined. + (8a) The payoff formula is the sum of "goal" value times the + characterisic function of the corresponding "goal" bodies. We do + not translate the body if the value is zero (we drop the zero goal + branches from the definition). For each goal value we collect + bodies to form a disjunction. + +() + *) let debug_level = ref 0 @@ -1461,7 +1464,8 @@ if next_arg = Const "_IGNORE_RHS_" then [], [] else let mask, sb, m_sb, blanked = term_to_blank masks next_arg in - let rhs_elem = term_to_name blanked in + let rhs_elem = + (* Formula.fo_var_of_string *) (term_to_name blanked) in Aux.partition_map (fun (v,t as v_sb) -> if t = Const "_BLANK_" then let neg_rels = List.assoc (mask, v) dyn_rels in @@ -1550,10 +1554,8 @@ let lift_universal (uni_vars : Formula.fo_var list) conjs = - let rec flatten_ands = function - | Formula.And conjs -> Aux.concat_map flatten_ands conjs - | phi -> [phi] in - let conjs = Aux.unique_sorted (Aux.concat_map flatten_ands conjs) in + let conjs = Aux.unique_sorted + (Aux.concat_map FormulaOps.flatten_ands conjs) in (* {{{ log entry *) if !debug_level > 2 then ( Printf.printf "lift_universal: vars %s -- conjs:\n%s\n%!" @@ -1736,6 +1738,7 @@ let legal_rules = List.assoc "legal" exp_defs in let next_rules = List.assoc "next" exp_defs in let terminal_rules = List.assoc "terminal" exp_defs in + let goal_rules = List.assoc "goal" exp_defs in (* 3b *) let exp_next = Aux.concat_map (subst_def_branch ["does", legal_rules]) next_rules in @@ -2144,7 +2147,7 @@ (* 7e -- TODO (together with non-maximal (7d) classes) *) (* 7f *) let rules_brs = - List.map (fun (lead_head, lead_body, lead_neg_body as lead, + List.map (fun ((lead_head, lead_body, lead_neg_body), branches) -> let fixed_vars = term_vars lead_head in let fixed_brs, other_brs = List.partition @@ -2295,7 +2298,7 @@ (* TODO: (7f5) we ignore the possibility that "lead" is instantiated by some of erasure substitutions, since we already ignore non-maximal "legal" classes *) - lead, fixed_brs @ erasure_brs + lead_head, fixed_brs @ erasure_brs ) rules_brs in (* let rules_inds = Array.of_list rules_brs in *) rules_brs @@ -2305,7 +2308,7 @@ if !debug_level > 1 then ( Array.iteri (fun loc rules_brs -> Printf.printf "Rule precursors for loc %d:\n%!" loc; - List.iter (fun ((lead,_,_), brs) -> + List.iter (fun (lead, brs) -> Printf.printf "Rule-precursor: player %s move %s\n%s\n%!" (term_str loc_players.(loc)) (term_str lead) (def_str ("action", brs)) @@ -2350,7 +2353,7 @@ function | "_DOES_PLACEHOLDER_",args -> (try ignore ( - unify [] [loc_players.(loc); Aux.fst3 lead] + unify [] [loc_players.(loc); lead] args); true with Not_found -> false) | _ -> false) body @@ -2484,28 +2487,86 @@ | _ -> assert false) terminal_rules in let terminal_uni_vars, terminal_4b, terminal_brs = translate_branches struc masks static_rnames dyn_rels terminal_brs in - (* lifting will drop spurious (4b) premises *) let terminal_disjs = List.map (fun ((_,_,_,conjs),_) -> let disj_vars = FormulaOps.free_vars (Formula.And conjs) in let disj_4b = List.filter (fun a -> List.exists (fun v->List.mem v disj_vars) (FormulaOps.free_vars a)) terminal_4b in - lift_universal terminal_uni_vars - (disj_4b @ conjs)) terminal_brs in + Formula.Ex (disj_vars, + lift_universal terminal_uni_vars + (disj_4b @ conjs))) terminal_brs in let terminal_phi = Formula.Or terminal_disjs in + + let fluents = Aux.strings_of_list + (Aux.concat_map (fun (_,drels) -> drels) dyn_rels) in (* {{{ log entry *) if !debug_level > 1 then ( Printf.printf "GDL.translate_game: terminal condition -- %s\n%!" - (Formula.sprint terminal_phi) + (Formula.sprint terminal_phi); ); (* }}} *) - (* let loc_toss_rules = *) + (* 8 *) + let goal_rules = + Aux.concat_map (function [Const _; _], _, _ as lrule -> [lrule] + | [Var v; gterm], body, neg_body -> + Array.to_list + (Array.map (fun player -> + let sb = [v, player] in + [player; subst sb gterm], + subst_rels sb body, + List.map (fun (uni_vs,neg) -> uni_vs, subst_rels sb neg) neg_body) + player_terms) + | [Func _; gterm], _, _ -> + (* TODO: easy to fix *) + failwith "GDL.translate_game: bigger player terms not handled yet" + | _ -> assert false) goal_rules in + let goal_brs = + List.map (function + | [player; score], body, neg_body -> + player, (score, ([Const "_IGNORE_RHS_"], body, neg_body)) + | _ -> assert false) goal_rules in + let player_goals = + List.map (fun (player, goal_brs) -> player, Aux.collect goal_brs) + (Aux.collect goal_brs) in + let payoffs = List.map (fun (player, goals) -> + let payoff = List.fold_left (fun sum (score, brs) -> + let score = + match score with + | Const pay -> + (try float_of_string pay with _ -> assert false) + | _ -> assert false in + let goal_uni_vars, goal_4b, brs = + translate_branches struc masks static_rnames dyn_rels brs in + let goal_disjs = List.map (fun ((_,_,_,conjs),_) -> + let disj_vars = FormulaOps.free_vars (Formula.And conjs) in + let disj_4b = + List.filter (fun a -> List.exists (fun v->List.mem v disj_vars) + (FormulaOps.free_vars a)) goal_4b in + lift_universal goal_uni_vars + (disj_4b @ conjs)) brs in + let guard = Formula.Or goal_disjs in + Formula.Plus (sum, Formula.Times ( + Formula.Const score, Formula.Char guard)) + ) (Formula.Const 0.) goals in + player, payoff + ) player_goals in + (* {{{ log entry *) if !debug_level > 1 then ( + Printf.printf "GDL.translate_game: payoffs --\n%!"; + List.iter (fun (player, payoff) -> + Printf.printf "%s: %s\n%!" + (term_str player) (Formula.sprint_real payoff)) + payoffs + ); + (* }}} *) + + (* {{{ log entry *) + if !debug_level > 1 then ( Array.iteri (fun loc rules_brs -> Printf.printf "Rule translations for loc %d:\n%!" loc; - List.iter (fun ((lead,_,_), (rhs_pos,rhs_neg,precond)) -> + List.iter (fun (lead, (rhs_pos,rhs_neg,precond)) -> Printf.printf "Rule-translation: player %s move %s precond:\n%s\naction:\nADD %s... DEL %s\n%!" (term_str loc_players.(loc)) (term_str lead) @@ -2516,20 +2577,73 @@ ) loc_toss_rules; ); (* }}} *) - struc + let signature = Structure.rel_signature struc in + let payoffs = Aux.array_from_assoc + (List.map (fun (player, payoff) -> find_player player, payoff) + payoffs) in + let payoffs_pp = + Array.map (fun pay -> Solver.M.register_real_expr pay) payoffs in + let rules_and_locations = + let rnames = ref Aux.Strings.empty in + Array.mapi (fun loc rules_brs -> + let labelled_rules = + List.map (fun (lead, (rhs_pos,rhs_neg,precond)) -> + let precond = + Formula.And [precond; Formula.Not terminal_phi] in + let rname = Aux.not_conflicting_name !rnames + ((term_to_name lead) ^ "_" ^ string_of_int loc) in + rnames := Aux.Strings.add rname !rnames; + let next_loc = (loc + 1) mod loc_n in + let label = { + Arena.rule = rname; + time_in = 0.1, 0.1; parameters_in = [] + }, next_loc in + let discrete = + DiscreteRule.translate_from_precond ~precond + ~add:rhs_pos ~del:rhs_neg in + let rule = + ContinuousRule.make_rule signature [] discrete + [] [] ~pre:discrete.DiscreteRule.pre () in + label, (rname, rule) + ) rules_brs in + let labels, rules = List.split labelled_rules in + let location = { + Arena.id = loc; + player = find_player loc_players.(loc); + payoffs = payoffs; + payoffs_pp = payoffs_pp; + moves = labels} in + rules, location + ) loc_toss_rules in + let rules = Array.map fst rules_and_locations + and locations = Array.map snd rules_and_locations in + let rules = List.concat (Array.to_list rules) in + let player_names = + Array.to_list + (Array.mapi (fun pnum pterm -> term_to_name pterm, pnum) + player_terms) in + let game = { + Arena.rules = rules; + graph = locations; + num_players = players_n; + player_names = player_names; + defined_rels = []} in + let result = { + Arena.game = game; + struc = struc; + time = 0.; + cur_loc = 0; + data = []; + } in + (* {{{ log entry *) + if !debug_level > 1 then ( + Printf.printf "\n\nGDL.translate_game:\n%s\n%!" + (Arena.sprint_state result) + ); + (* }}} *) + result -(* - let paths = collect_paths element_terms in - let static_facts = - Array.of_list - (Aux.map_some (function Atomic p -> Some p | _ -> None) game_descr) in - let element_names = List.map term_to_name element_terms in - let struc = List.fold_left (fun acc name -> - fst (Structure.add_new_elem acc ~name ())) - Structure.empty_structure element_names in -*) - let player_name_terms = ref [|Const "uninit"|] Modified: trunk/Toss/GGP/GDL.mli =================================================================== --- trunk/Toss/GGP/GDL.mli 2011-02-10 17:40:57 UTC (rev 1317) +++ trunk/Toss/GGP/GDL.mli 2011-02-12 17:32:53 UTC (rev 1318) @@ -74,7 +74,7 @@ term list * (term list list list * term list list) (* DEBUG intermediate *) -val translate_game : game_descr_entry list -> Structure.structure +val translate_game : game_descr_entry list -> Arena.game_state val defs_of_rules : gdl_rule list -> exp_def list val expand_def_rules : ?more_defs:exp_def list -> gdl_rule list -> exp_def list Modified: trunk/Toss/Play/GameTest.ml =================================================================== --- trunk/Toss/Play/GameTest.ml 2011-02-10 17:40:57 UTC (rev 1317) +++ trunk/Toss/Play/GameTest.ml 2011-02-12 17:32:53 UTC (rev 1318) @@ -20,6 +20,12 @@ let real_expr_of_str s = FormulaParser.parse_real_expr Lexer.lex (Lexing.from_string s) +let defstruc_of_str s = + match + ArenaParser.parse_game_defs Lexer.lex (Lexing.from_string s) + with Arena.StateStruc struc -> struc + | _ -> failwith "defstruc_of_str: not a structure" + let state_of_str s = ArenaParser.parse_game_state Lexer.lex (Lexing.from_string s) @@ -50,8 +56,10 @@ let move_gs_str state move = move_str state.Arena.game.Arena.rules state.Arena.struc move -let update_game (lazy (horizon, adv_ratio, game)) state cur_loc = - let state = struc_of_str state in +let update_game ?(defs=false) + (lazy (horizon, adv_ratio, game)) state cur_loc = + let state = + if defs then defstruc_of_str state else struc_of_str state in horizon, adv_ratio, {game with Arena.struc = state; cur_loc = cur_loc} @@ -821,9 +829,8 @@ "connect4 simple" >:: (fun () -> - let state = update_game connect4_game -"[ | | - ] \" + let state = update_game ~defs:true connect4_game +"MODEL [ | | ] \" . . . . . . . @@ -836,7 +843,8 @@ P . . . . . . P Q Q +Q . . . -\"" 0 in +\" with DiagA (x, y) = ex u (R(x, u) and C(u, y)) ; + DiagB (x, y) = ex u (R(x, u) and C(y, u))" 0 in Game.use_monotonic := false; easy_case state 0 "should attack" (fun mov_s -> "Cross{1:a4}" = mov_s); @@ -845,9 +853,8 @@ "connect4 avoid losing" >:: (fun () -> - let state = update_game connect4_game -"[ | | - ] \" + let state = update_game ~defs:true connect4_game +"MODEL [ | | ] \" ... ... ... ... ... ... ... ... ... ... @@ -860,7 +867,8 @@ ... Q..P P.. ... ... ... ... ... Q..P P..P Q.. -\"" 0 in +\" with DiagA (x, y) = ex u (R(x, u) and C(u, y)) ; + DiagB (x, y) = ex u (R(x, u) and C(y, u))" 0 in Game.use_monotonic := false; hard_case state 0 "should not attack" (fun mov_s -> "Cross{1:f3}" <> mov_s); @@ -870,9 +878,8 @@ "connect4 endgame" >:: (fun () -> - let state = update_game connect4_game -"[ | | - ] \" + let state = update_game ~defs:true connect4_game +"MODEL [ | | ] \" . . . . . . . @@ -885,7 +892,8 @@ P . +Q Q . . . P P P Q Q . . -\"" 0 in +\" with DiagA (x, y) = ex u (R(x, u) and C(u, y)) ; + DiagB (x, y) = ex u (R(x, u) and C(y, u))" 0 in Game.use_monotonic := false; hard_case state 0 "should defend" (fun mov_s -> "Cross{1:e2}" = mov_s); @@ -957,7 +965,7 @@ let a () = match test_filter - ["Game:2:alpha_beta_ord-time 8 16 32:16:connect4 avoid losing"] + ["Game:1:alpha_beta_ord-effort 2 3 4:15:connect4 simple"] tests with | Some tests -> ignore (run_test_tt ~verbose:true tests) Modified: trunk/Toss/Server/ServerGDLTest.in =================================================================== --- trunk/Toss/Server/ServerGDLTest.in 2011-02-10 17:40:57 UTC (rev 1317) +++ trunk/Toss/Server/ServerGDLTest.in 2011-02-12 17:32:53 UTC (rev 1318) @@ -41,7 +41,7 @@ Content-type: text/acl Content-length: 41 -(PLAY MATCH.3316980891 ((MARK 2 1) NOOP)) +(PLAY MATCH.3316980891 ((MARK 1 1) NOOP)) POST / HTTP/1.0 Accept: text/delim @@ -50,7 +50,7 @@ Content-type: text/acl Content-length: 41 -(PLAY MATCH.3316980891 (NOOP (MARK 2 3))) +(PLAY MATCH.3316980891 (NOOP (MARK 3 2))) POST / HTTP/1.0 Accept: text/delim @@ -59,13 +59,4 @@ Content-type: text/acl Content-length: 41 -(PLAY MATCH.3316980891 ((MARK 3 3) NOOP)) - -POST / HTTP/1.0 -Accept: text/delim -Sender: GAMEMASTER -Receiver: GAMEPLAYER -Content-type: text/acl -Content-length: 41 - -(STOP MATCH.3316980891 (NOOP (MARK 1 1))) +(STOP MATCH.3316980891 ((MARK 3 3) NOOP)) Modified: trunk/Toss/Server/ServerGDLTest.out =================================================================== --- trunk/Toss/Server/ServerGDLTest.out 2011-02-10 17:40:57 UTC (rev 1317) +++ trunk/Toss/Server/ServerGDLTest.out 2011-02-12 17:32:53 UTC (rev 1318) @@ -17,7 +17,7 @@ Content-type: text/acl Content-length: 10 -(MARK 2 1) +(MARK 1 1) HTTP/1.0 200 OK Content-type: text/acl Content-length: 4 @@ -27,15 +27,10 @@ Content-type: text/acl Content-length: 10 -(MARK 1 2) +(MARK 3 3) HTTP/1.0 200 OK Content-type: text/acl Content-length: 4 -NOOP -HTTP/1.0 200 OK -Content-type: text/acl -Content-length: 4 - DONE ERR processing completed -- EOF Modified: trunk/Toss/Solver/Structure.ml =================================================================== --- trunk/Toss/Solver/Structure.ml 2011-02-10 17:40:57 UTC (rev 1317) +++ trunk/Toss/Solver/Structure.ml 2011-02-12 17:32:53 UTC (rev 1318) @@ -71,6 +71,10 @@ inv_names = IntMap.empty ; rel_signature = StringMap.empty ; } + +let rel_signature struc = + StringMap.fold (fun r ar si -> (r,ar)::si) + struc.rel_signature [] (* Return the list of relation tuples incident to an element [e] in [struc]. *) @@ -471,9 +475,11 @@ if StringMap.is_empty struc.rel_signature then "" else let s_str rel ar = rel ^ ": " ^ (string_of_int ar) in - (String.concat ", " (StringMap.fold - (fun rel ar acc -> s_str rel ar::acc) - struc.rel_signature [])) + let rel_structure struc = + StringMap.fold + (fun rel ar acc -> s_str rel ar::acc) + struc.rel_signature [] in + String.concat ", " (rel_structure struc) (* Print the structure [struc] as string, in extensive form (not using condensed representations like boards). *) Modified: trunk/Toss/Solver/Structure.mli =================================================================== --- trunk/Toss/Solver/Structure.mli 2011-02-10 17:40:57 UTC (rev 1317) +++ trunk/Toss/Solver/Structure.mli 2011-02-12 17:32:53 UTC (rev 1318) @@ -58,6 +58,7 @@ (** Return the list of functions. *) val f_signature : structure -> string list +val rel_signature : structure -> (string * int) list (** {2 Printing structures} *) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2011-02-10 17:41:03
|
Revision: 1317 http://toss.svn.sourceforge.net/toss/?rev=1317&view=rev Author: lukaszkaiser Date: 2011-02-10 17:40:57 +0000 (Thu, 10 Feb 2011) Log Message: ----------- Make payoff computation in terminal tree nodes faster (use tnf). Modified Paths: -------------- trunk/Toss/Solver/Solver.ml Modified: trunk/Toss/Solver/Solver.ml =================================================================== --- trunk/Toss/Solver/Solver.ml 2011-02-10 12:16:07 UTC (rev 1316) +++ trunk/Toss/Solver/Solver.ml 2011-02-10 17:40:57 UTC (rev 1317) @@ -304,7 +304,10 @@ (* Fast function to get a value of a real expression without free variables other than those assigned in [asg] explicitely. *) let rec get_real_val solver asg expr struc = - let check_fa = check_f struc asg in + let check_fa phi = (* check_f struc asg phi in *) + if FormulaOps.free_vars phi = [] then + (eval_cache_sentences solver struc phi) <> Empty + else check_f struc asg phi in match expr with Char phi -> if check_fa phi then 1. else 0. | Const v -> v This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2011-02-10 12:16:14
|
Revision: 1316 http://toss.svn.sourceforge.net/toss/?rev=1316&view=rev Author: lukstafi Date: 2011-02-10 12:16:07 +0000 (Thu, 10 Feb 2011) Log Message: ----------- GDL translation work in progress: game rules fully translated into Toss semantics (but not generated yet, only as precondition + update). Modified Paths: -------------- trunk/Toss/GGP/GDL.ml trunk/Toss/GGP/GDL.mli trunk/Toss/GGP/GDLTest.ml trunk/Toss/Play/GameTest.ml Modified: trunk/Toss/GGP/GDL.ml =================================================================== --- trunk/Toss/GGP/GDL.ml 2011-02-09 03:37:28 UTC (rev 1315) +++ trunk/Toss/GGP/GDL.ml 2011-02-10 12:16:07 UTC (rev 1316) @@ -154,6 +154,8 @@ duplication turns out prohibitive, this will be a huge TODO for this translation framework.) + First, we expand all uses of the built-in "role" predicate. + (6a) The definition: [(r, params1) <= body1 ... (r, params_n) <= body_n] @@ -190,14 +192,14 @@ eliminating the [params] (rather than the [args]) when possible. Still, we freshen each [vars_i] to avoid capture. We remember the (uneliminated) [vars_i] in the set of variables - quantified under the negation. If unification fails, we drop the - corresponding negated subformula. If unification succeeds but the - corresponding [body_i] is empty (and, in general, no other - disjuncts in the negated subformula are left), we drop the branch. + quantified existentially under the negation (since the free + variables occurring only under the negation are quantified + universally there -- it is a positive position). If unification + fails, we drop the corresponding negated subformula. If + unification succeeds but the corresponding [body_i] is empty (and, + in general, no other disjuncts in the negated subformula are + left), we drop the branch. - (6b1) The general case is not implemented yet since it slightly - complicates the code, and expressivity gain is very small. - (7) Generation of rewrite rules when the dynamic relations are not recursive and are expanded in the GDL definition. @@ -212,6 +214,9 @@ associated with a single "lead legal" branch of the location's player. + (7a1) Filter "lead legal" rules by satisfiability in the current + location plys of the aggregate playout. + (7b) We collect all the branches of the "next" relation definition for which the selected branches of "lead legal" and "noop legal" (the "joint legal" actions) unify with all (usually one, but we @@ -274,7 +279,10 @@ disjunct, place the original "next" atom but with meta-variable positions replaced by _BLANK_ as the head of the "erasure" branch, apply (and remove) unification atoms resulting from negating the - "distinct" relation. + "distinct" relation. The local variables of newly created negated + subformulas become existentially-quantified-under-negation + (i.e. universally quantified) (while the local variables of old + negated subformulas are "let free"). (7f4) Drop the erasure branches that contradict the "legal" condition of their rule. @@ -293,30 +301,43 @@ GDL-originals of branches (so to use GDL atoms for "subsumption checking" in (7l)). + (7i-7k) Variables corresponding to negated "true" atoms + that contain locally existentially quantified variables are + quantified universally (with a scope containing all their + occurrences). + + Implementation: we only introduce universal quantification after + filtering (7m), is it OK? + (7i-4a) For all subterms of "next" and "true" atoms, identify the sets of <mask-path, element variable> they "inhabit". Replace a static fact relation by relations built over a cartesian product of <mask-path, element variable> sets derived for each static fact's argument by applying corresponding (4a) relations. For a - negative literal generate result equivalent to a conjunction of - negations of generated atoms (FIXME: why disjunction is wrong?). + negative literal generate result equivalent to a *conjunction* of + negations of generated atoms, but deferred to (7k) to fall under a + common disjunction (unless there's only one disjunct). (7i-4c) Include the (4c) relations for "next" and "true" positive - atoms. Negative atoms are added with (5) relations since they are - under a common negation. + atoms. Negative atoms are added with (5) relations since they (the + (5) predicates and the mask-path anchors of (4c)) are under a + common negation. (7i-4b) Add an appropriate equality relation of (4b) for each case - of variable shared by terms corresponding to different element + of subterm shared by terms corresponding to different element variables (regardless if the element terms are in positive or - negative literals). FIXME: any shared subterm, not limited to - variables, right? + negative literals). Implementation: instead of all subterms we currently only consider subterms that instantiate (ordinary) variables in the mask corresponding to the "next"/"true" atom. + Reason for unsoundness: inclusion of negative "true" literals in + (4b) relations is a necessary "heuristic". Whether to extend it to + constant subterms (see above) is not clear. + (7i1) Remove branches that are unsatisfiable by their static - relations (4a), (4b) and (4c) alone. + relations (4a), (4b) and (positive) (4c) alone. (7j) Identify variables in "next" & "true" terms that are at-or-below meta-variables in the corresponding mask. (Most of @@ -326,11 +347,14 @@ position). (Note that since branches do not have unfixed variables anymore, we do not rename variables during duplication.) + Implementation: TODO. + (7k) Replace the "next" and "true" atoms by the conjunction of (4c) and (5) predicates over their corresponding variable. (For negative "true" literals this will be equivalent to a disjunction of negations of the predicates.) Note that positive static - relations are already added in (7i-4c). + relations are already added in (7i-4c). Handle negative literal + translations of (4a, 4c, 5) together. (7l) Build a pre-lattice of branch bodies w.r.t. subsumption, in a manner similar to (7b). The subsumption test has to say "no" @@ -351,8 +375,17 @@ associate the set of branches that do not allow such literal. For every vector we calculate the complement of the sum of branch sets associated with every bit. The unique resulting sets are exactly - the Toss rules precursors. + the Toss rules precursors. Heuristic (FIXME: needed?): We only use + atoms that are deterministically present or absent in at least + some branch for indexing. + (7l2) Filter rule candidates so that each has a "does"-specific + branch. + + (7l3) Filter out rule candidates that contradict all states + from the current location plys of aggregate playout (by their + "true" atoms -- "not true" are not valid in the aggregate playout). + (7m) Filter the final rule candidates by satisfiability of the static part (same as (7i1) conjoined). @@ -362,6 +395,9 @@ branches with unifiers more general than the equiv class, and from the disjointness conditions and the terminal condition.) + (7n1) Prior to translation, expand all variables under + meta-variables in "terminal" branches, as in (7j). Implementation TODO. + The rewrite rule is generated by joining the derived conjunctions from "next" atoms as RHS, and from bodies as the precondition. Exactly the RHS variables are listed in the LHS @@ -481,9 +517,10 @@ type gdl_atom = string * term list type gdl_rule = gdl_atom * gdl_atom list * gdl_atom list (* Definition with expanded definitions: expansion of a negated - relation brings negated conjunctions. *) + relation brings negated (possibly locally existentially quantified) + conjunctions. *) type exp_def_branch = - term list * gdl_atom list * gdl_atom list list + term list * gdl_atom list * (Aux.Strings.t * gdl_atom list) list type exp_def = string * exp_def_branch list @@ -493,8 +530,11 @@ struct type t = string * term list let compare = Pervasives.compare end) (* -let branch_vars (args, body, neg_body) = + let branch_vars (args, body, neg_body) = *) +let rels_vars body = + List.fold_left Aux.Strings.union Aux.Strings.empty + (List.map (fun (_,args)->terms_vars args) body) let rules_of_entry = function | Datalog (rel, args, body) -> @@ -542,10 +582,19 @@ head, pos_body, neg_body) bodies | Atomic (rel, args) -> [(rel, args), [], []] -let defs_of_rules rules : (string * exp_def_branch list) list = +let add_neg_body_vars global_vars neg_body = + List.map (fun (_, args as a)-> + let local_vs = Aux.Strings.diff (terms_vars args) global_vars in + local_vs, [a]) neg_body + +let defs_of_rules rules + : (string * exp_def_branch list) list = Aux.map_reduce (fun ((drel, params), body, neg_body) -> - drel,(params, body, List.map (fun a->[a]) neg_body)) + let global_vs = + Aux.Strings.union (terms_vars params) (rels_vars body) in + drel,(params, body, + add_neg_body_vars global_vs neg_body)) (fun x y->y::x) [] rules (* Only use [rules_of_defs] when sure that no multi-premise negative @@ -554,7 +603,7 @@ Aux.concat_map (fun (rel, branches) -> List.map (fun (args, body, neg_body) -> let neg_body = - List.map (function [a]->a | _ -> assert false) neg_body in + List.map (function _,[a]->a | _ -> assert false) neg_body in (rel, args), body, neg_body) branches) defs (* Stratify either w.r.t. the dependency graph ([~def:true]) or its @@ -563,11 +612,12 @@ match List.partition (fun (_, branches) -> List.for_all (fun (_, body, neg_body) -> + let neg_bodies = List.concat (List.map snd neg_body) in List.for_all (fun (rel1,_) -> rel1 = "distinct" || rel1 = "true" || rel1 = "does" || not (List.mem_assoc rel1 defs)) - (if def then body @ List.concat neg_body - else List.concat neg_body)) branches) defs + (if def then body @ neg_bodies + else neg_bodies)) branches) defs with | [], [] -> (* {{{ log entry *) @@ -615,6 +665,7 @@ | Func (f, args) -> Func (f, List.map (subst_one sb) args) +(* Eliminate [terms1] variables when possible. *) let rec unify sb terms1 terms2 = match terms1, terms2 with | [], [] -> sb @@ -715,6 +766,10 @@ if rel1 = rel2 then unify [] args1 args2 else raise Not_found +let unifies term1 term2 = + try ignore (unify [] [term1] [term2]); true + with Not_found -> false + let subst_rel sb (rel, args) = rel, List.map (subst sb) args let subst_rels sb body = List.map (subst_rel sb) body let extend_sb sb1 sb = Aux.map_prepend sb1 (fun (x,t)->x, subst sb1 t) sb @@ -727,8 +782,8 @@ let subst_br sb (head, body, neg_body) = List.map (subst sb) head, - List.map (subst_rel sb) body, - List.map (List.map (subst_rel sb)) neg_body + subst_rels sb body, + List.map (fun (uni_vs,neg) -> uni_vs, subst_rels sb neg) neg_body let fact_str (rel, args) = "("^rel^" "^String.concat " " (List.map term_str args) ^")" @@ -738,26 +793,42 @@ "("^String.concat " " (List.map term_str tup) ^")" in String.concat " " (List.map tup_str tups) +let terms_str facts = + String.concat ", " (List.map term_str facts) + let facts_str facts = String.concat " " (List.map fact_str facts) let neg_facts_str negs = String.concat " " - (List.map (fun d -> "(not (and "^facts_str d^"))") negs) + (List.map (fun (vs,d) -> + let vs = Aux.Strings.elements vs in + let q = if vs = [] then "" + else "forall "^String.concat ", " vs in + q ^ "(not (and "^facts_str d^"))") negs) +let branch_str rel (args, body, neg_body) = + "("^ fact_str (rel, args) ^ " <= " ^ facts_str body ^ + " " ^ neg_facts_str neg_body ^ ")" + let def_str (rel, branches) = String.concat "\n" (List.map (fun (args, body, neg_body) -> "("^ fact_str (rel, args) ^ " <= " ^ facts_str body ^ " " ^ neg_facts_str neg_body ^ ")" ) branches) - -let rule_pretransl_str (heads, bodies, neg_bodies) = - "("^ facts_str bodies ^ - " " ^ neg_facts_str neg_bodies ^ "==>" ^ - String.concat "; " (List.map term_str heads) ^ ")" - +(* +let rule_str (head, body, neg_body) = + String.concat "\n" (List.map (fun (args, body, neg_body) -> + "("^ fact_str (rel, args) ^ " <= " ^ facts_str body ^ + " " ^ String.concat " " + (List.map (fun f->"not "^fact_str f) neg_body) ^ ")" + ) branches) +*) let sb_str sb = String.concat ", " (List.map (fun (v,t)->v^":="^term_str t) sb) +let proto_rel_str (rel, args) = + rel ^"(" ^ String.concat ", " (Array.to_list args) ^")" + (* 1b *) (* TODO: optimize by using rel-indexing (also in [aggregate_playout]). @@ -884,9 +955,14 @@ Func (f, List.map map_vnames args) in let map_rel (rel, args) = rel, List.map map_vnames args in + let map_neg (vs, atoms) = + Aux.strings_of_list + (List.map (fun x-> x^string_of_int !freshen_count) + (Aux.Strings.elements vs)), + List.map map_rel atoms in List.map map_vnames args, List.map map_rel body, - List.map (List.map map_rel) neg_body + List.map map_neg neg_body let freshen_def_branches = List.map freshen_branch @@ -917,7 +993,8 @@ let sb1 = unify [] dparams args in Some ( subst_rels sb1 (dbody @ pos_sol), - List.map (subst_rels sb1) (dneg_body @ neg_sol), + List.map (fun (vs,bs)->vs, subst_rels sb1 bs) + (dneg_body @ neg_sol), extend_sb sb1 sb) with Not_found -> None ) def @@ -928,32 +1005,46 @@ ([[],[],[]]) body in (* 6b *) let sols = - List.fold_left (fun sols -> function [rel, args as atom] -> - (let try def = - freshen_def_branches (List.assoc rel defs) in - List.map (fun (pos_sol, neg_sol, sb) -> - let args = List.map (subst sb) args in - let more_neg = - Aux.map_some (fun (dparams, dbody, dneg_body) -> - if dneg_body <> [] then - failwith - ("GDL.subst_def_branch: negation in negatively used" ^ - " defined rels not supported yet, relation "^rel); - try - let sb1 = unify [] dparams args in - Some (subst_rels sb1 dbody) - with Not_found -> None - ) def in - pos_sol, more_neg @ neg_sol, sb - ) sols - with Not_found -> - List.map (fun (pos_sol, neg_sol, sb) -> - pos_sol, [subst_rel sb atom]::neg_sol, sb) sols) - | _ -> failwith - "GDL.subst_def_branch: unimplemented, see (6b1) of spec") - sols neg_body in + (* no branch duplication, but each negation has its own substitution *) + List.map (fun (pos_sol, neg_sol, sb) -> + let more_neg_sol = + Aux.concat_map (fun (uni_vs, neg_conjs) -> + (* negated subformulas are duplicated instead *) + List.fold_left (fun neg_sol (rel, args as atom) -> + (let try def = + freshen_def_branches (List.assoc rel defs) in + Aux.concat_map (fun (uni_vs, neg_acc, sb) -> + let args = List.map (subst sb) args in + Aux.map_try (fun (dparams, dbody, dneg_body) -> + if dneg_body <> [] then + failwith + ("GDL.subst_def_branch: negation in negatively used" ^ + " defined rels not supported yet, relation "^rel); + (let sb1 = unify [] dparams args in + let param_vars = terms_vars dparams in + let body_vars = rels_vars dbody in + let dbody = subst_rels sb1 dbody in + let local_vs = + Aux.Strings.inter (Aux.Strings.diff body_vars param_vars) + (rels_vars dbody) in + let neg_acc = subst_rels sb1 neg_acc in + Aux.Strings.union uni_vs local_vs, + dbody @ neg_acc, + extend_sb sb1 sb) + ) def) neg_sol + with Not_found -> (* rel not in defs *) + List.map (fun (uni_vs, neg_acc, sb) -> + uni_vs, subst_rel sb atom::neg_acc, sb) neg_sol) + ) [uni_vs, [], sb] neg_conjs + ) neg_body in + let more_neg_sol = + List.map (fun (uni_vs, neg_conjs,_) -> uni_vs, neg_conjs) + more_neg_sol in + List.rev pos_sol, List.rev_append neg_sol more_neg_sol, sb + ) sols in Aux.map_some (fun (pos_sol, neg_sol, sb) -> - if List.mem [] neg_sol then None + if List.exists (function _,[] -> true | _ -> false) neg_sol + then None else Some (List.map (subst sb) head, pos_sol, neg_sol)) sols (* Stratify and expand all relations in the given set. *) @@ -991,25 +1082,29 @@ (legal_args, legal_body, legal_neg_body : exp_def_branch) (head, body, neg_body : exp_def_branch) : (exp_def_branch * exp_def_branch) option = - if List.exists (List.exists (fun (rel,_)->rel="does")) neg_body + if List.exists (fun (_,neg_conjs) -> + List.exists (fun (rel,_)->rel="does") neg_conjs) neg_body then failwith "GDL.translate_game: negated \"does\" conditions not implemented yet"; try let body, more_neg_body, sb = List.fold_left (fun (body,more_neg_body,sb) (rel, args as atom) -> if rel = "does" then - List.rev_append legal_body body, + ("_DOES_PLACEHOLDER_", args) :: List.rev_append legal_body body, List.rev_append legal_neg_body more_neg_body, unify sb legal_args args else atom::body, more_neg_body, sb) ([],[],[]) body in - Some ( (List.map (subst sb) legal_args, - List.map (subst_rel sb) legal_body, - List.map (List.map (subst_rel sb)) legal_neg_body), + subst_rels sb legal_body, + List.map (fun (uni_vs,neg_conjs) -> + (* local variables so cannot be touched *) + uni_vs, subst_rels sb neg_conjs) + legal_neg_body), (List.map (subst sb) head, - List.map (subst_rel sb) (List.rev body), - List.map (List.map (subst_rel sb)) + subst_rels sb (List.rev body), + List.map (fun (uni_vs, neg_conjs) -> + uni_vs, subst_rels sb neg_conjs) (List.rev_append more_neg_body neg_body))) with Not_found -> None @@ -1072,21 +1167,17 @@ else dynamic_rules in let rec loop actions_accu state_accu step state = (* {{{ log entry *) - if !debug_level > 0 then ( Printf.printf "aggregate_playout: step %d...\n%!" step ); - (* }}} *) (let try actions, next = aggregate_ply players static_base state state_rules in (* {{{ log entry *) - if !debug_level > 0 then ( Printf.printf "aggregate_playout: state %s\n%!" (String.concat " " (List.map term_str next)) ); - (* }}} *) if step < horizon then loop (actions::actions_accu) (state::state_accu) (step+1) next @@ -1183,9 +1274,9 @@ let mask, _, _, blank = term_to_blank masks term in mask, Formula.fo_var_of_string (term_to_name blank) -let translate_branches struc masks static_rnames dyn_rels brs = +let translate_branches struc masks static_rnames dyn_rels + (brs : exp_def_branch list) = (* 7i *) - (* Do not flatten the already built super-partition. *) let state_terms = List.fold_left (fun acc -> function | [next_arg], body, neg_body -> @@ -1195,16 +1286,29 @@ | "true", _ -> assert false | _ -> acc) acc body in let res = - List.fold_left (List.fold_left (fun acc -> function - | "true", [true_arg] -> Terms.add true_arg acc - | "true", _ -> assert false - | _ -> acc)) res neg_body in - if next_arg = Const "_TERMINAL_" + List.fold_left (fun acc (_, neg_conjs) -> + List.fold_left (fun acc -> function + | "true", [true_arg] -> Terms.add true_arg acc + | "true", _ -> assert false + | _ -> acc) acc neg_conjs) res neg_body in + if next_arg = Const "_IGNORE_RHS_" then res else Terms.add next_arg res | _ -> assert false ) Terms.empty brs in let state_terms = Terms.elements state_terms in + let uni_gdl_vars = + List.fold_left (fun acc (_, _, neg_body) -> + Aux.Strings.union acc + (List.fold_left Aux.Strings.union Aux.Strings.empty + (List.map fst neg_body)) + ) Aux.Strings.empty brs in + let uni_toss_vars = + Aux.map_some (fun term -> + if Aux.Strings.is_empty + (Aux.Strings.inter uni_gdl_vars (term_vars term)) + then None + else Some (snd (toss_var masks term))) state_terms in (* {{{ log entry *) if !debug_level > 2 then ( Printf.printf "state_terms: %s\n%!" ( @@ -1220,7 +1324,7 @@ let ptups = List.map (fun arg -> Aux.assoc_all arg state_subterms) args in (* {{{ log entry *) - if !debug_level > 3 then ( + if !debug_level > 4 then ( Printf.printf "conjs_4a: of %s = subterms %s\n%!" (fact_str (rel,args)) (String.concat "; " ( List.map (fun l -> String.concat ", " @@ -1238,7 +1342,7 @@ Formula.Rel (rname, Array.of_list tup)) ptups in let res = Aux.unique_sorted res in (* {{{ log entry *) - if !debug_level > 3 then ( + if !debug_level > 4 then ( Printf.printf "conjs_4a: of %s = %s\n%!" (fact_str (rel,args)) (Formula.str (Formula.And res)) ); @@ -1267,7 +1371,7 @@ let brs = Aux.map_some (function | [next_arg],body,neg_body -> let phi, lvars = - if next_arg = Const "_TERMINAL_" then [], ref [] + if next_arg = Const "_IGNORE_RHS_" then [], ref [] else let mask, sb, m_sb, blanked = term_to_blank masks next_arg in let rname = term_to_name mask in @@ -1297,35 +1401,20 @@ conjs_4a rel args else [] ) body in + (* only to prune early *) let neg_conjs = - Aux.concat_map ( - Aux.concat_map (fun (rel, args) -> - if rel = "true" then - (* lvars := svar :: !lvars; ??? *) - (* negated (4c) is calculated together with (5) *) - [] - (* - let true_arg = List.hd args in - let mask, sb, m_sb, blanked = term_to_blank masks true_arg in - let rname = term_to_name mask in - let _, svar = toss_var masks true_arg in - let phi = Formula.Rel (rname, [|svar|]) in - let conjs = - Aux.map_some (function - | _, Var _ -> None - | v, t as v_sb -> - let rname = term_to_name (subst_one v_sb mask) in - Some (Formula.Rel (rname, [|svar|]))) sb in - (* FIXME: make sure it's the right semantics *) - [phi; Formula.Not (Formula.And/Or conjs)] - *) + Aux.concat_map (function + | _, [rel, args] -> + if rel = "true" then [] + else if rel = "_DOES_PLACEHOLDER_" + then [] else if List.mem rel static_rnames then - (* 7i-4a *) - (* FIXME: And / Or semantics? *) + (* 7i-4a *) List.map (fun c -> Formula.Not c) (conjs_4a rel args) - (* [Formula.Not (Formula.And (conjs_4a rel args))] *) - else [] - )) neg_body in + else + (* dynamic relations have been expanded *) + assert false + | _ -> []) neg_body in let all_conjs = phi @ conjs @ neg_conjs in let phi = Formula.And all_conjs in let lvars = (!lvars :> Formula.var list) in @@ -1335,6 +1424,7 @@ let rphi = Solver.M.register_formula (Formula.And optim_conjs) in (* {{{ log entry *) + if !debug_level > 4 then ( (* do not print, because it generates too many answers -- too little constraints per number of @@ -1350,11 +1440,12 @@ (Formula.str phi) (* (List.length atups) *) ); + (* }}} *) if Solver.M.check_formula struc rphi then ( (* {{{ log entry *) - if !debug_level > 3 then ( + if !debug_level > 4 then ( Printf.printf "holds\n%!" ); (* }}} *) @@ -1367,7 +1458,7 @@ let brs = List.map (fun (static_conjs, (next_arg,body,neg_body)) -> let rhs_pos_preds, rhs_possneg_preds = - if next_arg = Const "_TERMINAL_" then [], [] + if next_arg = Const "_IGNORE_RHS_" then [], [] else let mask, sb, m_sb, blanked = term_to_blank masks next_arg in let rhs_elem = term_to_name blanked in @@ -1404,7 +1495,7 @@ let lhs_possneg_preds = List.flatten lhs_possneg_preds in *) lhs_pos_preds - else if List.mem rel static_rnames + else if List.mem rel static_rnames || rel = "_DOES_PLACEHOLDER_" then [] else ( Printf.printf "\nunexpected_dynamic: %s\n%!" rel; @@ -1412,42 +1503,86 @@ assert false) ) body in let neg_conjs = - Aux.concat_map ( - Aux.concat_map (fun (rel, args) -> - if rel = "true" then - let true_arg = List.hd args in - let mask, sb, m_sb, blanked = term_to_blank masks true_arg in - let rname = term_to_name mask in - let _, svar = toss_var masks true_arg in - let phi = Formula.Rel (rname, [|svar|]) in - let conjs_4c = - Aux.map_some (function - | _, Var _ -> None - | v, t as v_sb -> - let rname = term_to_name (subst_one v_sb mask) in - Some (Formula.Rel (rname, [|svar|]))) sb in - let conjs_5 = - List.map (fun (v,t as v_sb) -> - if t = Const "_BLANK_" then - assert false - else - (* t = Var _ have been expanded *) - let rname = term_to_name (subst_one v_sb mask) in - Formula.Rel (rname, [|svar|])) m_sb in + Aux.map_some (fun (_, neg_conjs) -> + let disjs = + Aux.map_some (fun (rel, args) -> + if rel = "true" then + let true_arg = List.hd args in + let mask, sb, m_sb, blanked = term_to_blank masks true_arg in + let rname = term_to_name mask in + let _, svar = toss_var masks true_arg in + let phi = Formula.Rel (rname, [|svar|]) in + let conjs_4c = + Aux.map_some (function + | _, Var _ -> None + | v, t as v_sb -> + let rname = term_to_name (subst_one v_sb mask) in + Some (Formula.Rel (rname, [|svar|]))) sb in + let conjs_5 = + List.map (fun (v,t as v_sb) -> + if t = Const "_BLANK_" then + assert false + else + (* t = Var _ have been expanded *) + let rname = term_to_name (subst_one v_sb mask) in + Formula.Rel (rname, [|svar|])) m_sb in - (* FIXME: make sure it's the right semantics *) - [phi; Formula.Not (Formula.And (conjs_4c @ conjs_5))] - else if List.mem rel static_rnames - then [] - else - (* dynamic relations have been expanded *) - assert false - )) neg_body in + (* FIXME: make sure it's the right semantics *) + Some (Formula.Not (Formula.And (phi :: conjs_4c @ conjs_5))) + else if rel = "_DOES_PLACEHOLDER_" + then None + else if List.mem rel static_rnames then + (* 7i-4a *) + Some (Formula.And ( + List.map (fun c -> Formula.Not c) (conjs_4a rel args))) + else + (* dynamic relations have been expanded *) + assert false + ) neg_conjs in + match disjs with + | [] -> None + | [disj] -> Some disj + | _ -> Some (Formula.Or disjs)) neg_body in let all_conjs = static_conjs @ dyn_conjs @ neg_conjs in (rhs_pos_preds, rhs_possneg_preds, static_conjs, all_conjs), (next_arg, body, neg_body)) brs in - conjs_4b, brs + uni_toss_vars, conjs_4b, brs + +let lift_universal (uni_vars : Formula.fo_var list) conjs = + let rec flatten_ands = function + | Formula.And conjs -> Aux.concat_map flatten_ands conjs + | phi -> [phi] in + let conjs = Aux.unique_sorted (Aux.concat_map flatten_ands conjs) in + (* {{{ log entry *) + if !debug_level > 2 then ( + Printf.printf "lift_universal: vars %s -- conjs:\n%s\n%!" + (String.concat ", " + (List.map Formula.var_str (uni_vars :> Formula.var list))) + (Formula.sprint (Formula.And conjs)) + ); + (* }}} *) + let uni_vars = (uni_vars :> Formula.var list) in + let local, global = List.partition + (fun phi -> + let phi_vs = FormulaOps.free_vars phi in + List.exists (fun v -> List.mem v phi_vs) uni_vars) conjs in + let used_uni_vars = + List.filter (fun v -> List.mem v uni_vars) + (FormulaOps.free_vars (Formula.And local)) in + let res = + if local = [] then Formula.And global + else + Formula.And (global @ [ + Formula.All (used_uni_vars, Formula.And local)]) in + (* {{{ log entry *) + if !debug_level > 2 then ( + Printf.printf "lift_universal: result\n%s\n%!" + (Formula.sprint res) + ); + (* }}} *) + res + let translate_game game_descr = freshen_count := 0; let player_terms = @@ -1539,6 +1674,34 @@ done; loc_noops in (* 6 *) + let expand_roles rules = + Aux.concat_map (fun (head, body, neg_body as br) -> + let roles, body = + List.partition (fun (rel,_)->rel="role") body in + let neg_roles, neg_body = + List.partition (fun (rel,_)->rel="role") neg_body in + let pterms = Array.to_list player_terms in + let vs, roles = + Aux.partition_map + (function _,[Var v] -> Aux.Left v | _,[p] -> Aux.Right p + | _ -> assert false) roles in + let neg_roles = List.map (function _,[p] -> p + | _ -> assert false) neg_roles in + if List.exists (fun p -> not (List.mem p pterms)) roles + || List.exists (fun p -> List.mem p pterms) neg_roles + then [] + else if vs = [] then [br] + else + let sbs = Aux.product (List.map (fun _ -> pterms) vs) in + List.map (fun sb -> + let sb = List.combine vs sb in + subst_rel sb head, + subst_rels sb body, + subst_rels sb neg_body) sbs + ) rules in + let static_rules = (* Aux.unique_sorted *) (expand_roles static_rules) + and dynamic_rules = (* Aux.unique_sorted *) (expand_roles dynamic_rules) in + let static_rules, exp_static_rules = List.partition (fun ((rel,args), _, _) -> List.length args <= !expand_arity_above || @@ -1562,6 +1725,7 @@ (defs_of_rules static_rules)) in let exp_defs = expand_def_rules ~more_defs:static_exp_defs dynamic_rules in + (* {{{ log entry *) if !debug_level > 0 then ( Printf.printf "translate_game: All expanded dynamic rules:\n%s\n%!" @@ -1593,7 +1757,8 @@ ("GDL.initialize_game: invalid arity of \"true\" atom")) | _ -> None) in let pos_cands = collect body in - let neg_cands = Aux.concat_map collect neg_body in + let neg_cands = + Aux.concat_map (fun (_,neg) -> collect neg) neg_body in let pos_gens = List.map (generalize next_arg) pos_cands in let neg_gens = List.map (generalize next_arg) neg_cands in (* using the fact that Pervasives.compare is lexicographic *) @@ -1818,8 +1983,8 @@ (Array.map (fun player -> let sb = [v, player] in [player; subst sb lterm], - List.map (subst_rel sb) body, - List.map (List.map (subst_rel sb)) neg_body) + subst_rels sb body, + List.map (fun (uni_vs,neg) -> uni_vs, subst_rels sb neg) neg_body) player_terms) | [Func _; lterm], _, _ -> (* TODO: easy to fix *) @@ -1851,9 +2016,9 @@ && loc_noop_legal.(i).(p) <> Some legal then ( Printf.printf "Multiple noops: %s, %s\n%!" - (term_str (Func ("legal", Aux.fst3 legal))) - (term_str (Func ("legal", Aux.fst3 - (Aux.unsome loc_noop_legal.(i).(p))))); + (branch_str "legal" legal) + (branch_str "legal" + (Aux.unsome loc_noop_legal.(i).(p))); assert false) else loc_noop_legal.(i).(p) <- Some legal done @@ -1861,6 +2026,43 @@ | _ -> assert false ) legal_rules; loc_lead_legal, loc_noop_legal in + let agg_actions = Array.of_list agg_actions in + (* 7a1 *) + let loc_lead_legal = Array.mapi (fun i legals -> + let loc_actions = ref [] in + Array.iteri (fun ply actions -> + if ply mod loc_n = i then + loc_actions := actions @ !loc_actions) agg_actions; + (* {{{ log entry *) + if !debug_level > 4 then ( + Printf.printf "Possible actions in location %d:\n%s\n%!" + i (String.concat "; " + (List.map (fun a -> term_str (Func ("legal", a))) !loc_actions)) + ); + (* }}} *) + let matches head = + List.exists (fun action -> + try ignore (match_meta [] [] action head); true + with Not_found -> false) !loc_actions in + let res = List.filter (fun (head, _, _) -> matches head) legals in + (* {{{ log entry *) + if !debug_level > 3 then ( + Printf.printf "Filtered actions in location %d:\n%s\n\n%!" + i (String.concat "; " + (List.map (fun (a,_,_) -> term_str (Func ("legal", a))) res)) + ); + (* }}} *) + res + ) loc_lead_legal in + (* {{{ log entry *) + if !debug_level > 2 then ( + Printf.printf "Lead actions in locations:\n%!"; + Array.iteri (fun i lead -> + Printf.printf "loc: %d -- %s\n%!" i ( + String.concat "; " + (List.map (fun a -> branch_str "legal" a) lead))) loc_lead_legal + ); + (* }}} *) (* the joint actions available in a location *) let loc_joint_legal = Array.mapi (fun i lead -> @@ -1876,6 +2078,7 @@ ) loc_lead_legal in (* 7b *) let grtr ((lead1,_,_), _) ((lead2,_,_), _) = cmp_masks lead2 lead1 in + let agg_states = Array.of_list agg_states in let loc_next_classes = Array.mapi (fun loc joint_legal_branches -> Aux.concat_map (fun joint_legal -> @@ -1924,7 +2127,7 @@ done; let layers = List.rev !layers in (* 7d *) - let rules_brs = List.fold_left + let rules_brs : ('a * exp_def_branch list) list = List.fold_left (* folding reverses order so the maximal layer will generate the returned classes *) (fun rules_brs layer -> @@ -1988,13 +2191,14 @@ let multi_body = List.map (fun (head2, body2, neg_body2) -> let sb, _ = match_meta [] [] head head2 in - List.map (subst_rel sb) body2, - List.map (List.map (subst_rel sb)) neg_body2 + subst_rels sb body2, + List.map (fun (uni_vs,neg) -> + uni_vs, subst_rels sb neg) neg_body2 ) f_brs in head, (body, neg_body)::multi_body ) frames in (* 7f3 *) - let erasure_brs = Aux.concat_map + let erasure_brs : exp_def_branch list = Aux.concat_map (function | [next_arg] as next_args,multi_body -> let mask, _, _, blank_arg = term_to_blank masks next_arg in @@ -2024,8 +2228,8 @@ let neg_body = List.map (function - | ["distinct", []] -> assert false - | ["distinct", arg::more_args] -> + | _, ["distinct", []] -> assert false + | _, ["distinct", arg::more_args] -> let _, sb = List.fold_left (fun (base, sb) arg -> let sb = unify sb [base] [arg] in @@ -2038,9 +2242,9 @@ -> v2, Var v1 | vsb -> vsb) sb in Aux.Right (Aux.Right sb) - | conj when List.mem_assoc "distinct" conj -> + | _, conj when List.mem_assoc "distinct" conj -> assert false - | conj -> + | _, conj -> Aux.Right (Aux.Left conj)) neg_body in body @ neg_body) multi_body in @@ -2057,8 +2261,13 @@ then None else let body = List.map (subst_rel sb) body in + let global_vs = + Aux.Strings.union ( + Aux.Strings.union (term_vars next_arg) + (rels_vars body)) fixed_vars in let neg_body = - List.map (fun a -> [subst_rel sb a]) neg_body in + add_neg_body_vars global_vs + (subst_rels sb neg_body) in let head = subst sb blank_arg in if (* TODO: (7g) instead *) @@ -2066,9 +2275,10 @@ fixed_vars && (* (7f4) *) not (List.exists (fun pos -> - List.mem [pos] lead_neg_body + List.exists (fun (_,neg_conjs) -> + List.mem pos neg_conjs) lead_neg_body ) body) && - not (List.exists (fun neg -> + not (List.exists (fun (_,neg) -> List.for_all (fun neg->List.mem neg lead_body) neg ) neg_body) @@ -2108,31 +2318,67 @@ let loc_toss_rules = Array.mapi (fun loc rules_brs -> Aux.concat_map (fun (lead, brs) -> - let conjs_4b, brs = - translate_branches struc masks static_rnames dyn_rels brs in - - (* 7l *) + (* we build synthetic branches so as to get a proper partition *) let atoms = - List.fold_left (fun acc (_,(_,body,neg_body))-> + List.fold_left (fun acc (_,body,neg_body)-> List.fold_right Atoms.add body - (List.fold_right (List.fold_right Atoms.add) - neg_body acc) + (List.fold_right (function + | _, [neg] -> Atoms.add neg + | _ -> fun x -> x) neg_body acc) ) Atoms.empty brs in let atoms = Atoms.elements atoms in + let atoms = List.filter + (fun (rel,_)->rel<>"_DOES_PLACEHOLDER_") atoms in + let synth_brs = Aux.concat_map (fun atom -> + (* so that RHS are ignored *) + [[Const "_IGNORE_RHS_"], [atom], []; + [Const "_IGNORE_RHS_"], [], [Aux.Strings.empty, [atom]]] + ) atoms in + let uni_vars, conjs_4b, brs = + translate_branches struc masks static_rnames dyn_rels + (brs @ synth_brs) in + + (* 7l *) let brs = Array.of_list brs in (* indexing branches *) let full_set = Aux.ints_of_list (Array.to_list (Array.mapi (fun i _ -> i) brs)) in + (* 7l2 *) + let does_set = Aux.ints_of_list + (Aux.map_some (fun x->x) + (Array.to_list (Array.mapi (fun i (_,(_,body,_)) -> + if List.exists ( + function + | "_DOES_PLACEHOLDER_",args -> + (try ignore ( + unify [] [loc_players.(loc); Aux.fst3 lead] + args); true + with Not_found -> false) + | _ -> false) body + then Some i else None) brs))) in + let brs = Array.map (fun (lead,(head,body,neg_body))-> + let body = List.filter ( + function "_DOES_PLACEHOLDER_",_ -> false | _ -> true) body in + lead, (head, body, neg_body)) brs in let table = List.map (fun atom -> let positives = Array.mapi (fun i (_,(_,body,_)) -> if List.mem atom body then Some i else None) brs in let positives = Aux.map_some (fun x->x) (Array.to_list positives) in let negatives = Array.mapi (fun i (_,(_,_,neg_body)) -> - if List.exists (List.mem atom) neg_body then Some i + (* a disjunction is not enough a reason to exclude a branch *) + if List.exists (fun (_,neg)->[atom] = neg) neg_body + then Some i else None) brs in let negatives = Aux.map_some (fun x->x) (Array.to_list negatives) in - Printf.printf "\nd\n%!"; + (* {{{ log entry *) + if !debug_level > 3 then ( + Printf.printf "Entry for atom %s:\npositives: %s\nnegatives: %s\n%!" + (fact_str atom) + (String.concat ", "(List.map string_of_int positives)) + (String.concat ", "(List.map string_of_int negatives)) + ); + (* }}} *) (* first those that allow "P" then those that allow "not P" *) [Aux.Ints.diff full_set (Aux.ints_of_list negatives); Aux.Ints.diff full_set (Aux.ints_of_list positives)] @@ -2140,23 +2386,66 @@ let cases = Aux.product table in let cases = List.map (List.fold_left Aux.Ints.inter full_set) cases in + let cases = List.filter (fun case -> + not (Aux.Ints.is_empty (Aux.Ints.inter does_set case))) + cases in + (* every partition point has different preconditions... *) let cases = - Aux.unique_sorted (List.map Aux.Ints.elements cases) in - let cases = List.map (fun c_brs -> + (* Aux.unique_sorted *) (List.map Aux.Ints.elements cases) in + (* {{{ log entry *) + if !debug_level > 3 then ( + Printf.printf "CASES:\n%s\n%!" (String.concat "\n" (List.map ( + fun l -> String.concat ", " (List.map string_of_int l)) cases)) + ); + (* }}} *) + (* 7l3 *) + + let check_branch body = + Aux.array_existsi (fun ply states -> + if ply mod loc_n = loc then ( + (* {{{ log entry *) + if !debug_level > 4 then ( + let posi = + Aux.map_some (function + | "true", [st_arg] -> Some st_arg + | _ -> None) body in + Printf.printf + "Checking branch at states:\n%s\npositives:\n%s\n" + (terms_str states) (terms_str posi) + ); + (* }}} *) + let res = + List.for_all (function + | "true", [st_arg] -> + List.exists (unifies st_arg) states + | _ -> true) body in + (* {{{ log entry *) + if !debug_level > 4 then ( + Printf.printf "result: %b\n%!" res + ); + (* }}} *) + res + ) else false) agg_states in + + let cases = Aux.map_try (fun c_brs -> let c_brs = List.map (Array.get brs) c_brs in List.fold_left (fun - ((rhs_pos_acc, rhs_neg_acc, static_conjs_acc, conjs_acc), - heads, bodies, neg_bodies) + (rhs_pos_acc, rhs_neg_acc, static_conjs_acc, conjs_acc) ((rhs_pos, rhs_neg, static_conjs, conjs), - (head, body, neg_body)) -> - (rhs_pos @ rhs_pos_acc, rhs_neg @ rhs_neg_acc, - static_conjs @ static_conjs_acc, conjs @ conjs_acc), - head::heads,body@bodies,neg_body@neg_bodies) - (([],[],conjs_4b,conjs_4b),[],[],[]) c_brs + (_,body,_)) -> + if not (check_branch body) + then raise Not_found; + rhs_pos @ rhs_pos_acc, rhs_neg @ rhs_neg_acc, + static_conjs @ static_conjs_acc, conjs @ conjs_acc) + ([],[],conjs_4b,conjs_4b) c_brs ) cases in (* 7m *) - let cases = List.filter (fun ((_,_,static_phis,_), - heads,bodies,neg_bodies) -> + let cases = Aux.map_some (fun (rhs_pos,rhs_neg,static_phis,phis) -> + if rhs_pos = [] && rhs_neg = [] then None + else Some ( + Aux.unique_sorted rhs_pos, Aux.unique_sorted rhs_neg, + static_phis, phis)) cases in + let cases = Aux.map_some (fun (rhs_pos,rhs_neg,static_phis,phis) -> let phi = Formula.And static_phis in let rphi = Solver.M.register_formula phi in (* {{{ log entry *) @@ -2178,25 +2467,32 @@ (* }}} *) let res = Solver.M.check_formula struc rphi in (* {{{ log entry *) - if !debug_level > 3 && res then ( + if !debug_level > 4 && res then ( Printf.printf "holds\n%!" ); (* }}} *) - res) cases in - List.map (fun case -> lead, case) cases + if res then Some (rhs_pos, rhs_neg, phis) + else None) cases in + List.map (fun (rhs_pos, rhs_neg, conjs) -> + lead, (rhs_pos, rhs_neg, lift_universal uni_vars conjs)) cases ) rules_brs ) loc_next_classes in (* 7n *) let terminal_brs = List.map (function - | [], body, neg_body -> [Const "_TERMINAL_"], body, neg_body + | [], body, neg_body -> [Const "_IGNORE_RHS_"], body, neg_body | _ -> assert false) terminal_rules in - let terminal_4b, terminal_brs = + let terminal_uni_vars, terminal_4b, terminal_brs = translate_branches struc masks static_rnames dyn_rels terminal_brs in + (* lifting will drop spurious (4b) premises *) let terminal_disjs = List.map (fun ((_,_,_,conjs),_) -> - Formula.And conjs) terminal_brs in - let terminal_phi = - Formula.And [Formula.And terminal_4b; Formula.Or terminal_disjs] in + let disj_vars = FormulaOps.free_vars (Formula.And conjs) in + let disj_4b = + List.filter (fun a -> List.exists (fun v->List.mem v disj_vars) + (FormulaOps.free_vars a)) terminal_4b in + lift_universal terminal_uni_vars + (disj_4b @ conjs)) terminal_brs in + let terminal_phi = Formula.Or terminal_disjs in (* {{{ log entry *) if !debug_level > 1 then ( Printf.printf "GDL.translate_game: terminal condition -- %s\n%!" @@ -2204,22 +2500,18 @@ ); (* }}} *) (* let loc_toss_rules = *) - Array.mapi (fun loc rules_brs -> - List.map (fun (lead, brs) -> - ignore (terminal_4b, terminal_brs) - - ) rules_brs - ) loc_toss_rules; - (* {{{ log entry *) if !debug_level > 1 then ( Array.iteri (fun loc rules_brs -> Printf.printf "Rule translations for loc %d:\n%!" loc; - List.iter (fun ((lead,_,_), (phis,heads,bodies,neg_bodies)) -> - Printf.printf "Rule-translation: player %s move %s\n%s\n%!" + List.iter (fun ((lead,_,_), (rhs_pos,rhs_neg,precond)) -> + Printf.printf + "Rule-translation: player %s move %s precond:\n%s\naction:\nADD %s... DEL %s\n%!" (term_str loc_players.(loc)) (term_str lead) - (rule_pretransl_str (heads,bodies,neg_bodies)) + (Formula.sprint precond) + (String.concat "; " (List.map proto_rel_str rhs_pos)) + (String.concat "; " (List.map proto_rel_str rhs_neg)) ) rules_brs; ) loc_toss_rules; ); Modified: trunk/Toss/GGP/GDL.mli =================================================================== --- trunk/Toss/GGP/GDL.mli 2011-02-09 03:37:28 UTC (rev 1315) +++ trunk/Toss/GGP/GDL.mli 2011-02-10 12:16:07 UTC (rev 1316) @@ -57,8 +57,10 @@ type gdl_rule = gdl_atom * gdl_atom list * gdl_atom list (** Definition with expanded definitions: expansion of a negated relation brings negated conjunctions. *) +type exp_def_branch = + term list * gdl_atom list * (Aux.Strings.t * gdl_atom list) list type exp_def = - string * (term list * gdl_atom list * gdl_atom list list) list + string * exp_def_branch list val func_graph : string -> term list -> term list list Modified: trunk/Toss/GGP/GDLTest.ml =================================================================== --- trunk/Toss/GGP/GDLTest.ml 2011-02-09 03:37:28 UTC (rev 1315) +++ trunk/Toss/GGP/GDLTest.ml 2011-02-10 12:16:07 UTC (rev 1316) @@ -111,5 +111,6 @@ let a () = GDL.debug_level := 4; let breakthrough = load_rules "./GGP/examples/breakthrough.gdl" in - let gdef = GDL.translate_game breakthrough in + let connect5 = load_rules "./GGP/examples/connect5.gdl" in + let gdef = GDL.translate_game connect5 in () Modified: trunk/Toss/Play/GameTest.ml =================================================================== --- trunk/Toss/Play/GameTest.ml 2011-02-09 03:37:28 UTC (rev 1315) +++ trunk/Toss/Play/GameTest.ml 2011-02-10 12:16:07 UTC (rev 1316) @@ -863,8 +863,7 @@ \"" 0 in Game.use_monotonic := false; hard_case state 0 "should not attack" - (fun mov_s -> Printf.printf "avoid: %s\n" mov_s; - "Cross{1:f4}" <> mov_s && "Cross{1:f3}" <> mov_s); + (fun mov_s -> "Cross{1:f3}" <> mov_s); Game.use_monotonic := true; ); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2011-02-09 03:37:34
|
Revision: 1315 http://toss.svn.sourceforge.net/toss/?rev=1315&view=rev Author: lukaszkaiser Date: 2011-02-09 03:37:28 +0000 (Wed, 09 Feb 2011) Log Message: ----------- Final parameters from the server. Modified Paths: -------------- trunk/Toss/GGP/GDL.ml Modified: trunk/Toss/GGP/GDL.ml =================================================================== --- trunk/Toss/GGP/GDL.ml 2011-02-07 20:54:24 UTC (rev 1314) +++ trunk/Toss/GGP/GDL.ml 2011-02-09 03:37:28 UTC (rev 1315) @@ -2286,7 +2286,7 @@ game_description := game_descr; player_name_terms := [|Const "WHITE"; Const "BLACK"|]; let effort, horizon, heur_adv_ratio = - 6, 100, 2.0 in + 6, 100, 4.0 in effort, horizon, heur_adv_ratio let initialize_game_pawn_whopping state player game_descr startcl = @@ -2295,7 +2295,7 @@ game_description := game_descr; player_name_terms := [|Const "X"; Const "O"|]; let effort, horizon, heur_adv_ratio = - 10, 100, 2.0 in + 10, 100, 4.0 in effort, horizon, heur_adv_ratio let initialize_game state player game_descr startcl = This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2011-02-07 20:54:30
|
Revision: 1314 http://toss.svn.sourceforge.net/toss/?rev=1314&view=rev Author: lukaszkaiser Date: 2011-02-07 20:54:24 +0000 (Mon, 07 Feb 2011) Log Message: ----------- Setting parameters to play against Fluxplayer. Modified Paths: -------------- trunk/Toss/GGP/GDL.ml trunk/Toss/Server/Server.ml trunk/Toss/examples/Connect4.toss Modified: trunk/Toss/GGP/GDL.ml =================================================================== --- trunk/Toss/GGP/GDL.ml 2011-02-05 16:36:17 UTC (rev 1313) +++ trunk/Toss/GGP/GDL.ml 2011-02-07 20:54:24 UTC (rev 1314) @@ -2257,7 +2257,7 @@ game_description := game_descr; player_name_terms := [|Const "XPLAYER"; Const "OPLAYER"|]; let effort, horizon, heur_adv_ratio = - 5, 100, 4.0 in + 6, 100, 4.0 in effort, horizon, heur_adv_ratio let initialize_game_gomoku state player game_descr startcl = @@ -2277,7 +2277,7 @@ player_name_terms := [|Const "WHITE"; Const "RED"|]; Game.use_monotonic := false; let effort, horizon, heur_adv_ratio = - 8, 100, 4.0 in + 10, 100, 4.0 in effort, horizon, heur_adv_ratio let initialize_game_breakthrough state player game_descr startcl = @@ -2286,7 +2286,7 @@ game_description := game_descr; player_name_terms := [|Const "WHITE"; Const "BLACK"|]; let effort, horizon, heur_adv_ratio = - 4, 100, 2.0 in + 6, 100, 2.0 in effort, horizon, heur_adv_ratio let initialize_game_pawn_whopping state player game_descr startcl = @@ -2295,7 +2295,7 @@ game_description := game_descr; player_name_terms := [|Const "X"; Const "O"|]; let effort, horizon, heur_adv_ratio = - 8, 100, 2.0 in + 10, 100, 2.0 in effort, horizon, heur_adv_ratio let initialize_game state player game_descr startcl = Modified: trunk/Toss/Server/Server.ml =================================================================== --- trunk/Toss/Server/Server.ml 2011-02-05 16:36:17 UTC (rev 1313) +++ trunk/Toss/Server/Server.ml 2011-02-07 20:54:24 UTC (rev 1314) @@ -268,6 +268,7 @@ | Aux.Right (GDL.Start (_, player, game_descr, startcl, playcl)) -> (* GDL will store the player and the game in its state. *) + Random.init 1234; (* for repeatablity *) let effort, horizon, heur_adv_ratio = GDL.initialize_game state player game_descr startcl in (* TODO: handle timer (startclock) in Game.initialize_default*) Modified: trunk/Toss/examples/Connect4.toss =================================================================== --- trunk/Toss/examples/Connect4.toss 2011-02-05 16:36:17 UTC (rev 1313) +++ trunk/Toss/examples/Connect4.toss 2011-02-07 20:54:24 UTC (rev 1314) @@ -1,7 +1,5 @@ PLAYERS 1, 2 DATA r1: circle, r2: line, adv_ratio: 4, depth: 6 -REL DiagA (x, y) = ex u (R(x, u) and C(u, y)) -REL DiagB (x, y) = ex u (R(x, u) and C(y, u)) REL Row4 (x, y, z, v) = R(x, y) and R(y, z) and R(z, v) REL Col4 (x, y, z, v) = C(x, y) and C(y, z) and C(z, v) REL DiagA4 (x, y, z, v) = DiagA(x, y) and DiagA(y, z) and DiagA(z, v) @@ -49,4 +47,5 @@ ... ... ... ... ... ... ... ... ... ... ... -" +" with DiagA (x, y) = ex u (R(x, u) and C(u, y)) ; + DiagB (x, y) = ex u (R(x, u) and C(y, u)) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2011-02-05 16:36:23
|
Revision: 1313 http://toss.svn.sourceforge.net/toss/?rev=1313&view=rev Author: lukstafi Date: 2011-02-05 16:36:17 +0000 (Sat, 05 Feb 2011) Log Message: ----------- GDL: Correcting a stupid addition. GDL translation further progress. Modified Paths: -------------- trunk/Toss/GGP/GDL.ml Modified: trunk/Toss/GGP/GDL.ml =================================================================== --- trunk/Toss/GGP/GDL.ml 2011-02-05 16:14:05 UTC (rev 1312) +++ trunk/Toss/GGP/GDL.ml 2011-02-05 16:36:17 UTC (rev 1313) @@ -151,7 +151,7 @@ but do not contain ground facts, by duplicating the branch in which body an atom of the relation occurs, for each branch of the relation definition, unifying and applying the unifier. (If the - duplication turns out prohibitive, this will be a *huge* TODO for + duplication turns out prohibitive, this will be a huge TODO for this translation framework.) (6a) The definition: @@ -160,14 +160,16 @@ provides a DNF defining formula (using negation-as-failure): - [(r, args) <=> exist vars1 (args = params1 /\ body1) \/ ... - \/ exist vars_n (args = params_n /\ body_n)] + [(r, args) <=> exist vars1 (params1 = args /\ body1) \/ ... + \/ exist vars_n (params_n = args /\ body_n)] which expands in a natural way for positive occurrences. We duplicate the branch where [(r, args)] is substitued for each - disjunct and apply the unifier of [args = params_i] in the whole - [i]th cloned branch. We freshen each [vars_i] to avoid capture. If - unification fails, we drop the corresponding branch clone. + disjunct and apply the unifier of [params_i = args] in the whole + [i]th cloned branch, eliminating the [params] (rather than the + [args]) when possible. We freshen each [vars_i] to avoid + capture. If unification fails, we drop the corresponding branch + clone. (6b) For negative occurrences we transform the defining formula to: @@ -184,12 +186,14 @@ (and (...(r args)...))]) into the conjunction of negations, with no branch duplication (in general, duplicating the negated subformula inside a branch). We only apply the unifier of [args = - params_i] to [body_i] (in general, the whole negated - subformula). Still, we freshen each [vars_i] to avoid capture. If - unification fails, we drop the corresponding negated - subformula. If unification succeeds but the corresponding [body_i] - is empty (and, in general, no other disjuncts in the negated - subformula are left), we drop the branch. + params_i] to [body_i] (in general, the whole negated subformula), + eliminating the [params] (rather than the [args]) when + possible. Still, we freshen each [vars_i] to avoid capture. We + remember the (uneliminated) [vars_i] in the set of variables + quantified under the negation. If unification fails, we drop the + corresponding negated subformula. If unification succeeds but the + corresponding [body_i] is empty (and, in general, no other + disjuncts in the negated subformula are left), we drop the branch. (6b1) The general case is not implemented yet since it slightly complicates the code, and expressivity gain is very small. @@ -565,8 +569,26 @@ (if def then body @ List.concat neg_body else List.concat neg_body)) branches) defs with - | [], [] -> List.rev strata - | stratum, [] -> List.rev (stratum::strata) + | [], [] -> + (* {{{ log entry *) + if !debug_level > 3 then ( + Printf.printf "stratify: %d strata -- %s\n%!" + (List.length strata) (String.concat "; " (List.map (fun l -> + String.concat ", " (List.map fst l)) (List.rev strata))) + ); + (* }}} *) + List.rev strata + | stratum, [] -> + (* {{{ log entry *) + if !debug_level > 3 then ( + Printf.printf "stratify: %d strata -- %s\n%!" + (List.length (stratum::strata)) (String.concat "; " ( + List.map (fun l -> + String.concat ", " (List.map fst l)) + (List.rev (stratum::strata)))) + ); + (* }}} *) + List.rev (stratum::strata) | [], _ -> if def then raise (Lexer.Parsing_error @@ -574,7 +596,16 @@ else raise (Lexer.Parsing_error "GDL.stratify: cyclic negation dependency") - | stratum, rules -> stratify (stratum::strata) rules + | stratum, rules -> + if not def then + let stratum, more_rules = List.partition (fun (_, branches) -> + List.for_all (fun (_, body, neg_body) -> + List.for_all (fun (rel1,_) -> + rel1 = "distinct" || rel1 = "true" || rel1 = "does" || + not (List.mem_assoc rel1 rules)) + body) branches) stratum in + stratify ~def (stratum::strata) (more_rules @ rules) + else stratify ~def (stratum::strata) rules let rec subst_one (x, term as sb) = function @@ -864,7 +895,7 @@ let subst_def_branch (defs : exp_def list) (head, body, neg_body as br : exp_def_branch) : exp_def_branch list = (* {{{ log entry *) - if !debug_level > 3 then ( + if !debug_level > 4 then ( Printf.printf "Expanding branch %s\n%!" (def_str ("BRANCH", [br])); ); (* }}} *) @@ -874,7 +905,7 @@ (let try def = freshen_def_branches (List.assoc rel defs) in (* {{{ log entry *) - if !debug_level > 3 then ( + if !debug_level > 4 then ( Printf.printf "Expanding positive %s by %s\n%!" rel (def_str (rel, def)) ); @@ -930,9 +961,21 @@ let rec loop base = function | [] -> base | stratum::strata -> + (* {{{ log entry *) + if !debug_level > 3 then ( + Printf.printf "expand_def_rules: step base rels = %s\n%!" + (String.concat ", " (List.map fst base)) + ); + (* }}} *) let step = List.map (fun (rel, branches) -> rel, Aux.concat_map (subst_def_branch (more_defs@base)) branches) stratum in + (* {{{ log entry *) +if !debug_level > 3 then ( + Printf.printf "expand_def_rules: step result = %s\nexpand_def_rules: end step\n%!" + (String.concat "\n" (List.map def_str step)) +); +(* }}} *) loop (base @ step) strata in match stratify ~def:true [] (defs_of_rules rules) with | [] -> [] @@ -1274,11 +1317,13 @@ let rname = term_to_name (subst_one v_sb mask) in Some (Formula.Rel (rname, [|svar|]))) sb in (* FIXME: make sure it's the right semantics *) - [phi; Formula.Not (Formula.And conjs)] + [phi; Formula.Not (Formula.And/Or conjs)] *) else if List.mem rel static_rnames then (* 7i-4a *) + (* FIXME: And / Or semantics? *) List.map (fun c -> Formula.Not c) (conjs_4a rel args) + (* [Formula.Not (Formula.And (conjs_4a rel args))] *) else [] )) neg_body in let all_conjs = phi @ conjs @ neg_conjs in @@ -1290,7 +1335,7 @@ let rphi = Solver.M.register_formula (Formula.And optim_conjs) in (* {{{ log entry *) - if !debug_level > 3 then ( + if !debug_level > 4 then ( (* do not print, because it generates too many answers -- too little constraints per number of variables when considering a single branch *) @@ -1301,9 +1346,8 @@ let atups = AssignmentSet.tuples struc.Structure.elements avars assgn in *) - Printf.printf "evaluating: %s -- simpl %s\n%!" + Printf.printf "evaluating: %s\n%!" (Formula.str phi) - (Solver.M.formula_str rphi) (* (List.length atups) *) ); (* }}} *) @@ -2116,7 +2160,7 @@ let phi = Formula.And static_phis in let rphi = Solver.M.register_formula phi in (* {{{ log entry *) - if !debug_level > 3 then ( + if !debug_level > 4 then ( (* do not print, because it generates too many answers -- too little constraints per number of variables when considering a single branch *) @@ -2127,9 +2171,8 @@ let atups = AssignmentSet.tuples struc.Structure.elements avars assgn in *) - Printf.printf "evaluating: %s -- simpl %s\n%!" + Printf.printf "evaluating: %s\n%!" (Formula.str phi) - (Solver.M.formula_str rphi) (* (List.length atups) *) ); (* }}} *) @@ -2150,7 +2193,16 @@ | _ -> assert false) terminal_rules in let terminal_4b, terminal_brs = translate_branches struc masks static_rnames dyn_rels terminal_brs in - + let terminal_disjs = List.map (fun ((_,_,_,conjs),_) -> + Formula.And conjs) terminal_brs in + let terminal_phi = + Formula.And [Formula.And terminal_4b; Formula.Or terminal_disjs] in + (* {{{ log entry *) + if !debug_level > 1 then ( + Printf.printf "GDL.translate_game: terminal condition -- %s\n%!" + (Formula.sprint terminal_phi) + ); + (* }}} *) (* let loc_toss_rules = *) Array.mapi (fun loc rules_brs -> List.map (fun (lead, brs) -> @@ -2160,7 +2212,7 @@ ) rules_brs ) loc_toss_rules; - (* {{{ log entry *) + (* {{{ log entry *) if !debug_level > 1 then ( Array.iteri (fun loc rules_brs -> Printf.printf "Rule translations for loc %d:\n%!" loc; @@ -2247,7 +2299,6 @@ effort, horizon, heur_adv_ratio let initialize_game state player game_descr startcl = - translate_game game_descr; if (Some game_descr) = !tictactoe_descr then manual_game := "tictactoe"; if (Some game_descr) = !breakthrough_descr then manual_game := "breakthrough"; if (Some game_descr) = !connect5_descr then manual_game := "connect5"; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2011-02-05 16:14:12
|
Revision: 1312 http://toss.svn.sourceforge.net/toss/?rev=1312&view=rev Author: lukaszkaiser Date: 2011-02-05 16:14:05 +0000 (Sat, 05 Feb 2011) Log Message: ----------- Faster tests (lower timeout). Modified Paths: -------------- trunk/Toss/GGP/Makefile Modified: trunk/Toss/GGP/Makefile =================================================================== --- trunk/Toss/GGP/Makefile 2011-02-04 22:59:13 UTC (rev 1311) +++ trunk/Toss/GGP/Makefile 2011-02-05 16:14:05 UTC (rev 1312) @@ -17,12 +17,12 @@ %.black: examples/%.gdl ../TossServer ../TossServer -gdl unset -v & - java -jar gamecontroller-cli.jar play $< 600 180 1 -random 1 -remote 2 toss localhost 8110 1 | grep results + java -jar gamecontroller-cli.jar play $< 600 10 1 -random 1 -remote 2 toss localhost 8110 1 | grep results killall -v TossServer %.white: examples/%.gdl ../TossServer ../TossServer -gdl unset -v & - java -jar gamecontroller-cli.jar play $< 600 180 1 -random 2 -remote 1 toss localhost 8110 1 | grep results + java -jar gamecontroller-cli.jar play $< 600 10 1 -random 2 -remote 1 toss localhost 8110 1 | grep results killall -v TossServer tests: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2011-02-04 22:59:20
|
Revision: 1311 http://toss.svn.sourceforge.net/toss/?rev=1311&view=rev Author: lukaszkaiser Date: 2011-02-04 22:59:13 +0000 (Fri, 04 Feb 2011) Log Message: ----------- Parameter change. Modified Paths: -------------- trunk/Toss/GGP/GDL.ml Modified: trunk/Toss/GGP/GDL.ml =================================================================== --- trunk/Toss/GGP/GDL.ml 2011-02-04 15:23:14 UTC (rev 1310) +++ trunk/Toss/GGP/GDL.ml 2011-02-04 22:59:13 UTC (rev 1311) @@ -2225,7 +2225,7 @@ player_name_terms := [|Const "WHITE"; Const "RED"|]; Game.use_monotonic := false; let effort, horizon, heur_adv_ratio = - 8, 100, 2.0 in + 8, 100, 4.0 in effort, horizon, heur_adv_ratio let initialize_game_breakthrough state player game_descr startcl = This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2011-02-04 15:23:21
|
Revision: 1310 http://toss.svn.sourceforge.net/toss/?rev=1310&view=rev Author: lukstafi Date: 2011-02-04 15:23:14 +0000 (Fri, 04 Feb 2011) Log Message: ----------- GDL: progress (refactoring, terminal condition). Game: Reverting to payoff-scaled values in terminal nodes of alpha-beta. Modified Paths: -------------- trunk/Toss/GGP/GDL.ml trunk/Toss/Play/Game.ml trunk/Toss/Play/GameTest.ml Modified: trunk/Toss/GGP/GDL.ml =================================================================== --- trunk/Toss/GGP/GDL.ml 2011-02-03 20:36:45 UTC (rev 1309) +++ trunk/Toss/GGP/GDL.ml 2011-02-04 15:23:14 UTC (rev 1310) @@ -284,10 +284,10 @@ (7h) Introduce a new element variable for each class of "next" and "true" terms equal modulo mask (i.e. there is a mask matching them and they differ only at-or-below metavariables). (Remember the - atoms "corresponding variable".) From now on until (7m1) we keep + atoms "corresponding variable".) From now on until (7l1) we keep both the (partially) Toss-translated versions and the (complete) GDL-originals of branches (so to use GDL atoms for "subsumption - checking" in (7m)). + checking" in (7l)). (7i-4a) For all subterms of "next" and "true" atoms, identify the sets of <mask-path, element variable> they "inhabit". Replace a @@ -349,8 +349,8 @@ associated with every bit. The unique resulting sets are exactly the Toss rules precursors. - (7m) Filter the final rule candidates by satisfiability in at - least one of aggregate playout states. + (7m) Filter the final rule candidates by satisfiability of the + static part (same as (7i1) conjoined). (7n) Include translated negation of the terminal condition. (Now we build rewrite rules for a refinement of an equivalence class of @@ -363,6 +363,10 @@ precondition. Exactly the RHS variables are listed in the LHS (other variables are existentially closed in the precondition). + (7o) After the rules are translated, perform an aggregated playout + of the Toss variant of the game. Remove the rules that were never + applied. + (8) We use a single payoff matrix for all locations. Goal patterns are expanded to regular goals by instantiating the value variable by all values in its domain (for example, as gathered from the @@ -1116,6 +1120,290 @@ (term_str a) (term_str b); assert false +let triang_matrix elems = + let rec aux acc = function + | [] -> acc + | hd::tl -> aux (List.map (fun e->[|hd; e|]) tl @ acc) tl in + aux [] elems + +let term_to_blank masks next_arg = + let mask_cands = + Aux.map_try (fun mask -> + mask, match_meta [] [] [next_arg] [mask] + ) masks in + let mask, sb, m_sb = match mask_cands with + | [mask, (sb, m_sb)] -> mask, sb, m_sb + | _ -> assert false in + mask, sb, m_sb, blank_out (next_arg, mask) + +let toss_var masks term = + let mask, _, _, blank = term_to_blank masks term in + mask, Formula.fo_var_of_string (term_to_name blank) + +let translate_branches struc masks static_rnames dyn_rels brs = + (* 7i *) + (* Do not flatten the already built super-partition. *) + let state_terms = + List.fold_left (fun acc -> function + | [next_arg], body, neg_body -> + let res = + List.fold_left (fun acc -> function + | "true", [true_arg] -> Terms.add true_arg acc + | "true", _ -> assert false + | _ -> acc) acc body in + let res = + List.fold_left (List.fold_left (fun acc -> function + | "true", [true_arg] -> Terms.add true_arg acc + | "true", _ -> assert false + | _ -> acc)) res neg_body in + if next_arg = Const "_TERMINAL_" + then res + else Terms.add next_arg res + | _ -> assert false + ) Terms.empty brs in + let state_terms = Terms.elements state_terms in + (* {{{ log entry *) + if !debug_level > 2 then ( + Printf.printf "state_terms: %s\n%!" ( + String.concat ", " (List.map term_str state_terms)) + ); + (* }}} *) + let state_subterms = + Aux.concat_map (fun term -> + let mask, sb, m_sb, blanked = term_to_blank masks term in + List.map (fun (v,t) -> t, (mask, v, term)) sb + ) state_terms in + let conjs_4a rel args = + let ptups = List.map (fun arg -> + Aux.assoc_all arg state_subterms) args in + (* {{{ log entry *) + if !debug_level > 3 then ( + Printf.printf "conjs_4a: of %s = subterms %s\n%!" + (fact_str (rel,args)) (String.concat "; " ( + List.map (fun l -> String.concat ", " + (List.map (fun (_,_,term)->term_str term) l)) ptups)) + ); + (* }}} *) + let ptups = Aux.product ptups in + let res = + List.map (fun ptup -> + let rname = rel ^ "__" ^ String.concat "__" + (List.map (fun (mask,v,_)-> + term_to_name mask ^ "_" ^ v) ptup) in + let tup = List.map (fun (_,_,term) -> + snd (toss_var masks term)) ptup in + Formula.Rel (rname, Array.of_list tup)) ptups in + let res = Aux.unique_sorted res in + (* {{{ log entry *) + if !debug_level > 3 then ( + Printf.printf "conjs_4a: of %s = %s\n%!" + (fact_str (rel,args)) (Formula.str (Formula.And res)) + ); + (* }}} *) + res in + (* 7i-4b *) + let path_subterms = + Aux.concat_map (fun term -> + let mask, sb, m_sb, blanked = term_to_blank masks term in + Aux.map_some (function + | v, Var t -> Some ((mask, v), (t, term)) + | _ -> None) sb + ) state_terms in + let path_subterms = Aux.collect path_subterms in + let conjs_4b = + Aux.concat_map (fun ((mask, v), terms) -> + let rname = "EQ___" ^ term_to_name mask ^ "_" ^ v in + let terms = Aux.collect terms in + Aux.concat_map (fun (_,terms) -> + let vars = List.map (fun t -> snd (toss_var masks t)) terms in + let tups = triang_matrix (Aux.unique_sorted vars) in + List.map (fun tup -> Formula.Rel (rname, tup)) tups + ) terms + ) path_subterms in + let conjs_4b = Aux.unique_sorted conjs_4b in + let brs = Aux.map_some (function + | [next_arg],body,neg_body -> + let phi, lvars = + if next_arg = Const "_TERMINAL_" then [], ref [] + else + let mask, sb, m_sb, blanked = term_to_blank masks next_arg in + let rname = term_to_name mask in + let _, svar = toss_var masks next_arg in + let phi = Formula.Rel (rname, [|svar|]) in + let lvars = ref [svar] in + [phi], lvars in + let conjs = + Aux.concat_map (fun (rel, args) -> + if rel = "true" then + (* 7i-4c *) + let true_arg = List.hd args in + let mask, sb, m_sb, blanked = term_to_blank masks true_arg in + let rname = term_to_name mask in + let _, svar = toss_var masks true_arg in + lvars := svar :: !lvars; + let phi = Formula.Rel (rname, [|svar|]) in + let conjs = + Aux.map_some (function + | _, Var _ -> None + | v, t as v_sb -> + let rname = term_to_name (subst_one v_sb mask) in + Some (Formula.Rel (rname, [|svar|]))) sb in + phi::conjs + else if List.mem rel static_rnames then + (* 7i-4a *) + conjs_4a rel args + else [] + ) body in + let neg_conjs = + Aux.concat_map ( + Aux.concat_map (fun (rel, args) -> + if rel = "true" then + (* lvars := svar :: !lvars; ??? *) + (* negated (4c) is calculated together with (5) *) + [] + (* + let true_arg = List.hd args in + let mask, sb, m_sb, blanked = term_to_blank masks true_arg in + let rname = term_to_name mask in + let _, svar = toss_var masks true_arg in + let phi = Formula.Rel (rname, [|svar|]) in + let conjs = + Aux.map_some (function + | _, Var _ -> None + | v, t as v_sb -> + let rname = term_to_name (subst_one v_sb mask) in + Some (Formula.Rel (rname, [|svar|]))) sb in + (* FIXME: make sure it's the right semantics *) + [phi; Formula.Not (Formula.And conjs)] + *) + else if List.mem rel static_rnames then + (* 7i-4a *) + List.map (fun c -> Formula.Not c) (conjs_4a rel args) + else [] + )) neg_body in + let all_conjs = phi @ conjs @ neg_conjs in + let phi = Formula.And all_conjs in + let lvars = (!lvars :> Formula.var list) in + let optim_conjs = List.filter (fun c-> + List.for_all (fun v->List.mem v lvars) + (FormulaOps.free_vars c)) (conjs_4b @ all_conjs) in + let rphi = Solver.M.register_formula + (Formula.And optim_conjs) in + (* {{{ log entry *) + if !debug_level > 3 then ( + (* do not print, because it generates too many + answers -- too little constraints per number of + variables when considering a single branch *) + (* + let assgn = Solver.M.evaluate struc rphi in + let avars = List.map Formula.var_str + (FormulaOps.free_vars phi) in + let atups = + AssignmentSet.tuples struc.Structure.elements + avars assgn in *) + Printf.printf "evaluating: %s -- simpl %s\n%!" + (Formula.str phi) + (Solver.M.formula_str rphi) + (* (List.length atups) *) + ); + (* }}} *) + if Solver.M.check_formula struc rphi + then ( + (* {{{ log entry *) + if !debug_level > 3 then ( + Printf.printf "holds\n%!" + ); + (* }}} *) + Some (all_conjs, (next_arg,body,neg_body))) + else None + | _ -> assert false) brs in + (* 7j: TODO *) + + (* 7k *) + let brs = + List.map (fun (static_conjs, (next_arg,body,neg_body)) -> + let rhs_pos_preds, rhs_possneg_preds = + if next_arg = Const "_TERMINAL_" then [], [] + else + let mask, sb, m_sb, blanked = term_to_blank masks next_arg in + let rhs_elem = term_to_name blanked in + Aux.partition_map (fun (v,t as v_sb) -> + if t = Const "_BLANK_" then + let neg_rels = List.assoc (mask, v) dyn_rels in + Aux.Right (List.map (fun rel->rel, [|rhs_elem|]) neg_rels) + else + let rname = term_to_name (subst_one v_sb mask) in + Aux.Left (rname, [|rhs_elem|]) + ) m_sb in + let rhs_possneg_preds = List.flatten rhs_possneg_preds in + let dyn_conjs = + Aux.concat_map (fun (rel, args) -> + if rel = "true" then + (* 7i-4c *) + let true_arg = List.hd args in + let mask, sb, m_sb, blanked = term_to_blank masks true_arg in + let _, svar = toss_var masks true_arg in + + let lhs_pos_preds, lhs_possneg_preds = + Aux.partition_map (fun (v,t as v_sb) -> + if t = Const "_BLANK_" then + (* + let neg_rels = List.assoc (mask, v) dyn_rels in + Aux.Right (List.map (fun rel-> + Formula.Rel (rel, [|svar|])) neg_rels) + *) assert false + else + let rname = term_to_name (subst_one v_sb mask) in + Aux.Left (Formula.Rel (rname, [|svar|])) + ) m_sb in + (* + let lhs_possneg_preds = List.flatten lhs_possneg_preds in + *) + lhs_pos_preds + else if List.mem rel static_rnames + then [] + else ( + Printf.printf "\nunexpected_dynamic: %s\n%!" rel; + (* dynamic relations have been expanded *) + assert false) + ) body in + let neg_conjs = + Aux.concat_map ( + Aux.concat_map (fun (rel, args) -> + if rel = "true" then + let true_arg = List.hd args in + let mask, sb, m_sb, blanked = term_to_blank masks true_arg in + let rname = term_to_name mask in + let _, svar = toss_var masks true_arg in + let phi = Formula.Rel (rname, [|svar|]) in + let conjs_4c = + Aux.map_some (function + | _, Var _ -> None + | v, t as v_sb -> + let rname = term_to_name (subst_one v_sb mask) in + Some (Formula.Rel (rname, [|svar|]))) sb in + let conjs_5 = + List.map (fun (v,t as v_sb) -> + if t = Const "_BLANK_" then + assert false + else + (* t = Var _ have been expanded *) + let rname = term_to_name (subst_one v_sb mask) in + Formula.Rel (rname, [|svar|])) m_sb in + + (* FIXME: make sure it's the right semantics *) + [phi; Formula.Not (Formula.And (conjs_4c @ conjs_5))] + else if List.mem rel static_rnames + then [] + else + (* dynamic relations have been expanded *) + assert false + )) neg_body in + let all_conjs = static_conjs @ dyn_conjs @ neg_conjs in + (rhs_pos_preds, rhs_possneg_preds, static_conjs, all_conjs), + (next_arg, body, neg_body)) brs in + conjs_4b, brs + let translate_game game_descr = freshen_count := 0; let player_terms = @@ -1239,6 +1527,7 @@ (* 3 *) let legal_rules = List.assoc "legal" exp_defs in let next_rules = List.assoc "next" exp_defs in + let terminal_rules = List.assoc "terminal" exp_defs in (* 3b *) let exp_next = Aux.concat_map (subst_def_branch ["does", legal_rules]) next_rules in @@ -1462,27 +1751,21 @@ ) struc elements in (* 5 *) - let term_to_blank next_arg = - let mask_cands = - Aux.map_try (fun mask -> - mask, match_meta [] [] [next_arg] [mask] - ) masks in - let mask, sb, m_sb = match mask_cands with - | [mask, (sb, m_sb)] -> mask, sb, m_sb - | _ -> assert false in - mask, sb, m_sb, blank_out (next_arg, mask) in - let struc = List.fold_left (fun struc term -> - let mask, sb, m_sb, blanked = term_to_blank term in + let dyn_rels, struc = List.fold_left (fun (dyn_rels, struc) term -> + let mask, sb, m_sb, blanked = term_to_blank masks term in let e = let elems = List.assoc mask elements in List.assoc sb elems in - List.fold_left (fun struc (v,t as v_sb) -> + List.fold_left (fun (dyn_rels, struc) (v,t as v_sb) -> let rname = term_to_name (subst_one v_sb mask) in + ((mask, v), rname)::dyn_rels, if List.mem term init_state then Structure.add_rel struc rname [|e|] - else Structure.add_rel_name rname 1 struc) struc m_sb - ) struc element_terms in - + else Structure.add_rel_name rname 1 struc) (dyn_rels, struc) m_sb + ) ([], struc) element_terms in + let dyn_rels = + List.map (fun (path, subts) -> path, Aux.unique_sorted subts) + (Aux.collect dyn_rels) in (* 7a *) let legal_rules = Aux.concat_map (function [Const _; _], _, _ as lrule -> [lrule] @@ -1670,7 +1953,7 @@ let erasure_brs = Aux.concat_map (function | [next_arg] as next_args,multi_body -> - let mask, _, _, blank_arg = term_to_blank next_arg in + let mask, _, _, blank_arg = term_to_blank masks next_arg in (* {{{ log entry *) if !debug_level > 2 then ( Printf.printf "Blanking-out of %s by %s\n%!" @@ -1776,171 +2059,14 @@ ) loc_next_classes; ); (* }}} *) + let static_rnames = List.map (fun ((srel,_),_,_) -> srel) static_rules in (* 7h *) - let toss_var term = - let mask, _, _, blank = term_to_blank term in - mask, Formula.fo_var_of_string (term_to_name blank) in let loc_toss_rules = Array.mapi (fun loc rules_brs -> Aux.concat_map (fun (lead, brs) -> - (* 7i *) - (* Do not flatten the already built super-partition. *) - let state_terms = - List.fold_left (fun acc -> function - | [next_arg], body, neg_body -> - let res = - List.fold_left (fun acc -> function - | "true", [true_arg] -> Terms.add true_arg acc - | "true", _ -> assert false - | _ -> acc) acc body in - let res = - List.fold_left (List.fold_left (fun acc -> function - | "true", [true_arg] -> Terms.add true_arg acc - | "true", _ -> assert false - | _ -> acc)) res neg_body in - Terms.add next_arg res - | _ -> assert false - ) Terms.empty brs in - let state_terms = Terms.elements state_terms in - (* {{{ log entry *) - if !debug_level > 2 then ( - Printf.printf "state_terms: %s\n%!" ( - String.concat ", " (List.map term_str state_terms)) - ); - (* }}} *) - let state_subterms = - Aux.concat_map (fun term -> - let mask, sb, m_sb, blanked = term_to_blank term in - List.map (fun (v,t) -> t, (mask, v, term)) sb - ) state_terms in - let conjs_4a rel args = - let ptups = List.map (fun arg -> - Aux.assoc_all arg state_subterms) args in - (* {{{ log entry *) - if !debug_level > 3 then ( - Printf.printf "conjs_4a: of %s = subterms %s\n%!" - (fact_str (rel,args)) (String.concat "; " ( - List.map (fun l -> String.concat ", " - (List.map (fun (_,_,term)->term_str term) l)) ptups)) - ); - (* }}} *) - let ptups = Aux.product ptups in - let res = - List.map (fun ptup -> - let rname = rel ^ "__" ^ String.concat "__" - (List.map (fun (mask,v,_)-> - term_to_name mask ^ "_" ^ v) ptup) in - let tup = List.map (fun (_,_,term) -> - snd (toss_var term)) ptup in - Formula.Rel (rname, Array.of_list tup)) ptups in - let res = Aux.unique_sorted res in - (* {{{ log entry *) - if !debug_level > 3 then ( - Printf.printf "conjs_4a: of %s = %s\n%!" - (fact_str (rel,args)) (Formula.str (Formula.And res)) - ); - (* }}} *) - res in - let brs = Aux.map_some (function - | [next_arg],body,neg_body -> - let mask, sb, m_sb, blanked = term_to_blank next_arg in - let rname = term_to_name mask in - let _, svar = toss_var next_arg in - let phi = Formula.Rel (rname, [|svar|]) in - let lvars = ref [svar] in - let conjs = - Aux.concat_map (fun (rel, args) -> - if rel = "true" then - (* 7i-4c *) - let true_arg = List.hd args in - let mask, sb, m_sb, blanked = term_to_blank true_arg in - let rname = term_to_name mask in - let _, svar = toss_var true_arg in - lvars := svar :: !lvars; - let phi = Formula.Rel (rname, [|svar|]) in - let conjs = - Aux.map_some (function - | _, Var _ -> None - | v, t as v_sb -> - let rname = term_to_name (subst_one v_sb mask) in - Some (Formula.Rel (rname, [|svar|]))) sb in - phi::conjs - else if List.exists (fun ((srel,_),_,_) -> rel=srel) - static_rules then - (* 7i-4a *) - conjs_4a rel args - else - (* TODO: 7i-4b *) - [] - ) body in - let neg_conjs = - Aux.concat_map ( - Aux.concat_map (fun (rel, args) -> - if rel = "true" then - (* lvars := svar :: !lvars; ??? *) - (* negated (4c) is calculated together with (5) *) - [] - (* - let true_arg = List.hd args in - let mask, sb, m_sb, blanked = term_to_blank true_arg in - let rname = term_to_name mask in - let _, svar = toss_var true_arg in - let phi = Formula.Rel (rname, [|svar|]) in - let conjs = - Aux.map_some (function - | _, Var _ -> None - | v, t as v_sb -> - let rname = term_to_name (subst_one v_sb mask) in - Some (Formula.Rel (rname, [|svar|]))) sb in - (* FIXME: make sure it's the right semantics *) - [phi; Formula.Not (Formula.And conjs)] - *) - else if List.exists (fun ((srel,_),_,_) -> rel=srel) - static_rules then - (* 7i-4a *) - List.map (fun c -> Formula.Not c) (conjs_4a rel args) - else - (* TODO: 7i-4b *) - [] - )) neg_body in - let all_conjs = phi::conjs @ neg_conjs in - let phi = Formula.And all_conjs in - let lvars = (!lvars :> Formula.var list) in - let optim_conjs = List.filter (fun c-> - List.for_all (fun v->List.mem v lvars) - (FormulaOps.free_vars c)) all_conjs in - let rphi = Solver.M.register_formula - (Formula.And optim_conjs) in - (* {{{ log entry *) - if !debug_level > 3 then ( - (* do not print, because it generates too many - answers -- too little constraints per number of - variables when considering a single branch *) - (* - let assgn = Solver.M.evaluate struc rphi in - let avars = List.map Formula.var_str - (FormulaOps.free_vars phi) in - let atups = - AssignmentSet.tuples struc.Structure.elements - avars assgn in *) - Printf.printf "evaluating: %s -- simpl %s\n%!" - (Formula.str phi) - (Solver.M.formula_str rphi) - (* (List.length atups) *) - ); - (* }}} *) - if Solver.M.check_formula struc rphi - then ( - (* {{{ log entry *) - if !debug_level > 3 then ( - Printf.printf "holds\n%!" - ); - (* }}} *) - Some (phi, (next_arg,body,neg_body))) - else None - | _ -> assert false) brs in - (* 7j: TODO *) - (* 7k: TODO *) + let conjs_4b, brs = + translate_branches struc masks static_rnames dyn_rels brs in + (* 7l *) let atoms = List.fold_left (fun acc (_,(_,body,neg_body))-> @@ -1948,13 +2074,10 @@ (List.fold_right (List.fold_right Atoms.add) neg_body acc) ) Atoms.empty brs in - Printf.printf "\na\n%!"; let atoms = Atoms.elements atoms in - Printf.printf "\nb\n%!"; let brs = Array.of_list brs in (* indexing branches *) let full_set = Aux.ints_of_list (Array.to_list (Array.mapi (fun i _ -> i) brs)) in - Printf.printf "\nc\n%!"; let table = List.map (fun atom -> let positives = Array.mapi (fun i (_,(_,body,_)) -> if List.mem atom body then Some i else None) brs in @@ -1970,42 +2093,44 @@ [Aux.Ints.diff full_set (Aux.ints_of_list negatives); Aux.Ints.diff full_set (Aux.ints_of_list positives)] ) atoms in - Printf.printf "\ne\n%!"; let cases = Aux.product table in - Printf.printf "\nf\n%!"; let cases = List.map (List.fold_left Aux.Ints.inter full_set) cases in - Printf.printf "\ng\n%!"; let cases = Aux.unique_sorted (List.map Aux.Ints.elements cases) in - Printf.printf "\nh\n%!"; let cases = List.map (fun c_brs -> let c_brs = List.map (Array.get brs) c_brs in - List.fold_left (fun (phis,heads,bodies,neg_bodies) - (phi,(head,body,neg_body)) -> - phi::phis,head::heads,body@bodies,neg_body@neg_bodies) - ([],[],[],[]) c_brs + List.fold_left (fun + ((rhs_pos_acc, rhs_neg_acc, static_conjs_acc, conjs_acc), + heads, bodies, neg_bodies) + ((rhs_pos, rhs_neg, static_conjs, conjs), + (head, body, neg_body)) -> + (rhs_pos @ rhs_pos_acc, rhs_neg @ rhs_neg_acc, + static_conjs @ static_conjs_acc, conjs @ conjs_acc), + head::heads,body@bodies,neg_body@neg_bodies) + (([],[],conjs_4b,conjs_4b),[],[],[]) c_brs ) cases in - Printf.printf "\ni\n%!"; - let cases = List.filter (fun (phis,heads,bodies,neg_bodies) -> - let phi = Formula.And phis in + (* 7m *) + let cases = List.filter (fun ((_,_,static_phis,_), + heads,bodies,neg_bodies) -> + let phi = Formula.And static_phis in let rphi = Solver.M.register_formula phi in - (* {{{ log entry *) + (* {{{ log entry *) if !debug_level > 3 then ( - (* do not print, because it generates too many - answers -- too little constraints per number of - variables when considering a single branch *) - (* - let assgn = Solver.M.evaluate struc rphi in - let avars = List.map Formula.var_str - (FormulaOps.free_vars phi) in - let atups = - AssignmentSet.tuples struc.Structure.elements - avars assgn in *) + (* do not print, because it generates too many + answers -- too little constraints per number of + variables when considering a single branch *) + (* + let assgn = Solver.M.evaluate struc rphi in + let avars = List.map Formula.var_str + (FormulaOps.free_vars phi) in + let atups = + AssignmentSet.tuples struc.Structure.elements + avars assgn in *) Printf.printf "evaluating: %s -- simpl %s\n%!" (Formula.str phi) (Solver.M.formula_str rphi) - (* (List.length atups) *) + (* (List.length atups) *) ); (* }}} *) let res = Solver.M.check_formula struc rphi in @@ -2015,11 +2140,27 @@ ); (* }}} *) res) cases in - Printf.printf "\nj\n%!"; List.map (fun case -> lead, case) cases ) rules_brs ) loc_next_classes in - (* {{{ log entry *) + (* 7n *) + let terminal_brs = + List.map (function + | [], body, neg_body -> [Const "_TERMINAL_"], body, neg_body + | _ -> assert false) terminal_rules in + let terminal_4b, terminal_brs = + translate_branches struc masks static_rnames dyn_rels terminal_brs in + + (* let loc_toss_rules = *) + Array.mapi (fun loc rules_brs -> + List.map (fun (lead, brs) -> + + ignore (terminal_4b, terminal_brs) + + ) rules_brs + ) loc_toss_rules; + + (* {{{ log entry *) if !debug_level > 1 then ( Array.iteri (fun loc rules_brs -> Printf.printf "Rule translations for loc %d:\n%!" loc; @@ -2106,6 +2247,7 @@ effort, horizon, heur_adv_ratio let initialize_game state player game_descr startcl = + translate_game game_descr; if (Some game_descr) = !tictactoe_descr then manual_game := "tictactoe"; if (Some game_descr) = !breakthrough_descr then manual_game := "breakthrough"; if (Some game_descr) = !connect5_descr then manual_game := "connect5"; Modified: trunk/Toss/Play/Game.ml =================================================================== --- trunk/Toss/Play/Game.ml 2011-02-03 20:36:45 UTC (rev 1309) +++ trunk/Toss/Play/Game.ml 2011-02-04 15:23:14 UTC (rev 1310) @@ -781,14 +781,14 @@ gen_moves grid_size rules model location in if moves = [| |] then (* terminal position *) let res = - (* * + (* *) Array.map (fun expr -> 100000. *. Solver.M.get_real_val expr model) location.Arena.payoffs_pp (* see [let payoff] above *) - * *) + (* * play_evgame grid_size model time subgames.(loc) - (* *) + * *) in (* {{{ log entry *) if !debug_level > 4 then ( @@ -808,14 +808,14 @@ else if n = 0 then begin (* terminal after postconditions *) let res = (* play_evgame grid_size model time subgames.(loc) *) - (* * + (* *) Array.map (fun expr -> 100000. *. Solver.M.get_real_val expr model) location.Arena.payoffs_pp - * *) + (* * play_evgame grid_size model time subgames.(loc) - (* *) + * *) in (* {{{ log entry *) if !debug_level > 4 then ( Modified: trunk/Toss/Play/GameTest.ml =================================================================== --- trunk/Toss/Play/GameTest.ml 2011-02-03 20:36:45 UTC (rev 1309) +++ trunk/Toss/Play/GameTest.ml 2011-02-04 15:23:14 UTC (rev 1310) @@ -131,7 +131,7 @@ lazy (None, 4.0, state_of_file "./examples/Gomoku19x19.toss") let connect4_game = - lazy (None, 6.0, state_of_file "./examples/Connect4.toss") + lazy (None, 2.0, state_of_file "./examples/Connect4.toss") let chess_game = lazy (Some 400, 2.0, state_of_file "./examples/Chess.toss") @@ -843,7 +843,32 @@ Game.use_monotonic := true; ); + "connect4 avoid losing" >:: + (fun () -> + let state = update_game connect4_game +"[ | | + ] \" + ... ... ... + ... ... ... + ... ... ... ... + ... ... ... ... + ... ... ... + ... Q..Q ... + ... ... ... ... + ... ...P Q.. ... + ... ... ... + ... Q..P P.. + ... ... ... ... + ... Q..P P..P Q.. +\"" 0 in + Game.use_monotonic := false; + hard_case state 0 "should not attack" + (fun mov_s -> Printf.printf "avoid: %s\n" mov_s; + "Cross{1:f4}" <> mov_s && "Cross{1:f3}" <> mov_s); + Game.use_monotonic := true; +); + "connect4 endgame" >:: (fun () -> let state = update_game connect4_game @@ -933,7 +958,7 @@ let a () = match test_filter - ["Game:2:alpha_beta_ord-time 8 16 32:15:connect4 simple"] + ["Game:2:alpha_beta_ord-time 8 16 32:16:connect4 avoid losing"] tests with | Some tests -> ignore (run_test_tt ~verbose:true tests) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2011-02-03 20:36:50
|
Revision: 1309 http://toss.svn.sourceforge.net/toss/?rev=1309&view=rev Author: lukaszkaiser Date: 2011-02-03 20:36:45 +0000 (Thu, 03 Feb 2011) Log Message: ----------- More timeout time (very quick stupid hack). Modified Paths: -------------- trunk/Toss/Server/Server.ml Modified: trunk/Toss/Server/Server.ml =================================================================== --- trunk/Toss/Server/Server.ml 2011-02-03 19:36:49 UTC (rev 1308) +++ trunk/Toss/Server/Server.ml 2011-02-03 20:36:45 UTC (rev 1309) @@ -366,7 +366,7 @@ | Some play, Some play_state -> play, play_state | _ -> assert false in - ignore (Unix.alarm (!playclock - time_used - 1)); + ignore (Unix.alarm (!playclock - time_used - 2)); let res = Game.suggest p ps in Game.cancel_timeout (); let mov_msg = This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2011-02-03 19:36:56
|
Revision: 1308 http://toss.svn.sourceforge.net/toss/?rev=1308&view=rev Author: lukaszkaiser Date: 2011-02-03 19:36:49 +0000 (Thu, 03 Feb 2011) Log Message: ----------- Small parameter changes. Modified Paths: -------------- trunk/Toss/GGP/GDL.ml trunk/Toss/examples/Checkers.toss trunk/Toss/examples/Gomoku.toss Modified: trunk/Toss/GGP/GDL.ml =================================================================== --- trunk/Toss/GGP/GDL.ml 2011-02-02 02:07:08 UTC (rev 1307) +++ trunk/Toss/GGP/GDL.ml 2011-02-03 19:36:49 UTC (rev 1308) @@ -2074,7 +2074,7 @@ player_name_terms := [|Const "X"; Const "O"|]; Game.use_monotonic := true; let effort, horizon, heur_adv_ratio = - 2, 100, 4.0 in + 4, 100, 4.0 in effort, horizon, heur_adv_ratio let initialize_game_connect4 state player game_descr startcl = @@ -2084,7 +2084,7 @@ player_name_terms := [|Const "WHITE"; Const "RED"|]; Game.use_monotonic := false; let effort, horizon, heur_adv_ratio = - 6, 100, 2.0 in + 8, 100, 2.0 in effort, horizon, heur_adv_ratio let initialize_game_breakthrough state player game_descr startcl = @@ -2093,7 +2093,7 @@ game_description := game_descr; player_name_terms := [|Const "WHITE"; Const "BLACK"|]; let effort, horizon, heur_adv_ratio = - 3, 100, 2.0 in + 4, 100, 2.0 in effort, horizon, heur_adv_ratio let initialize_game_pawn_whopping state player game_descr startcl = @@ -2102,7 +2102,7 @@ game_description := game_descr; player_name_terms := [|Const "X"; Const "O"|]; let effort, horizon, heur_adv_ratio = - 4, 100, 2.0 in + 8, 100, 2.0 in effort, horizon, heur_adv_ratio let initialize_game state player game_descr startcl = Modified: trunk/Toss/examples/Checkers.toss =================================================================== --- trunk/Toss/examples/Checkers.toss 2011-02-02 02:07:08 UTC (rev 1307) +++ trunk/Toss/examples/Checkers.toss 2011-02-03 19:36:49 UTC (rev 1308) @@ -1,5 +1,5 @@ PLAYERS 1, 2 -DATA depth: 2, adv_ratio: 2 +DATA depth: 4, adv_ratio: 2 REL IsFirst(x) = not ex z C(z, x) REL IsEight(x) = not ex z C(x, z) REL w(x) = W(x) or Wq(x) Modified: trunk/Toss/examples/Gomoku.toss =================================================================== --- trunk/Toss/examples/Gomoku.toss 2011-02-02 02:07:08 UTC (rev 1307) +++ trunk/Toss/examples/Gomoku.toss 2011-02-03 19:36:49 UTC (rev 1308) @@ -1,5 +1,5 @@ PLAYERS 1, 2 -DATA r1: circle, r2: line, adv_ratio: 4, depth: 1 +DATA r1: circle, r2: line, adv_ratio: 4, depth: 2 REL DiagA (x, y) = ex u (R(x, u) and C(u, y)) REL DiagB (x, y) = ex u (R(x, u) and C(y, u)) REL Row5 (x, y, z, v, w) = R(x, y) and R(y, z) and R(z, v) and R(v, w) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2011-02-02 02:07:14
|
Revision: 1307 http://toss.svn.sourceforge.net/toss/?rev=1307&view=rev Author: lukstafi Date: 2011-02-02 02:07:08 +0000 (Wed, 02 Feb 2011) Log Message: ----------- Connect4 non-monotonic in tests. Modified Paths: -------------- trunk/Toss/Play/GameTest.ml Modified: trunk/Toss/Play/GameTest.ml =================================================================== --- trunk/Toss/Play/GameTest.ml 2011-02-02 01:44:03 UTC (rev 1306) +++ trunk/Toss/Play/GameTest.ml 2011-02-02 02:07:08 UTC (rev 1307) @@ -131,7 +131,7 @@ lazy (None, 4.0, state_of_file "./examples/Gomoku19x19.toss") let connect4_game = - lazy (None, 4.0, state_of_file "./examples/Connect4.toss") + lazy (None, 6.0, state_of_file "./examples/Connect4.toss") let chess_game = lazy (Some 400, 2.0, state_of_file "./examples/Chess.toss") @@ -837,8 +837,10 @@ P Q Q +Q . . . \"" 0 in - easy_case state 0 "should attack" - (fun mov_s -> "Cross{1:a4}" = mov_s); + Game.use_monotonic := false; + easy_case state 0 "should attack" + (fun mov_s -> "Cross{1:a4}" = mov_s); + Game.use_monotonic := true; ); @@ -860,8 +862,10 @@ P P P Q Q . . \"" 0 in - hard_case state 0 "should defend" - (fun mov_s -> "Cross{1:e2}" = mov_s); + Game.use_monotonic := false; + hard_case state 0 "should defend" + (fun mov_s -> "Cross{1:e2}" = mov_s); + Game.use_monotonic := true ); @@ -929,7 +933,7 @@ let a () = match test_filter - ["Game:0:misc:2:play: checkers suggest first move depth 4"] + ["Game:2:alpha_beta_ord-time 8 16 32:15:connect4 simple"] tests with | Some tests -> ignore (run_test_tt ~verbose:true tests) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2011-02-02 01:44:10
|
Revision: 1306 http://toss.svn.sourceforge.net/toss/?rev=1306&view=rev Author: lukstafi Date: 2011-02-02 01:44:03 +0000 (Wed, 02 Feb 2011) Log Message: ----------- Timeout test suite. Bug fix related to postcondition handling. Modified Paths: -------------- trunk/Toss/Play/Game.ml trunk/Toss/Play/GameTest.ml Modified: trunk/Toss/Play/Game.ml =================================================================== --- trunk/Toss/Play/Game.ml 2011-02-02 00:00:24 UTC (rev 1305) +++ trunk/Toss/Play/Game.ml 2011-02-02 01:44:03 UTC (rev 1306) @@ -627,14 +627,17 @@ ) matchings)) let gen_models rules defined_rels model time moves = - Aux.array_map_some (fun mv -> + let res = + Aux.map_some (fun mv -> let rule = List.assoc mv.rule rules in Aux.map_option (fun (model, time, _) -> (* ignoring shifts, i.e. animation steps *) - {loc=mv.next_loc; struc=model; time=time}) + mv, {loc=mv.next_loc; struc=model; time=time}) (ContinuousRule.rewrite_single model time mv.embedding - rule mv.mv_time mv.parameters)) moves + rule mv.mv_time mv.parameters)) (Array.to_list moves) in + let moves, models = List.split res in + Array.of_list moves, Array.of_list models let debug_count = ref 0 @@ -797,7 +800,7 @@ else if !timeout then Array.map (fun _ -> 0.) graph.(loc).Arena.payoffs else - let models = + let moves, models = gen_models rules defined_rels model time moves in let n = Array.length models in if !timeout then @@ -879,7 +882,7 @@ aux alphas 0 in let betas = Array.make num_players infinity in let player = loc.Arena.player in - let models = + let moves, models = gen_models rules defined_rels state.struc state.time moves in if models = [| |] then let payoff = @@ -1026,7 +1029,7 @@ (* {{{ log entry *) if !debug_level > 3 then printf "toss: external\n"; (* }}} *) - let models = + let moves, models = gen_models rules defined_rels state.struc state.time moves in if models = [| |] then let payoff = @@ -1181,7 +1184,7 @@ upscore, Terminal (state, upscore, heuristic, payoff) else - let models = + let moves, models = gen_models rules defined_rels state.struc state.time moves in if models = [| |] then let payoff = Modified: trunk/Toss/Play/GameTest.ml =================================================================== --- trunk/Toss/Play/GameTest.ml 2011-02-02 00:00:24 UTC (rev 1305) +++ trunk/Toss/Play/GameTest.ml 2011-02-02 01:44:03 UTC (rev 1306) @@ -133,6 +133,12 @@ let connect4_game = lazy (None, 4.0, state_of_file "./examples/Connect4.toss") +let chess_game = + lazy (Some 400, 2.0, state_of_file "./examples/Chess.toss") + +let checkers_game = + lazy (Some 400, 2.0, state_of_file "./examples/Checkers.toss") + let breakthrough_heur_adv adv_ratio = let expanded_win1 = "ex y1, y2, y3, y4, y5, y6, y7, y8 (C(y1, y2) and C(y2, y3) and C(y3, y4) and C(y4, y5) and C(y5, y6) and C(y6, y7) and C(y7, y8) and W(y8))" in @@ -153,9 +159,6 @@ let breakthrough_heur = breakthrough_heur_adv 1.5 -let chess_game = - lazy (Some 400, 2.0, state_of_file "./examples/Chess.toss") - let chess_piece_value_heur = let white_val = "Sum (x | wP(x): 1) + Sum (x | wN(x): 3.2) + @@ -208,13 +211,12 @@ (horizon, heur_adv_ratio, state) loc msg pred = let p,ps = Game.initialize_default state ~heur_adv_ratio ?horizon ~loc ~effort ~search_method () in - let old_signal = - Sys.signal Sys.sigalrm - (Sys.Signal_handle (fun _ -> failwith "timeout")) in - ignore (Unix.alarm timer_sec); - (try let compute_move () = - Aux.unsome (Game.suggest p ps) in + ignore (Unix.alarm timer_sec); + let res = + Aux.unsome (Game.suggest p ps) in + Game.cancel_timeout (); + res in if randomize then try_n_times 5 state compute_move pred msg else @@ -223,11 +225,7 @@ assert_bool (Printf.sprintf "%s: Failed move: %s." msg move_str) (pred move_str) - with Failure "timeout" -> - assert_failure - (Printf.sprintf "suggest did not finish in %d seconds" timer_sec)); - ignore (Unix.alarm 0); - Sys.set_signal Sys.sigalrm old_signal + let misc_tests = "misc" >::: [ @@ -278,6 +276,19 @@ assert_bool "Game is not over yet -- some move expected." (move_opt <> None); ); + + "play: checkers suggest first move depth 4" >:: + (fun () -> + let horizon, heur_adv_ratio, state = + Lazy.force checkers_game in + let move_opt = (let p,ps = Game.initialize_default state + ~heur_adv_ratio ?horizon + ~loc:0 ~effort:4 + ~search_method:"alpha_beta_ord" () in + Game.suggest p ps) in + assert_bool "Game is not over yet -- some move expected." + (move_opt <> None); + ); "play: chess begin random play" >:: (fun () -> @@ -454,11 +465,13 @@ ] -let search_tests algo randomize effort_easy effort_medium effort_hard = - let easy_case = compute_try algo randomize effort_easy 240 - and medium_case = compute_try algo randomize effort_medium 600 - and hard_case = compute_try algo randomize effort_hard 1200 in - algo >::: [ +let search_tests algo comment randomize effort_easy time_easy effort_medium + time_medium effort_hard time_hard = + let easy_case = compute_try algo randomize effort_easy time_easy + and easy_big_case = compute_try algo randomize effort_easy time_medium + and medium_case = compute_try algo randomize effort_medium time_medium + and hard_case = compute_try algo randomize effort_hard time_hard in + (algo ^ "-" ^ comment) >::: [ "tictactoe suggest tie" >:: (fun () -> let state = update_game tictactoe_game @@ -701,7 +714,7 @@ ... ... ... ... ... ... ... ... \"" 0 in - easy_case state 0 "P should block" + easy_big_case state 0 "P should block" (fun mov_s -> "Cross{1:b5}" = mov_s); let state = update_game gomoku8x8_game @@ -723,7 +736,7 @@ ... ... ... ... ... ... ... ... \"" 0 in - easy_case state 0 "P should block with line" + easy_big_case state 0 "P should block with line" (fun mov_s -> "Cross{1:f7}" = mov_s); ); @@ -750,7 +763,7 @@ ... ... ... ... ... ... ... ... \"" 0 in - easy_case state 0 "P should block" + easy_big_case state 0 "P should block" (fun mov_s -> "Cross{1:a3}" = mov_s); ); @@ -777,7 +790,7 @@ ... ... ... ... ... ... ...Q ... \"" 0 in - easy_case state 0 "should block the open line" + easy_big_case state 0 "should block the open line" (fun mov_s -> "Cross{1:e7}" = mov_s); ); @@ -802,7 +815,7 @@ ... ... ... ... ... ... Q.. ... \"" 0 in - easy_case state 0 "should attack the diagonal" + easy_big_case state 0 "should attack the diagonal" (fun mov_s -> "Cross{1:d4}" = mov_s); ); @@ -856,7 +869,8 @@ let tests = "Game" >::: [ misc_tests; - search_tests "alpha_beta_ord" false 2 3 4; + search_tests "alpha_beta_ord" "effort 2 3 4" false 2 120 3 240 4 360; + search_tests "alpha_beta_ord" "time 8 16 32" false 10 8 10 16 10 32; ] let experiments = "Game" >::: [ @@ -915,7 +929,7 @@ let a () = match test_filter - ["Game:1:alpha_beta_ord:15:connect4 simple"] + ["Game:0:misc:2:play: checkers suggest first move depth 4"] tests with | Some tests -> ignore (run_test_tt ~verbose:true tests) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2011-02-02 00:00:32
|
Revision: 1305 http://toss.svn.sourceforge.net/toss/?rev=1305&view=rev Author: lukstafi Date: 2011-02-02 00:00:24 +0000 (Wed, 02 Feb 2011) Log Message: ----------- GDL translation: in progress (final assignment of GDL branches to Toss rules but not filtered yet). Minor fixes in iterative deepening. Restored Server tests. Modified Paths: -------------- trunk/Toss/Formula/Aux.ml trunk/Toss/GGP/GDL.ml trunk/Toss/GGP/GDLTest.ml trunk/Toss/Play/Game.ml trunk/Toss/Play/GameTest.ml trunk/Toss/Server/Server.ml trunk/Toss/Server/ServerGDLTest.in trunk/Toss/Server/ServerGDLTest.out trunk/Toss/Server/ServerTest.ml Modified: trunk/Toss/Formula/Aux.ml =================================================================== --- trunk/Toss/Formula/Aux.ml 2011-02-01 01:47:19 UTC (rev 1304) +++ trunk/Toss/Formula/Aux.ml 2011-02-02 00:00:24 UTC (rev 1305) @@ -457,8 +457,8 @@ let strip_spaces s = let (b, e) = (ref 0, ref ((String.length s) - 1)) in - while !b < !e && is_space (s.[!b]) do b := !b + 1 done; - while !b <= !e && is_space (s.[!e]) do e := !e - 1 done; + while !b < !e && is_space (s.[!b]) do incr b done; + while !b <= !e && is_space (s.[!e]) do decr e done; if !e < !b then "" else String.sub s !b (!e - !b + 1) let rec input_http_message file = Modified: trunk/Toss/GGP/GDL.ml =================================================================== --- trunk/Toss/GGP/GDL.ml 2011-02-01 01:47:19 UTC (rev 1304) +++ trunk/Toss/GGP/GDL.ml 2011-02-02 00:00:24 UTC (rev 1305) @@ -349,7 +349,10 @@ associated with every bit. The unique resulting sets are exactly the Toss rules precursors. - (7m) Include translated negation of the terminal condition. (Now we + (7m) Filter the final rule candidates by satisfiability in at + least one of aggregate playout states. + + (7n) Include translated negation of the terminal condition. (Now we build rewrite rules for a refinement of an equivalence class of (7b): from the branches with unifiers in the equiv class, from branches with unifiers more general than the equiv class, and from @@ -712,6 +715,11 @@ " " ^ neg_facts_str neg_body ^ ")" ) branches) +let rule_pretransl_str (heads, bodies, neg_bodies) = + "("^ facts_str bodies ^ + " " ^ neg_facts_str neg_bodies ^ "==>" ^ + String.concat "; " (List.map term_str heads) ^ ")" + let sb_str sb = String.concat ", " (List.map (fun (v,t)->v^":="^term_str t) sb) @@ -1772,71 +1780,69 @@ let toss_var term = let mask, _, _, blank = term_to_blank term in mask, Formula.fo_var_of_string (term_to_name blank) in - (* 7i *) - let state_terms = - Array.fold_left (fun acc rules_brs -> - List.fold_left (fun acc (lead, brs) -> - List.fold_left (fun acc -> function - | [next_arg], body, neg_body -> - let res = - List.fold_left (fun acc -> function - | "true", [true_arg] -> Terms.add true_arg acc - | "true", _ -> assert false - | _ -> acc) acc body in - let res = - List.fold_left (List.fold_left (fun acc -> function - | "true", [true_arg] -> Terms.add true_arg acc - | "true", _ -> assert false - | _ -> acc)) res neg_body in - Terms.add next_arg res - | _ -> assert false - ) acc brs - ) acc rules_brs) Terms.empty loc_next_classes in - let state_terms = Terms.elements state_terms in - (* {{{ log entry *) - if !debug_level > 2 then ( - Printf.printf "state_terms: %s\n%!" ( - String.concat ", " (List.map term_str state_terms)) - ); - (* }}} *) - let state_subterms = - Aux.concat_map (fun term -> - let mask, sb, m_sb, blanked = term_to_blank term in - List.map (fun (v,t) -> t, (mask, v, term)) sb - ) state_terms in - let conjs_4a rel args = - let ptups = List.map (fun arg -> - Aux.assoc_all arg state_subterms) args in - (* {{{ log entry *) - if !debug_level > 3 then ( - Printf.printf "conjs_4a: of %s = subterms %s\n%!" - (fact_str (rel,args)) (String.concat "; " ( - List.map (fun l -> String.concat ", " - (List.map (fun (_,_,term)->term_str term) l)) ptups)) - ); - (* }}} *) - let ptups = Aux.product ptups in - let res = - List.map (fun ptup -> - let rname = rel ^ "__" ^ String.concat "__" - (List.map (fun (mask,v,_)-> - term_to_name mask ^ "_" ^ v) ptup) in - let tup = List.map (fun (_,_,term) -> - snd (toss_var term)) ptup in - Formula.Rel (rname, Array.of_list tup)) ptups in - let res = Aux.unique_sorted res in - (* {{{ log entry *) - if !debug_level > 3 then ( - Printf.printf "conjs_4a: of %s = %s\n%!" - (fact_str (rel,args)) (Formula.str (Formula.And res)) - ); - (* }}} *) - res in let loc_toss_rules = Array.mapi (fun loc rules_brs -> Aux.concat_map (fun (lead, brs) -> + (* 7i *) + (* Do not flatten the already built super-partition. *) + let state_terms = + List.fold_left (fun acc -> function + | [next_arg], body, neg_body -> + let res = + List.fold_left (fun acc -> function + | "true", [true_arg] -> Terms.add true_arg acc + | "true", _ -> assert false + | _ -> acc) acc body in + let res = + List.fold_left (List.fold_left (fun acc -> function + | "true", [true_arg] -> Terms.add true_arg acc + | "true", _ -> assert false + | _ -> acc)) res neg_body in + Terms.add next_arg res + | _ -> assert false + ) Terms.empty brs in + let state_terms = Terms.elements state_terms in + (* {{{ log entry *) + if !debug_level > 2 then ( + Printf.printf "state_terms: %s\n%!" ( + String.concat ", " (List.map term_str state_terms)) + ); + (* }}} *) + let state_subterms = + Aux.concat_map (fun term -> + let mask, sb, m_sb, blanked = term_to_blank term in + List.map (fun (v,t) -> t, (mask, v, term)) sb + ) state_terms in + let conjs_4a rel args = + let ptups = List.map (fun arg -> + Aux.assoc_all arg state_subterms) args in + (* {{{ log entry *) + if !debug_level > 3 then ( + Printf.printf "conjs_4a: of %s = subterms %s\n%!" + (fact_str (rel,args)) (String.concat "; " ( + List.map (fun l -> String.concat ", " + (List.map (fun (_,_,term)->term_str term) l)) ptups)) + ); + (* }}} *) + let ptups = Aux.product ptups in + let res = + List.map (fun ptup -> + let rname = rel ^ "__" ^ String.concat "__" + (List.map (fun (mask,v,_)-> + term_to_name mask ^ "_" ^ v) ptup) in + let tup = List.map (fun (_,_,term) -> + snd (toss_var term)) ptup in + Formula.Rel (rname, Array.of_list tup)) ptups in + let res = Aux.unique_sorted res in + (* {{{ log entry *) + if !debug_level > 3 then ( + Printf.printf "conjs_4a: of %s = %s\n%!" + (fact_str (rel,args)) (Formula.str (Formula.And res)) + ); + (* }}} *) + res in let brs = Aux.map_some (function - | [next_arg],body,neg_body as br -> + | [next_arg],body,neg_body -> let mask, sb, m_sb, blanked = term_to_blank next_arg in let rname = term_to_name mask in let _, svar = toss_var next_arg in @@ -1930,7 +1936,7 @@ Printf.printf "holds\n%!" ); (* }}} *) - Some (phi, br)) + Some (phi, (next_arg,body,neg_body))) else None | _ -> assert false) brs in (* 7j: TODO *) @@ -1942,8 +1948,13 @@ (List.fold_right (List.fold_right Atoms.add) neg_body acc) ) Atoms.empty brs in + Printf.printf "\na\n%!"; let atoms = Atoms.elements atoms in + Printf.printf "\nb\n%!"; let brs = Array.of_list brs in (* indexing branches *) + let full_set = Aux.ints_of_list + (Array.to_list (Array.mapi (fun i _ -> i) brs)) in + Printf.printf "\nc\n%!"; let table = List.map (fun atom -> let positives = Array.mapi (fun i (_,(_,body,_)) -> if List.mem atom body then Some i else None) brs in @@ -1954,32 +1965,72 @@ else None) brs in let negatives = Aux.map_some (fun x->x) (Array.to_list negatives) in - [Aux.Ints.empty; Aux.Ints.empty] (* TODO *) + Printf.printf "\nd\n%!"; + (* first those that allow "P" then those that allow "not P" *) + [Aux.Ints.diff full_set (Aux.ints_of_list negatives); + Aux.Ints.diff full_set (Aux.ints_of_list positives)] ) atoms in + Printf.printf "\ne\n%!"; let cases = Aux.product table in - let full_set = Aux.ints_of_list - (Array.to_list (Array.mapi (fun i _ -> i) brs)) in + Printf.printf "\nf\n%!"; let cases = List.map (List.fold_left Aux.Ints.inter full_set) cases in - - [lead, brs] + Printf.printf "\ng\n%!"; + let cases = + Aux.unique_sorted (List.map Aux.Ints.elements cases) in + Printf.printf "\nh\n%!"; + let cases = List.map (fun c_brs -> + let c_brs = List.map (Array.get brs) c_brs in + List.fold_left (fun (phis,heads,bodies,neg_bodies) + (phi,(head,body,neg_body)) -> + phi::phis,head::heads,body@bodies,neg_body@neg_bodies) + ([],[],[],[]) c_brs + ) cases in + Printf.printf "\ni\n%!"; + let cases = List.filter (fun (phis,heads,bodies,neg_bodies) -> + let phi = Formula.And phis in + let rphi = Solver.M.register_formula phi in + (* {{{ log entry *) + if !debug_level > 3 then ( + (* do not print, because it generates too many + answers -- too little constraints per number of + variables when considering a single branch *) + (* + let assgn = Solver.M.evaluate struc rphi in + let avars = List.map Formula.var_str + (FormulaOps.free_vars phi) in + let atups = + AssignmentSet.tuples struc.Structure.elements + avars assgn in *) + Printf.printf "evaluating: %s -- simpl %s\n%!" + (Formula.str phi) + (Solver.M.formula_str rphi) + (* (List.length atups) *) + ); + (* }}} *) + let res = Solver.M.check_formula struc rphi in + (* {{{ log entry *) + if !debug_level > 3 && res then ( + Printf.printf "holds\n%!" + ); + (* }}} *) + res) cases in + Printf.printf "\nj\n%!"; + List.map (fun case -> lead, case) cases ) rules_brs ) loc_next_classes in - (* (* {{{ log entry *) if !debug_level > 1 then ( Array.iteri (fun loc rules_brs -> Printf.printf "Rule translations for loc %d:\n%!" loc; - List.iter (fun ((lead,_,_), brs) -> - let brs = List.map snd brs in + List.iter (fun ((lead,_,_), (phis,heads,bodies,neg_bodies)) -> Printf.printf "Rule-translation: player %s move %s\n%s\n%!" (term_str loc_players.(loc)) (term_str lead) - (def_str ("action", brs)) + (rule_pretransl_str (heads,bodies,neg_bodies)) ) rules_brs; ) loc_toss_rules; ); (* }}} *) - *) struc (* @@ -2060,6 +2111,12 @@ if (Some game_descr) = !connect5_descr then manual_game := "connect5"; if (Some game_descr) = !connect4_descr then manual_game := "connect4"; if (Some game_descr) = !pawn_whopping_descr then manual_game:="pawn_whopping"; + (* {{{ log entry *) + if !debug_level > 0 then ( + Printf.printf "GDL.initialize_game: player=%s, game=%s, startcl=%d\n%!" + (term_str player) !manual_game startcl + ); + (* }}} *) match !manual_translation, !manual_game with | true, "tictactoe" -> initialize_game_tictactoe state player game_descr startcl @@ -2209,10 +2266,18 @@ let loc = state.Arena.cur_loc in let loc_player = state.Arena.game.Arena.graph.(loc).Arena.player in + (* {{{ log entry *) + if !debug_level > 0 then ( + Printf.printf + "GDL.our_turn: loc=%d, loc_player=%d, playing_as=%s, player_name=%s, res=%b\n%!" + loc loc_player (term_str !playing_as) + (term_str !player_name_terms.(loc_player)) + (!player_name_terms.(loc_player) = !playing_as) + ); + (* }}} *) !player_name_terms.(loc_player) = !playing_as let translate_move_tictactoe rule emb new_state = - print_endline "Translate"; let struc = new_state.Arena.struc in let elem = snd (List.hd emb) in let c, r = @@ -2270,6 +2335,7 @@ | _ -> assert false let translate_move rule emb new_state = + let res = match !manual_translation, !manual_game with | true, "tictactoe" -> translate_move_tictactoe rule emb new_state @@ -2285,3 +2351,10 @@ failwith ("GDL: manual translation of unknown game "^game) | false, _ -> failwith "GDL: automatic translation not finished yet" + in + (* {{{ log entry *) + if !debug_level > 0 then ( + Printf.printf "GDL.translate_move: %s\n%!" res + ); + (* }}} *) + res Modified: trunk/Toss/GGP/GDLTest.ml =================================================================== --- trunk/Toss/GGP/GDLTest.ml 2011-02-01 01:47:19 UTC (rev 1304) +++ trunk/Toss/GGP/GDLTest.ml 2011-02-02 00:00:24 UTC (rev 1305) @@ -78,7 +78,8 @@ "connect5" >:: (fun () -> - GDL.debug_level := 3; + todo "Only log would be interesting at this point."; + (* GDL.debug_level := 3; *) let connect5 = load_rules "./GGP/examples/connect5.gdl" in let gdef = GDL.translate_game connect5 in () @@ -86,6 +87,7 @@ "breakthrough" >:: (fun () -> + todo "Only log would be interesting at this point."; let breakthrough = load_rules "./GGP/examples/breakthrough.gdl" in let gdef = GDL.translate_game breakthrough in () @@ -95,7 +97,7 @@ ] -let a () = +let a = Aux.run_test_if_target "GDLTest" tests let a () = @@ -106,7 +108,7 @@ | Some tests -> ignore (run_test_tt ~verbose:true tests) | None -> () -let a = +let a () = GDL.debug_level := 4; let breakthrough = load_rules "./GGP/examples/breakthrough.gdl" in let gdef = GDL.translate_game breakthrough in Modified: trunk/Toss/Play/Game.ml =================================================================== --- trunk/Toss/Play/Game.ml 2011-02-01 01:47:19 UTC (rev 1304) +++ trunk/Toss/Play/Game.ml 2011-02-02 00:00:24 UTC (rev 1305) @@ -757,7 +757,9 @@ ("\n"^Str.first_chars "|||||||||||" (depth0-depth)) ("\n" ^ Structure.str model)); (* }}} *) - if depth < 1 || !timeout then ( (* leaf position *) + if !timeout then (* will be handled by i.deep. *) + Array.map (fun _ -> 0.) graph.(loc).Arena.payoffs + else if depth < 1 then ( (* leaf position *) let res = match pre_heur with | Some h -> h @@ -769,21 +771,21 @@ printf ", leaf %d heur: %F %!" player res.(player) ); (* }}} *) - res + res ) else let location = graph.(loc) in let moves = gen_moves grid_size rules model location in if moves = [| |] then (* terminal position *) let res = - (* *) + (* * Array.map (fun expr -> 100000. *. Solver.M.get_real_val expr model) location.Arena.payoffs_pp (* see [let payoff] above *) - (* * + * *) play_evgame grid_size model time subgames.(loc) - * *) + (* *) in (* {{{ log entry *) if !debug_level > 4 then ( @@ -793,22 +795,24 @@ (* }}} *) res else if !timeout then - play_evgame grid_size model time subgames.(loc) + Array.map (fun _ -> 0.) graph.(loc).Arena.payoffs else let models = gen_models rules defined_rels model time moves in let n = Array.length models in - if n = 0 then begin (* terminal after postconditions *) + if !timeout then + Array.map (fun _ -> 0.) graph.(loc).Arena.payoffs + else if n = 0 then begin (* terminal after postconditions *) let res = (* play_evgame grid_size model time subgames.(loc) *) - (* *) - Array.map (fun expr -> - 100000. *. - Solver.M.get_real_val expr model) - location.Arena.payoffs_pp - (* * + (* * + Array.map (fun expr -> + 100000. *. + Solver.M.get_real_val expr model) + location.Arena.payoffs_pp + * *) play_evgame grid_size model time subgames.(loc) - * *) + (* *) in (* {{{ log entry *) if !debug_level > 4 then ( @@ -839,7 +843,7 @@ Some heuristics end else None in let rec aux best i = - if i < n && not !timeout then + if i < n && not !timeout then ( let pos = index.(i) in let state = models.(pos) in let sub_heur = @@ -859,18 +863,18 @@ sub_heur) else if sub_heur.(player) > best.(player) then aux sub_heur (i+1) - else aux best (i+1) - else if !timeout then best - else ( - betas.(player) <- best.(player); + else aux best (i+1)) + else if !timeout then best + else ( + betas.(player) <- best.(player); (* {{{ log entry *) - if !debug_level > 2 && (depth0 > 2 || !debug_level > 4) && - (depth > 1 || !debug_level > 3) - then ( - printf ", best %d maximax: %F. %!" player - best.(player)); + if !debug_level > 2 && (depth0 > 2 || !debug_level > 4) && + (depth > 1 || !debug_level > 3) + then ( + printf ", best %d maximax: %F. %!" player + best.(player)); (* }}} *) - best) in + best) in let alphas = Array.make num_players neg_infinity in aux alphas 0 in let betas = Array.make num_players infinity in @@ -885,23 +889,45 @@ Aux.Right payoff else let cur_depth = ref 0 in + (* {{{ log entry *) + if !debug_level > 1 && (depth > 2 || !debug_level > 3) then ( + Printf.printf "\n\nIterative-deepening: depth %d\n%!" + (!cur_depth + 1) + ); + (* }}} *) let scores = Array.map (maximax_tree None player betas !cur_depth) models in + incr cur_depth; while not !timeout && !cur_depth < depth do + (* {{{ log entry *) + if !debug_level > 1 && (depth > 2 || !debug_level > 3) then ( + Printf.printf "\n\nIterative-deepening: depth %d\n%!" + (!cur_depth + 1) + ); + (* }}} *) let index = Array.init (Array.length models) (fun i->i) in Array.sort (fun j i-> compare scores.(i).(player) scores.(j).(player)) index; let betas = Array.make num_players infinity in let new_scores = - Array.map (fun i -> - maximax_tree None player betas !cur_depth models.(i)) + Array.map (fun j -> + maximax_tree None player betas !cur_depth models.(j)) index in incr cur_depth; if not !timeout then Array.iteri (fun i j -> (* inverting the permutation *) - scores.(j) <- new_scores.(i)) index + scores.(j) <- new_scores.(i)) index; + (* {{{ log entry *) + if !debug_level > 1 && (depth > 2 || !debug_level > 3) then ( + Printf.printf "\nIterative-deepening: depth %d scores:\n%!" + !cur_depth; + Array.iteri (fun i score -> + Printf.printf "Structure:%s -- score %F\n" + (Structure.str models.(i).struc) score.(player)) scores + ); + (* }}} *) done; let _, best = find_best_score ~use_det_setting:true cooperative player scores Modified: trunk/Toss/Play/GameTest.ml =================================================================== --- trunk/Toss/Play/GameTest.ml 2011-02-01 01:47:19 UTC (rev 1304) +++ trunk/Toss/Play/GameTest.ml 2011-02-02 00:00:24 UTC (rev 1305) @@ -806,6 +806,29 @@ (fun mov_s -> "Cross{1:d4}" = mov_s); ); + "connect4 simple" >:: + (fun () -> + let state = update_game connect4_game +"[ | | + ] \" + + . . . . . . . + + . . . . . . . + + . . . . . . . + + P . . . . . . + + P . . . . . . + + P Q Q +Q . . . +\"" 0 in + easy_case state 0 "should attack" + (fun mov_s -> "Cross{1:a4}" = mov_s); +); + + "connect4 endgame" >:: (fun () -> let state = update_game connect4_game @@ -888,9 +911,11 @@ let a () = Game.set_debug_level 10 -let a = +let a () = Game.use_monotonic := false + +let a () = match test_filter - ["Game:1:alpha_beta_ord:1:tictactoe suggest optimal single"] + ["Game:1:alpha_beta_ord:15:connect4 simple"] tests with | Some tests -> ignore (run_test_tt ~verbose:true tests) Modified: trunk/Toss/Server/Server.ml =================================================================== --- trunk/Toss/Server/Server.ml 2011-02-01 01:47:19 UTC (rev 1304) +++ trunk/Toss/Server/Server.ml 2011-02-02 00:00:24 UTC (rev 1305) @@ -517,8 +517,6 @@ let _ = (* Test against being called from a test... *) - let target_name1 = "GameTest" - and target_name2 = "TossTest" in let file_from_path p = String.sub p (String.rindex p '/'+1) (String.length p - String.rindex p '/' - 1) in @@ -526,10 +524,9 @@ String.sub p 0 (String.rindex p '/') in let test_fname = let fname = file_from_path Sys.executable_name in - String.length fname >= String.length target_name1 && - String.sub fname 0 (String.length target_name1) = target_name1 || - String.length fname >= String.length target_name2 && - String.sub fname 0 (String.length target_name2) = target_name2 + Printf.printf "fname: %s\n%!" fname; + let len = String.length fname in + Str.string_match (Str.regexp ".*Test.*") fname 0 in (* so that the server is not started by the test suite. *) if not test_fname then ( Modified: trunk/Toss/Server/ServerGDLTest.in =================================================================== --- trunk/Toss/Server/ServerGDLTest.in 2011-02-01 01:47:19 UTC (rev 1304) +++ trunk/Toss/Server/ServerGDLTest.in 2011-02-02 00:00:24 UTC (rev 1305) @@ -3,9 +3,9 @@ Sender: GAMEMASTER Receiver: GAMEPLAYER Content-type: text/acl -Content-length: 1589 +Content-length: 1661 -(START MATCH.3316980891 X ((ROLE X) (ROLE O) (INIT (CELL 1 1 B)) (INIT (CELL 1 2 B)) (INIT (CELL 1 3 B)) (INIT (CELL 2 1 B)) (INIT (CELL 2 2 B)) (INIT (CELL 2 3 B)) (INIT (CELL 3 1 B)) (INIT (CELL 3 2 B)) (INIT (CELL 3 3 B)) (INIT (CONTROL X)) (<= (NEXT (CELL ?X ?Y ?PLAYER)) (DOES ?PLAYER (MARK ?X ?Y))) (<= (NEXT (CELL ?X ?Y ?MARK)) (TRUE (CELL ?X ?Y ?MARK)) (DOES ?PLAYER (MARK ?M ?N)) (DISTINCTCELL ?X ?Y ?M ?N)) (<= (NEXT (CONTROL X)) (TRUE (CONTROL O))) (<= (NEXT (CONTROL O)) (TRUE (CONTROL X))) (<= (ROW ?X ?PLAYER) (TRUE (CELL ?X 1 ?PLAYER)) (TRUE (CELL ?X 2 ?PLAYER)) (TRUE (CELL ?X 3 ?PLAYER))) (<= (COLUMN ?Y ?PLAYER) (TRUE (CELL 1 ?Y ?PLAYER)) (TRUE (CELL 2 ?Y ?PLAYER)) (TRUE (CELL 3 ?Y ?PLAYER))) (<= (DIAGONAL ?PLAYER) (TRUE (CELL 1 1 ?PLAYER)) (TRUE (CELL 2 2 ?PLAYER)) (TRUE (CELL 3 3 ?PLAYER))) (<= (DIAGONAL ?PLAYER) (TRUE (CELL 1 3 ?PLAYER)) (TRUE (CELL 2 2 ?PLAYER)) (TRUE (CELL 3 1 ?PLAYER))) (<= (LINE ?PLAYER) (ROW ?X ?PLAYER)) (<= (LINE ?PLAYER) (COLUMN ?Y ?PLAYER)) (<= (LINE ?PLAYER) (DIAGONAL ?PLAYER)) (<= OPEN (TRUE (CELL ?X ?Y B))) (<= (DISTINCTCELL ?X ?Y ?M ?N) (DISTINCT ?X ?M)) (<= (DISTINCTCELL ?X ?Y ?M ?N) (DISTINCT ?Y ?N)) (<= (LEGAL ?PLAYER (MARK ?X ?Y)) (TRUE (CELL ?X ?Y B)) (TRUE (CONTROL ?PLAYER))) (<= (LEGAL ?PLAYER NOOP) (NOT (TRUE (CONTROL ?PLAYER)))) (<= (GOAL ?PLAYER 100) (LINE ?PLAYER)) (<= (GOAL ?PLAYER 50) (NOT (LINE X)) (NOT (LINE O)) (NOT OPEN)) (<= (GOAL ?PLAYER1 0) (LINE ?PLAYER2) (DISTINCT ?PLAYER1 ?PLAYER2)) (<= (GOAL ?PLAYER 0) (NOT (LINE X)) (NOT (LINE O)) OPEN) (<= TERMINAL (LINE ?PLAYER)) (<= TERMINAL (NOT OPEN))) 30 30) +(START MATCH.3316980891 XPLAYER ((ROLE XPLAYER) (ROLE OPLAYER) (INIT (CELL 1 1 B)) (INIT (CELL 1 2 B)) (INIT (CELL 1 3 B)) (INIT (CELL 2 1 B)) (INIT (CELL 2 2 B)) (INIT (CELL 2 3 B)) (INIT (CELL 3 1 B)) (INIT (CELL 3 2 B)) (INIT (CELL 3 3 B)) (INIT (CONTROL XPLAYER)) (<= (NEXT (CELL ?X ?Y ?PLAYER)) (DOES ?PLAYER (MARK ?X ?Y))) (<= (NEXT (CELL ?X ?Y ?MARK)) (TRUE (CELL ?X ?Y ?MARK)) (DOES ?PLAYER (MARK ?M ?N)) (DISTINCTCELL ?X ?Y ?M ?N)) (<= (NEXT (CONTROL XPLAYER)) (TRUE (CONTROL OPLAYER))) (<= (NEXT (CONTROL OPLAYER)) (TRUE (CONTROL XPLAYER))) (<= (ROW ?X ?PLAYER) (TRUE (CELL ?X 1 ?PLAYER)) (TRUE (CELL ?X 2 ?PLAYER)) (TRUE (CELL ?X 3 ?PLAYER))) (<= (COLUMN ?Y ?PLAYER) (TRUE (CELL 1 ?Y ?PLAYER)) (TRUE (CELL 2 ?Y ?PLAYER)) (TRUE (CELL 3 ?Y ?PLAYER))) (<= (DIAGONAL ?PLAYER) (TRUE (CELL 1 1 ?PLAYER)) (TRUE (CELL 2 2 ?PLAYER)) (TRUE (CELL 3 3 ?PLAYER))) (<= (DIAGONAL ?PLAYER) (TRUE (CELL 1 3 ?PLAYER)) (TRUE (CELL 2 2 ?PLAYER)) (TRUE (CELL 3 1 ?PLAYER))) (<= (LINE ?PLAYER) (ROW ?X ?PLAYER)) (<= (LINE ?PLAYER) (COLUMN ?Y ?PLAYER)) (<= (LINE ?PLAYER) (DIAGONAL ?PLAYER)) (<= OPEN (TRUE (CELL ?X ?Y B))) (<= (DISTINCTCELL ?X ?Y ?M ?N) (DISTINCT ?X ?M)) (<= (DISTINCTCELL ?X ?Y ?M ?N) (DISTINCT ?Y ?N)) (<= (LEGAL ?PLAYER (MARK ?X ?Y)) (TRUE (CELL ?X ?Y B)) (TRUE (CONTROL ?PLAYER))) (<= (LEGAL ?PLAYER NOOP) (NOT (TRUE (CONTROL ?PLAYER)))) (<= (GOAL ?PLAYER 100) (LINE ?PLAYER)) (<= (GOAL ?PLAYER 50) (NOT (LINE XPLAYER)) (NOT (LINE OPLAYER)) (NOT OPEN)) (<= (GOAL ?PLAYER1 0) (LINE ?PLAYER2) (DISTINCT ?PLAYER1 ?PLAYER2)) (<= (GOAL ?PLAYER 0) (NOT (LINE XPLAYER)) (NOT (LINE OPLAYER)) OPEN) (<= TERMINAL (LINE ?PLAYER)) (<= TERMINAL (NOT OPEN))) 30 30) POST / HTTP/1.0 Accept: text/delim Modified: trunk/Toss/Server/ServerGDLTest.out =================================================================== --- trunk/Toss/Server/ServerGDLTest.out 2011-02-01 01:47:19 UTC (rev 1304) +++ trunk/Toss/Server/ServerGDLTest.out 2011-02-02 00:00:24 UTC (rev 1305) @@ -27,7 +27,7 @@ Content-type: text/acl Content-length: 10 -(MARK 3 3) +(MARK 1 2) HTTP/1.0 200 OK Content-type: text/acl Content-length: 4 Modified: trunk/Toss/Server/ServerTest.ml =================================================================== --- trunk/Toss/Server/ServerTest.ml 2011-02-01 01:47:19 UTC (rev 1304) +++ trunk/Toss/Server/ServerTest.ml 2011-02-02 00:00:24 UTC (rev 1305) @@ -2,20 +2,22 @@ open Aux let tests = "server" >::: [ + "check ServerTest.in response" >:: (fun () -> let in_ch = open_in "./Server/ServerTest.in" in let out_ch = open_out "./Server/ServerTest.temp" in - (*(try while true do + (try while true do Server.req_handle in_ch out_ch done - with End_of_file -> ());*) + with End_of_file -> ()); close_in in_ch; close_out out_ch; let result = Aux.input_file (open_in "./Server/ServerTest.temp") in let target = Aux.input_file (open_in "./Server/ServerTest.out") in Sys.remove "./Server/ServerTest.temp"; - assert_equal ~printer:(fun x->x) target result + assert_equal ~printer:(fun x->x) + (strip_spaces target) (strip_spaces result) ); "ServerGDLTest.in GDL Tic-Tac-Toe" >:: @@ -27,9 +29,10 @@ GDL.manual_game := "tictactoe"; let in_ch = open_in "./Server/ServerGDLTest.in" in let out_ch = open_out "./Server/ServerGDLTest.temp" in - (* (try while true do + Game.deterministic_suggest := true; + (try while true do Server.req_handle in_ch out_ch done - with End_of_file -> ()); *) + with End_of_file -> ()); close_in in_ch; close_out out_ch; Game.deterministic_suggest := old_det_suggest; let result = @@ -37,9 +40,12 @@ let target = Aux.input_file (open_in "./Server/ServerGDLTest.out") in Sys.remove "./Server/ServerGDLTest.temp"; - assert_equal ~printer:(fun x->x) target result + assert_equal ~printer:(fun x->x) + (strip_spaces target) (strip_spaces result) ); + ] let a = + GDL.top_exec_path := "."; Aux.run_test_if_target "ServerTest" tests This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2011-02-01 01:47:25
|
Revision: 1304 http://toss.svn.sourceforge.net/toss/?rev=1304&view=rev Author: lukstafi Date: 2011-02-01 01:47:19 +0000 (Tue, 01 Feb 2011) Log Message: ----------- Alpha-beta: reverting to using payoffs in terminal subtrees. Modified Paths: -------------- trunk/Toss/Play/Game.ml Modified: trunk/Toss/Play/Game.ml =================================================================== --- trunk/Toss/Play/Game.ml 2011-02-01 01:36:13 UTC (rev 1303) +++ trunk/Toss/Play/Game.ml 2011-02-01 01:47:19 UTC (rev 1304) @@ -776,14 +776,14 @@ gen_moves grid_size rules model location in if moves = [| |] then (* terminal position *) let res = - (* * + (* *) Array.map (fun expr -> 100000. *. - Solver.M.get_real_val expr state.struc) + Solver.M.get_real_val expr model) location.Arena.payoffs_pp (* see [let payoff] above *) - * *) + (* * play_evgame grid_size model time subgames.(loc) - (* *) + * *) in (* {{{ log entry *) if !debug_level > 4 then ( @@ -801,14 +801,14 @@ if n = 0 then begin (* terminal after postconditions *) let res = (* play_evgame grid_size model time subgames.(loc) *) - (* * + (* *) Array.map (fun expr -> 100000. *. - Solver.M.get_real_val expr state.struc) + Solver.M.get_real_val expr model) location.Arena.payoffs_pp + (* * + play_evgame grid_size model time subgames.(loc) * *) - play_evgame grid_size model time subgames.(loc) - (* *) in (* {{{ log entry *) if !debug_level > 4 then ( This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2011-02-01 01:36:19
|
Revision: 1303 http://toss.svn.sourceforge.net/toss/?rev=1303&view=rev Author: lukstafi Date: 2011-02-01 01:36:13 +0000 (Tue, 01 Feb 2011) Log Message: ----------- Alpha-beta: logging fix. Modified Paths: -------------- trunk/Toss/Play/Game.ml Modified: trunk/Toss/Play/Game.ml =================================================================== --- trunk/Toss/Play/Game.ml 2011-02-01 00:37:25 UTC (rev 1302) +++ trunk/Toss/Play/Game.ml 2011-02-01 01:36:13 UTC (rev 1303) @@ -775,14 +775,23 @@ let moves = gen_moves grid_size rules model location in if moves = [| |] then (* terminal position *) - (* * - Array.map (fun expr -> - 100000. *. - Solver.M.get_real_val expr state.struc) - location.Arena.payoffs_pp (* see [let payoff] above *) - * *) - play_evgame grid_size model time subgames.(loc) - (* *) + let res = + (* * + Array.map (fun expr -> + 100000. *. + Solver.M.get_real_val expr state.struc) + location.Arena.payoffs_pp (* see [let payoff] above *) + * *) + play_evgame grid_size model time subgames.(loc) + (* *) + in + (* {{{ log entry *) + if !debug_level > 4 then ( + let player = graph.(loc).Arena.player in + printf ", terminal %d heur: %F %!" player res.(player) + ); + (* }}} *) + res else if !timeout then play_evgame grid_size model time subgames.(loc) else This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2011-02-01 00:37:31
|
Revision: 1302 http://toss.svn.sourceforge.net/toss/?rev=1302&view=rev Author: lukstafi Date: 2011-02-01 00:37:25 +0000 (Tue, 01 Feb 2011) Log Message: ----------- Alpha-beta: reverting to unmodified heuristics in terminal subtrees. Modified Paths: -------------- trunk/Toss/Play/Game.ml Modified: trunk/Toss/Play/Game.ml =================================================================== --- trunk/Toss/Play/Game.ml 2011-02-01 00:23:05 UTC (rev 1301) +++ trunk/Toss/Play/Game.ml 2011-02-01 00:37:25 UTC (rev 1302) @@ -775,14 +775,14 @@ let moves = gen_moves grid_size rules model location in if moves = [| |] then (* terminal position *) - (* *) + (* * Array.map (fun expr -> 100000. *. Solver.M.get_real_val expr state.struc) location.Arena.payoffs_pp (* see [let payoff] above *) - (* * + * *) play_evgame grid_size model time subgames.(loc) - * *) + (* *) else if !timeout then play_evgame grid_size model time subgames.(loc) else @@ -792,14 +792,14 @@ if n = 0 then begin (* terminal after postconditions *) let res = (* play_evgame grid_size model time subgames.(loc) *) - (* *) + (* * Array.map (fun expr -> 100000. *. Solver.M.get_real_val expr state.struc) location.Arena.payoffs_pp - (* * + * *) play_evgame grid_size model time subgames.(loc) - * *) + (* *) in (* {{{ log entry *) if !debug_level > 4 then ( This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2011-02-01 00:23:12
|
Revision: 1301 http://toss.svn.sourceforge.net/toss/?rev=1301&view=rev Author: lukstafi Date: 2011-02-01 00:23:05 +0000 (Tue, 01 Feb 2011) Log Message: ----------- Iterative deepening in alpha-beta: bug fix. Modified Paths: -------------- trunk/Toss/Play/Game.ml trunk/Toss/Play/GameTest.ml Modified: trunk/Toss/Play/Game.ml =================================================================== --- trunk/Toss/Play/Game.ml 2011-02-01 00:03:04 UTC (rev 1300) +++ trunk/Toss/Play/Game.ml 2011-02-01 00:23:05 UTC (rev 1301) @@ -775,13 +775,14 @@ let moves = gen_moves grid_size rules model location in if moves = [| |] then (* terminal position *) - (* + (* *) Array.map (fun expr -> 100000. *. Solver.M.get_real_val expr state.struc) location.Arena.payoffs_pp (* see [let payoff] above *) - *) + (* * play_evgame grid_size model time subgames.(loc) + * *) else if !timeout then play_evgame grid_size model time subgames.(loc) else @@ -791,13 +792,14 @@ if n = 0 then begin (* terminal after postconditions *) let res = (* play_evgame grid_size model time subgames.(loc) *) - (* + (* *) Array.map (fun expr -> 100000. *. Solver.M.get_real_val expr state.struc) location.Arena.payoffs_pp - *) + (* * play_evgame grid_size model time subgames.(loc) + * *) in (* {{{ log entry *) if !debug_level > 4 then ( @@ -874,24 +876,27 @@ Aux.Right payoff else let cur_depth = ref 0 in - let scores = ref - (Array.map (maximax_tree None player betas !cur_depth) models) in + let scores = + Array.map (maximax_tree None player betas !cur_depth) models in while not !timeout && !cur_depth < depth do let index = Array.init (Array.length models) (fun i->i) in Array.sort (fun j i-> compare - !scores.(i).(player) !scores.(j).(player)) index; + scores.(i).(player) scores.(j).(player)) index; let betas = Array.make num_players infinity in let new_scores = Array.map (fun i -> maximax_tree None player betas !cur_depth models.(i)) index in incr cur_depth; - if not !timeout then scores := new_scores + if not !timeout then + Array.iteri (fun i j -> + (* inverting the permutation *) + scores.(j) <- new_scores.(i)) index done; let _, best = - find_best_score ~use_det_setting:true cooperative player !scores - (Array.map (fun _ -> 1) !scores) in + find_best_score ~use_det_setting:true cooperative player scores + (Array.map (fun _ -> 1) scores) in let state = models.(best) in (* {{{ log entry *) if !debug_level > 0 && (depth > 1 || !debug_level > 3) Modified: trunk/Toss/Play/GameTest.ml =================================================================== --- trunk/Toss/Play/GameTest.ml 2011-02-01 00:03:04 UTC (rev 1300) +++ trunk/Toss/Play/GameTest.ml 2011-02-01 00:23:05 UTC (rev 1301) @@ -267,6 +267,7 @@ "play: chess suggest first move" >:: (fun () -> + skip_if true "loading takes long, worked last time"; let horizon, heur_adv_ratio, state = Lazy.force chess_game in let move_opt = (let p,ps = Game.initialize_default state @@ -280,6 +281,7 @@ "play: chess begin random play" >:: (fun () -> + skip_if true "loading takes long, worked last time"; let _, heur_adv_ratio, state = Lazy.force chess_game in let struc = state.Arena.struc in @@ -350,6 +352,7 @@ "chess draw" >:: (fun () -> + skip_if true "loading takes long, worked last time"; let horizon, heur_adv_ratio, state = update_game chess_game "[a1, b1, c1, d1, e1, f1, g1, h1, a2, b2, c2, d2, e2, f2, g2, h2, a3, b3, c3, d3, e3, f3, g3, h3, a4, b4, c4, d4, e4, f4, g4, h4, a5, b5, c5, d5, e5, f5, g5, h5, a6, b6, c6, d6, e6, f6, g6, h6, a7, b7, c7, d7, e7, f7, g7, h7, a8, b8, c8, d8, e8, f8, g8, h8 | D1 {(a1, b2); (b1, c2); (c1, d2); (d1, e2); (e1, f2); (f1, g2); (g1, h2); (a2, b3); (b2, a1); (b2, c3); (c2, b1); (c2, d3); (d2, c1); (d2, e3); (e2, d1); (e2, f3); (f2, e1); (f2, g3); (g2, f1); (g2, h3); (h2, g1); (a3, b4); (b3, a2); (b3, c4); (c3, b2); (c3, d4); (d3, c2); (d3, e4); (e3, d2); (e3, f4); (f3, e2); (f3, g4); (g3, f2); (g3, h4); (h3, g2); (a4, b5); (b4, a3); (b4, c5); (c4, b3); (c4, d5); (d4, c3); (d4, e5); (e4, d3); (e4, f5); (f4, e3); (f4, g5); (g4, f3); (g4, h5); (h4, g3); (a5, b6); (b5, a4); (b5, c6); (c5, b4); (c5, d6); (d5, c4); (d5, e6); (e5, d4); (e5, f6); (f5, e4); (f5, g6); (g5, f4); (g5, h6); (h5, g4); (a6, b7); (b6, a5); (b6, c7); (c6, b5); (c6, d7); (d6, c5); (d6, e7); (e6, d5); (e6, f7); (f6, e5); (f6, g7); (g6, f5); (g6, h7); (h6, g5); (a7, b8); (b7, a6); (b7, c8); (c7, b6); (c7, d8); (d7, c6); (d7, e8); (e7, d6); (e7, f8); (f7, e6); (f7, g8); (g7, f6); (g7, h8); (h7, g6); (b8, a7); (c8, b7); (d8, c7); (e8, d7); (f8, e7); (g8, f7); (h8, g7)}; D2 {(b1, a2); (c1, b2); (d1, c2); (e1, d2); (f1, e2); (g1, f2); (h1, g2); (a2, b1); (b2, c1); (b2, a3); (c2, d1); (c2, b3); (d2, e1); (d2, c3); (e2, f1); (e2, d3); (f2, g1); (f2, e3); (g2, h1); (g2, f3); (h2, g3); (a3, b2); (b3, c2); (b3, a4); (c3, d2); (c3, b4); (d3, e2); (d3, c4); (e3, f2); (e3, d4); (f3, g2); (f3, e4); (g3, h2); (g3, f4); (h3, g4); (a4, b3); (b4, c3); (b4, a5); (c4, d3); (c4, b5); (d4, e3); (d4, c5); (e4, f3); (e4, d5); (f4, g3); (f4, e5); (g4, h3); (g4, f5); (h4, g5); (a5, b4); (b5, c4); (b5, a6); (c5, d4); (c5, b6); (d5, e4); (d5, c6); (e5, f4); (e5, d6); (f5, g4); (f5, e6); (g5, h4); (g5, f6); (h5, g6); (a6, b5); (b6, c5); (b6, a7); (c6, d5); (c6, b7); (d6, e5); (d6, c7); (e6, f5); (e6, d7); (f6, g5); (f6, e7); (g6, h5); (g6, f7); (h6, g7); (a7, b6); (b7, c6); (b7, a8); (c7, d6); (c7, b8); (d7, e6); (d7, c8); (e7, f6); (e7, d8); (f7, g6); (f7, e8); (g7, h6); (g7, f8); (h7, g8); (a8, b7); (b8, c7); (c8, d7); (d8, e7); (e8, f7); (f8, g7); (g8, h7)}; bB:1 {}; wB:1 {}; wN:1 {}; wP:1 {}; wQ:1 {}; wR:1 {} | ] \" This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2011-02-01 00:03:10
|
Revision: 1300 http://toss.svn.sourceforge.net/toss/?rev=1300&view=rev Author: lukstafi Date: 2011-02-01 00:03:04 +0000 (Tue, 01 Feb 2011) Log Message: ----------- Iterative deepening in alpha-beta: provisional changes. Modified Paths: -------------- trunk/Toss/Play/Game.ml trunk/Toss/Play/GameTest.ml Modified: trunk/Toss/Play/Game.ml =================================================================== --- trunk/Toss/Play/Game.ml 2011-01-31 23:38:52 UTC (rev 1299) +++ trunk/Toss/Play/Game.ml 2011-02-01 00:03:04 UTC (rev 1300) @@ -775,10 +775,13 @@ let moves = gen_moves grid_size rules model location in if moves = [| |] then (* terminal position *) + (* Array.map (fun expr -> 100000. *. Solver.M.get_real_val expr state.struc) location.Arena.payoffs_pp (* see [let payoff] above *) + *) + play_evgame grid_size model time subgames.(loc) else if !timeout then play_evgame grid_size model time subgames.(loc) else @@ -788,10 +791,13 @@ if n = 0 then begin (* terminal after postconditions *) let res = (* play_evgame grid_size model time subgames.(loc) *) + (* Array.map (fun expr -> 100000. *. Solver.M.get_real_val expr state.struc) - location.Arena.payoffs_pp (* see [let payoff] above *) + location.Arena.payoffs_pp + *) + play_evgame grid_size model time subgames.(loc) in (* {{{ log entry *) if !debug_level > 4 then ( @@ -871,11 +877,11 @@ let scores = ref (Array.map (maximax_tree None player betas !cur_depth) models) in while not !timeout && !cur_depth < depth do - (* FIXME: is using common betas OK? *) let index = Array.init (Array.length models) (fun i->i) in Array.sort (fun j i-> compare !scores.(i).(player) !scores.(j).(player)) index; + let betas = Array.make num_players infinity in let new_scores = Array.map (fun i -> maximax_tree None player betas !cur_depth models.(i)) Modified: trunk/Toss/Play/GameTest.ml =================================================================== --- trunk/Toss/Play/GameTest.ml 2011-01-31 23:38:52 UTC (rev 1299) +++ trunk/Toss/Play/GameTest.ml 2011-02-01 00:03:04 UTC (rev 1300) @@ -830,7 +830,7 @@ let tests = "Game" >::: [ misc_tests; - search_tests "alpha_beta_ord" false 2 3 7; + search_tests "alpha_beta_ord" false 2 3 4; ] let experiments = "Game" >::: [ @@ -883,11 +883,11 @@ let a () = run_test_tt ~verbose:true experiments let a () = - Game.set_debug_level 1 + Game.set_debug_level 10 -let a () = +let a = match test_filter - ["Game:1:alpha_beta_ord:15:connect4 endgame"] + ["Game:1:alpha_beta_ord:1:tictactoe suggest optimal single"] tests with | Some tests -> ignore (run_test_tt ~verbose:true tests) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <luk...@us...> - 2011-01-31 23:38:58
|
Revision: 1299 http://toss.svn.sourceforge.net/toss/?rev=1299&view=rev Author: lukstafi Date: 2011-01-31 23:38:52 +0000 (Mon, 31 Jan 2011) Log Message: ----------- Iterative deepening in alpha-beta: bug fix. Modified Paths: -------------- trunk/Toss/Play/Game.ml trunk/Toss/Play/GameTest.ml Modified: trunk/Toss/Play/Game.ml =================================================================== --- trunk/Toss/Play/Game.ml 2011-01-31 23:14:55 UTC (rev 1298) +++ trunk/Toss/Play/Game.ml 2011-01-31 23:38:52 UTC (rev 1299) @@ -868,23 +868,24 @@ Aux.Right payoff else let cur_depth = ref 0 in - let scores = - Array.map (maximax_tree None player betas !cur_depth) models in + let scores = ref + (Array.map (maximax_tree None player betas !cur_depth) models) in while not !timeout && !cur_depth < depth do (* FIXME: is using common betas OK? *) let index = Array.init (Array.length models) (fun i->i) in Array.sort (fun j i-> compare - scores.(i).(player) scores.(j).(player)) index; - Array.iter (fun i -> - scores.(i) <- + !scores.(i).(player) !scores.(j).(player)) index; + let new_scores = + Array.map (fun i -> maximax_tree None player betas !cur_depth models.(i)) - index; - incr cur_depth + index in + incr cur_depth; + if not !timeout then scores := new_scores done; let _, best = - find_best_score ~use_det_setting:true cooperative player scores - (Array.map (fun _ -> 1) scores) in + find_best_score ~use_det_setting:true cooperative player !scores + (Array.map (fun _ -> 1) !scores) in let state = models.(best) in (* {{{ log entry *) if !debug_level > 0 && (depth > 1 || !debug_level > 3) Modified: trunk/Toss/Play/GameTest.ml =================================================================== --- trunk/Toss/Play/GameTest.ml 2011-01-31 23:14:55 UTC (rev 1298) +++ trunk/Toss/Play/GameTest.ml 2011-01-31 23:38:52 UTC (rev 1299) @@ -821,7 +821,7 @@ P P P Q Q . . \"" 0 in - medium_case state 0 "should defend" + hard_case state 0 "should defend" (fun mov_s -> "Cross{1:e2}" = mov_s); ); @@ -830,7 +830,7 @@ let tests = "Game" >::: [ misc_tests; - search_tests "alpha_beta_ord" false 2 3 4; + search_tests "alpha_beta_ord" false 2 3 7; ] let experiments = "Game" >::: [ @@ -887,7 +887,7 @@ let a () = match test_filter - [""] + ["Game:1:alpha_beta_ord:15:connect4 endgame"] tests with | Some tests -> ignore (run_test_tt ~verbose:true tests) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |