module planner. % best_plan(S,Limit,Plan) => best_plan(S,Limit,Plan). % best_plan(S,Limit,Plan,PlanCost) => best_plan(S,Limit,Plan,PlanCost). % best_plan(S,Plan,PlanCost) => best_plan(S,Plan,PlanCost). % best_plan(S,Plan) => best_plan(S,Plan). % best_plan_bin(S,Limit,Plan) => best_plan_bin(S,Limit,Plan). % best_plan_bin(S,Limit,Plan,PlanCost) => best_plan_bin(S,Limit,Plan,PlanCost). % best_plan_bin(S,Plan,PlanCost) => best_plan_bin(S,Plan,PlanCost). % best_plan_bin(S,Plan) => best_plan_bin(S,Plan). % best_plan_bb(S,Limit,Plan) => best_plan_bb(S,Limit,Plan). % best_plan_bb(S,Plan,PlanCost) => best_plan_bb(S,Plan,PlanCost). % best_plan_bb(S,Limit,Plan,PlanCost) => best_plan_bb(S,Limit,Plan,PlanCost). % best_plan_bb(S,Plan) => best_plan_bb(S,Plan). % best_plan_nondet(S,Limit,Plan) => best_plan_nondet(S,Limit,Plan). % best_plan_nondet(S,Plan,PlanCost) => best_plan_nondet(S,Plan,PlanCost). % best_plan_nondet(S,Limit,Plan,PlanCost) => best_plan_nondet(S,Limit,Plan,PlanCost). % best_plan_nondet(S,Plan) => best_plan_nondet(S,Plan). % best_plan_unbounded(S,Limit,Plan) => best_plan_unbounded(S,Limit,Plan). % best_plan_unbounded(S,Plan,PlanCost) => best_plan_unbounded(S,Plan,PlanCost). % best_plan_unbounded(S,Limit,Plan,PlanCost) => best_plan_unbounded(S,Limit,Plan,PlanCost). % best_plan_unbounded(S,Plan) => best_plan_unbounded(S,Plan). % current_plan() = current_plan(). % current_resource() = current_resource(). % current_resource_plan(Amount,Plan) => current_resource_plan(Amount,Plan). % current_resource_plan_cost(Amount,Plan,Cost) => current_resource_plan_cost(Amount,Plan,Cost). % insert_state_list(StateL,Elm) = insert_state_list(StateL,Elm). % is_tabled_state(S) => is_tabled_state(S). % new_state_list(List) = new_state_list(List). % plan(S,Limit,Plan) => plan(S,Limit,Plan). % plan(S,Plan,PlanCost) => plan(S,Plan,PlanCost). % plan(S,Limit,Plan,PlanCost) => plan(S,Limit,Plan,PlanCost). % plan(S,Plan) => plan(S,Plan). % plan_unbounded(S,Limit,Plan) => plan_unbounded(S,Limit,Plan). % plan_unbounded(S,Plan,PlanCost) => plan_unbounded(S,Plan,PlanCost). % plan_unbounded(S,Limit,Plan,PlanCost) => plan_unbounded(S,Limit,Plan,PlanCost). % plan_unbounded(S,Plan) => plan_unbounded(S,Plan). % A state-list is an ordered list, where the ordering of symbols is determined % by the addresses of the symbols in the symbol table, not by the characters that % constitute the symbols. This ordering allows for efficient ordering of symbols. % Note that this ordering is different from lexicographical ordering, which is used by sort(). new_state_list(List) = SList => new_state_list_aux(List,[],SList). new_state_list_aux([],SList0,SList) => SList = SList0. new_state_list_aux([E|List],SList0,SList) => bp.b_INSERT_STATE_LIST_ccf(SList0,E,SList1), new_state_list_aux(List,SList1,SList). insert_state_list(SList0, Elm) = SList => bp.b_INSERT_STATE_LIST_ccf(SList0,Elm,SList). %%% current_resource() = Amount => bp.b_PLANNER_CURR_RPC_fff(Amount,_Plan,_Cost). current_plan() = Plan => bp.b_PLANNER_CURR_RPC_fff(_Amount,Plan,_Cost). current_resource_plan(Amount,Plan) => bp.b_PLANNER_CURR_RPC_fff(Amount,Plan,_Cost). current_resource_plan_cost(Amount,Plan,Cost) => bp.b_PLANNER_CURR_RPC_fff(Amount,Plan,Cost). %%% plan(S,Plan), var(Plan) => bp.picat_plan(S,268435455,Plan,_). % the limit is assumed to be 268435455 plan(_S,Plan) => throw_plan_arg_error(1,Plan,_,plan). plan(S,Limit,Plan), var(Plan), integer(Limit), Limit >= 0 => bp.picat_plan(S,Limit,Plan,_). plan(S,Plan,PlanCost), var(Plan), var(PlanCost) => bp.picat_plan(S,268435455,Plan,PlanCost). plan(_S,Limit,Plan) => throw_plan_arg_error(Limit,Plan,_,plan). plan(S,Limit,Plan,PlanCost), var(Plan), var(PlanCost), integer(Limit), Limit >= 0 => bp.picat_plan(S,Limit,Plan,PlanCost). plan(_S,Limit,Plan,PlanCost) => throw_plan_arg_error(Limit,Plan,PlanCost,plan). plan(S,Limit,Plan,PlanCost,FinS), var(Plan), var(PlanCost), integer(Limit), Limit >= 0 => bp.picat_plan(S,Limit,Plan,PlanCost,FinS). plan(_S,Limit,Plan,PlanCost,_FinS) => throw_plan_arg_error(Limit,Plan,PlanCost,plan). %%% plan_unbounded(S,Plan), var(Plan) => bp.picat_plan_unbounded(S,268435455,Plan,_). % the limit is assumed to be 268435455 plan_unbounded(_S,Plan) => throw_plan_arg_error(1,Plan,_,plan_unbounded). plan_unbounded(S,Limit,Plan), var(Plan), integer(Limit), Limit >= 0 => bp.picat_plan_unbounded(S,Limit,Plan,_). plan_unbounded(S,Plan,PlanCost), var(Plan), var(PlanCost) => bp.picat_plan_unbounded(S,268435455,Plan,PlanCost). plan_unbounded(_S,Limit,Plan) => throw_plan_arg_error(Limit,Plan,_,plan_unbounded). plan_unbounded(S,Limit,Plan,PlanCost), var(Plan), var(PlanCost), integer(Limit), Limit >= 0 => bp.picat_plan_unbounded(S,Limit,Plan,PlanCost). plan_unbounded(_S,Limit,Plan,PlanCost) => throw_plan_arg_error(Limit,Plan,PlanCost,plan_unbounded). %%% %%% iterative deepening best_plan(S,Plan), var(Plan) => best_plan_downward(S,0,268435455,Plan,_,_). best_plan(_S,Plan) => throw_plan_arg_error(1,Plan,_,best_plan). best_plan(S,Limit,Plan), var(Plan), integer(Limit), Limit >= 0 => best_plan_downward(S,0,Limit,Plan,_,_). best_plan(S,Plan,PlanCost), var(Plan), var(PlanCost) => best_plan_downward(S,0,268435455,Plan,PlanCost,_). best_plan(_S,Limit,Plan) => throw_plan_arg_error(Limit,Plan,_,best_plan). best_plan(S,Limit,Plan,PlanCost), var(Plan), var(PlanCost), integer(Limit), Limit >= 0 => best_plan_downward(S,0,Limit,Plan,PlanCost,_). best_plan(_S,Limit,Plan,PlanCost) => throw_plan_arg_error(Limit,Plan,PlanCost,best_plan). best_plan(S,Limit,Plan,PlanCost,FinS), var(Plan), var(PlanCost), integer(Limit), Limit >= 0 => best_plan_downward(S,0,Limit,Plan,PlanCost,FinS). best_plan(_S,Limit,Plan,PlanCost,_FinS) => throw_plan_arg_error(Limit,Plan,PlanCost,best_plan). %%% best_plan_downward(S,Level,_Limit,_Plan,_PlanCost,_FinS) ?=> (bp.global_get('_$picat_log',0, 1) -> printf("%% Searching with the bound %d\n",Level); true), call_picat_plan(S,Level), fail. best_plan_downward(S,_Level,_Limit,Plan,PlanCost,FinS), Map = get_table_map('_$planner'), Map.has_key($current_best_plan(S)) => Map.get($current_best_plan(S)) = Plan, Map.get($current_best_plan_cost(S)) = PlanCost, Map.get($current_best_plan_fin_state(S)) = FinS. best_plan_downward(S,Level,Limit,Plan,PlanCost,FinS) => bp.global_get('_$planner_explored_depth',0,Depth), (Depth == 268435455 -> Level1 = Level+1; Level1 = Depth), Level1 =< Limit, best_plan_downward(S,Level1,Limit,Plan,PlanCost,FinS). %%% iterative deeping and binary search best_plan_bin(S,Plan), var(Plan) => best_plan_downward_bin(S,0,268435455,Plan,_,_). best_plan_bin(_S,Plan) => throw_plan_arg_error(1,Plan,_,best_plan). best_plan_bin(S,Limit,Plan), var(Plan), integer(Limit), Limit >= 0 => best_plan_downward_bin(S,0,Limit,Plan,_,_). best_plan_bin(S,Plan,PlanCost), var(Plan), var(PlanCost) => best_plan_downward_bin(S,0,268435455,Plan,PlanCost,_). best_plan_bin(_S,Limit,Plan) => throw_plan_arg_error(Limit,Plan,_,best_plan). best_plan_bin(S,Limit,Plan,PlanCost), var(Plan), var(PlanCost), integer(Limit), Limit >= 0 => best_plan_downward_bin(S,0,Limit,Plan,PlanCost,_). best_plan_bin(_S,Limit,Plan,PlanCost) => throw_plan_arg_error(Limit,Plan,PlanCost,best_plan). best_plan_bin(S,Limit,Plan,PlanCost,FinS), var(Plan), var(PlanCost), integer(Limit), Limit >= 0 => best_plan_downward_bin(S,0,Limit,Plan,PlanCost,FinS). best_plan_bin(_S,Limit,Plan,PlanCost,_FinS) => throw_plan_arg_error(Limit,Plan,PlanCost,best_plan). %%% best_plan_downward_bin(S,Level,Limit,Plan,PlanCost,FinS) => Map = get_table_map('_$planner'), loop_best_plan_downward_bin(S,Level,Limit,Plan,PlanCost,FinS,Map). loop_best_plan_downward_bin(S,Level,Limit,_Plan,_PlanCost,_FinS,_Map) ?=> Level =< Limit, (bp.global_get('_$picat_log',0, 1) -> printf("%% Searching with the bound %d\n",Level); true), call_picat_plan(S,Level), fail. loop_best_plan_downward_bin(S,_Level,_Limit,Plan,PlanCost,_FinS,Map), Map.has_key($current_best_plan(S)) => Lower = Map.get($current_lower_bound(S), 0), Upper = Map.get($current_best_plan_cost(S))-1, loop_best_plan_bin(S,Map,Lower,Upper,Plan,PlanCost). loop_best_plan_downward_bin(S,Level,Limit,Plan,PlanCost,FinS,Map) => bp.global_get('_$planner_explored_depth',0,Depth), % writeln(depth=Depth), (Depth == 268435455 -> Lower = Level+1; Lower = Depth), Map.put($current_lower_bound(S), Lower), Lower < Limit, Level1 = 2*Lower, NewLevel = cond(Level1 > Limit, Limit, Level1), loop_best_plan_downward_bin(S,NewLevel,Limit,Plan,PlanCost,FinS,Map). % binary search loop_best_plan_bin(S,Map,Lower,Upper,Plan,PlanCost), Lower =< Upper => NewLimit = Lower + (Upper-Lower) div 2, (bp.global_get('_$picat_log',0, 1) -> printf("%% Searching with the bound %d\n",NewLimit); true), if call_picat_plan(S,NewLimit) then NewUpper = Map.get($current_best_plan_cost(S))-1, loop_best_plan_bin(S,Map,Lower,NewUpper,Plan,PlanCost) else NewLower = NewLimit+1, loop_best_plan_bin(S,Map,NewLower,Upper,Plan,PlanCost) end. loop_best_plan_bin(S,Map,_Lower,_Upper,Plan,PlanCost) => Map.has_key($current_best_plan(S)), Map.get($current_best_plan(S)) = Plan, Map.get($current_best_plan_cost(S)) = PlanCost. %%% best_plan_nondet(S,Plan), var(Plan) => best_plan_nondet_aux(S,268435455,Plan,_). best_plan_nondet(_S,Plan) => throw_plan_arg_error(1,Plan,_,best_plan_nondet). best_plan_nondet(S,Limit,Plan), var(Plan), integer(Limit), Limit >= 0 => best_plan_nondet_aux(S,Limit,Plan,_). best_plan_nondet(S,Plan,PlanCost), var(Plan), var(PlanCost) => best_plan_nondet_aux(S,268435455,Plan,PlanCost). best_plan_nondet(_S,Limit,Plan) => throw_plan_arg_error(Limit,Plan,_,best_plan_nondet). best_plan_nondet(S,Limit,Plan,PlanCost), var(Plan), var(PlanCost), integer(Limit), Limit >= 0 => best_plan_nondet_aux(S,Limit,Plan,PlanCost). best_plan_nondet(_S,Limit,Plan,PlanCost) => throw_plan_arg_error(Limit,Plan,PlanCost,best_plan_nondet). best_plan_nondet_aux(S,Limit,Plan,PlanCost) => not not (M = get_global_map(), M.put('_first_best_plan',[]), best_plan_downward(S,0,Limit,Plan0,PlanCost0,_), % use tabled search to find the first best plan M.put('_first_best_plan', (Plan0,PlanCost0))), get_global_map().get('_first_best_plan') = (Plan0,PlanCost), ( Plan = Plan0 ; bp.picat_best_plan_nondet_nontabled_search(S,Plan,PlanCost), Plan0 != Plan ). %%% Branch-and-Bound best_plan_bb(S,Plan), var(Plan) => loop_best_plan_bb(S,268435455,Plan,_). best_plan_bb(_S,Plan) => throw_plan_arg_error(1,Plan,_,best_plan_bb). best_plan_bb(S,Limit,Plan), var(Plan), integer(Limit), Limit >= 0 => loop_best_plan_bb(S,Limit,Plan,_PlanCost). best_plan_bb(S,Plan,PlanCost), var(Plan), var(PlanCost) => loop_best_plan_bb(S,268435455,Plan,PlanCost). best_plan_bb(_S,Limit,Plan) => throw_plan_arg_error(Limit,Plan,_,best_plan_bb). best_plan_bb(S,Limit,Plan,PlanCost), var(Plan), var(PlanCost), integer(Limit), Limit >= 0 => loop_best_plan_bb(S,Limit,Plan,PlanCost). best_plan_bb(_S,Limit,Plan,PlanCost) => throw_plan_arg_error(Limit,Plan,PlanCost,best_plan_bb). loop_best_plan_bb(S,Limit,Plan,PlanCost), (bp.global_get('_$picat_log',0, 1) -> printf("%% Searching with the bound %d\n",Limit); true), call_picat_plan(S,Limit) => get_table_map('_$planner').get($current_best_plan_cost(S)) = PlanCost1, loop_best_plan_bb(S,PlanCost1-1,Plan,PlanCost). loop_best_plan_bb(S,_Limit,Plan,PlanCost) => Map = get_table_map('_$planner'), Map.has_key($current_best_plan(S)), Map.get($current_best_plan(S)) = Plan, Map.get($current_best_plan_cost(S)) = PlanCost. call_picat_plan(S,Limit) => bp.global_set('_$planner_explored_depth',0,268435455), not not call_picat_plan_aux(S,Limit). % discard exception catchers created by picat_plan call_picat_plan_aux(S,Limit) => bp.picat_plan(S,Limit,Plan,PlanCost,FinS), Map = get_table_map('_$planner'), Map.put($current_best_plan(S), Plan), Map.put($current_best_plan_cost(S), PlanCost), Map.put($current_best_plan_fin_state(S), FinS). %%% best_plan_unbounded(S,Plan), var(Plan) => bp.picat_best_plan_unbounded(S,Plan,_). best_plan_unbounded(_S,Plan) => throw_plan_arg_error(1,Plan,_,best_plan_unbounded). best_plan_unbounded(S,Limit,Plan), var(Plan), integer(Limit), Limit >= 0 => bp.picat_best_plan_unbounded(S,Plan,PlanCost), PlanCost =< Limit. best_plan_unbounded(S,Plan,PlanCost), var(Plan), var(PlanCost) => bp.picat_best_plan_unbounded(S,Plan,PlanCost). best_plan_unbounded(_S,Limit,Plan) => throw_plan_arg_error(Limit,Plan,_,best_plan_unbounded). best_plan_unbounded(S,Limit,Plan,PlanCost), var(Plan), var(PlanCost), integer(Limit), Limit >= 0 => bp.picat_best_plan_unbounded(S,Plan,PlanCost), PlanCost =< Limit. best_plan_unbounded(_S,Limit,Plan,PlanCost) => throw_plan_arg_error(Limit,Plan,PlanCost,best_plan_unbounded). %%% is_tabled_state(S) => bp.b_IS_PLANNER_STATE_c(S). throw_plan_arg_error(_Limit,Plan,_PlanCost,Source), nonvar(Plan) => handle_exception($var_expected(Plan), Source). throw_plan_arg_error(_Limit,_Plan,PlanCost,Source), nonvar(PlanCost) => handle_exception($var_expected(PlanCost), Source). throw_plan_arg_error(Limit,_Plan,_PlanCost,Source), integer(Limit) => handle_exception($nonnegative_integer_expected(Limit), Source). throw_plan_arg_error(Limit,_Plan,_PlanCost,Source) => handle_exception($integer_expected(Limit), Source).