11use anyhow:: { ensure, Context , Result } ;
22use aries:: core:: state:: Domains ;
33use aries:: model:: extensions:: AssignmentExt ;
4- use aries:: model:: lang:: { Atom , FAtom , SAtom } ;
4+ use aries:: model:: lang:: { Atom , FAtom } ;
55use aries_planners:: encoding:: ChronicleId ;
6+ use aries_planners:: fmt:: { extract_plan_actions, format_atom} ;
67use aries_planning:: chronicles:: { ChronicleKind , ChronicleOrigin , FiniteProblem , TaskId } ;
78use std:: collections:: HashMap ;
89use unified_planning as up;
910use unified_planning:: { Real , Schedule } ;
1011
1112pub fn serialize_plan (
12- _problem_request : & up:: Problem ,
13+ problem_request : & up:: Problem ,
1314 problem : & FiniteProblem ,
1415 assignment : & Domains ,
1516) -> Result < unified_planning:: Plan > {
@@ -46,74 +47,88 @@ pub fn serialize_plan(
4647 if assignment. value ( ch. chronicle . presence ) != Some ( true ) {
4748 continue ; // chronicle is absent, skip
4849 }
49- let start = serialize_time ( ch. chronicle . start , assignment) ?;
50- let end = serialize_time ( ch. chronicle . end , assignment) ?;
51-
52- // extract name and parameters (possibly empty if not an action or method chronicle)
53- let name = match ch. chronicle . kind {
54- ChronicleKind :: Problem => "problem" . to_string ( ) ,
55- ChronicleKind :: Method | ChronicleKind :: Action | ChronicleKind :: DurativeAction => {
56- let name = ch. chronicle . name . first ( ) . context ( "No name for action" ) ?;
57- let name = SAtom :: try_from ( * name) . context ( "Action name is not a symbol" ) ?;
58- let name = assignment. sym_value_of ( name) . context ( "Unbound sym var" ) ?;
59- problem. model . shape . symbols . symbol ( name) . to_string ( )
60- }
61- } ;
6250
63- let parameters = if ch. chronicle . name . len ( ) > 1 {
64- ch. chronicle . name [ 1 ..]
65- . iter ( )
66- . map ( |& param| serialize_atom ( param, problem, assignment) )
67- . collect :: < Result < Vec < _ > > > ( ) ?
68- } else {
69- Vec :: new ( )
70- } ;
71-
72- // map identifying subtasks of the chronicle
73- let mut subtasks: HashMap < String , String > = Default :: default ( ) ;
74- for ( tid, t) in ch. chronicle . subtasks . iter ( ) . enumerate ( ) {
75- let subtask_up_id = t. id . as_ref ( ) . cloned ( ) . unwrap_or_default ( ) ;
76- let subtask_id = TaskId {
77- instance_id : id,
78- task_id : tid,
79- } ;
80- subtasks. insert ( subtask_up_id, refining_chronicle ( subtask_id) ?. to_string ( ) ) ;
81- }
51+ let subtasks: HashMap < String , String > = ch
52+ . chronicle
53+ . subtasks
54+ . iter ( )
55+ . enumerate ( )
56+ . map ( |( tid, t) | {
57+ let subtask_up_id = t. id . as_ref ( ) . cloned ( ) . unwrap_or_default ( ) ;
58+ let subtask_id = TaskId {
59+ instance_id : id,
60+ task_id : tid,
61+ } ;
62+ ( subtask_up_id, refining_chronicle ( subtask_id) . unwrap ( ) . to_string ( ) )
63+ } )
64+ . collect ( ) ;
8265
8366 match ch. chronicle . kind {
8467 ChronicleKind :: Problem => {
8568 // base chronicles, its subtasks are the problem's subtasks
8669 ensure ! ( hier. root_tasks. is_empty( ) , "More than one set of root tasks." ) ;
8770 hier. root_tasks = subtasks;
8871 }
89- ChronicleKind :: Action | ChronicleKind :: DurativeAction => {
90- ensure ! ( subtasks. is_empty( ) , "Action with subtasks." ) ;
91- actions. push ( up:: ActionInstance {
92- id : id. to_string ( ) ,
93- action_name : name. to_string ( ) ,
94- parameters,
95- start_time : Some ( start) ,
96- end_time : Some ( end) ,
97- } ) ;
98- }
99-
10072 ChronicleKind :: Method => {
73+ let name = match ch. chronicle . kind {
74+ ChronicleKind :: Problem => "problem" . to_string ( ) ,
75+ ChronicleKind :: Method | ChronicleKind :: Action | ChronicleKind :: DurativeAction => {
76+ format_atom ( & ch. chronicle . name [ 0 ] , & problem. model , assignment)
77+ }
78+ } ;
79+ let parameters = ch. chronicle . name [ 1 ..]
80+ . iter ( )
81+ . map ( |& param| serialize_atom ( param, problem, assignment) )
82+ . collect :: < Result < Vec < _ > > > ( ) ?;
10183 hier. methods . push ( up:: MethodInstance {
10284 id : id. to_string ( ) ,
10385 method_name : name. to_string ( ) ,
10486 parameters,
10587 subtasks,
10688 } ) ;
10789 }
108- }
90+ ChronicleKind :: Action | ChronicleKind :: DurativeAction => {
91+ ensure ! ( subtasks. is_empty( ) , "Action with subtasks." ) ;
92+ let instances = extract_plan_actions ( ch, problem, assignment) ?;
93+ actions. extend (
94+ instances
95+ . iter ( )
96+ . map ( |a| {
97+ // The id is used in HTNs plans where there are no rolling
98+ let id = if problem_request. hierarchy . is_some ( ) {
99+ ensure ! ( instances. len( ) == 1 , "Rolling in HTN plan" ) ;
100+ id. to_string ( )
101+ } else {
102+ ( actions. len ( ) + id) . to_string ( )
103+ } ;
104+ let parameters = a
105+ . params
106+ . iter ( )
107+ . map ( |& p| serialize_atom ( p. into ( ) , problem, assignment) )
108+ . collect :: < Result < Vec < _ > > > ( ) ?;
109+ let start_time = Some ( serialize_time ( a. start . into ( ) , assignment) ?) ;
110+ let end_time = Some ( serialize_time ( ( a. start + a. duration ) . into ( ) , assignment) ?) ;
111+
112+ Ok ( up:: ActionInstance {
113+ id,
114+ action_name : a. name . to_string ( ) ,
115+ parameters,
116+ start_time,
117+ end_time,
118+ } )
119+ } )
120+ . collect :: < Result < Vec < _ > > > ( ) ?,
121+ ) ;
122+ }
123+ } ;
109124 }
110125 // sort actions by increasing start time.
111126 actions. sort_by_key ( |a| real_to_rational ( a. start_time . as_ref ( ) . unwrap ( ) ) ) ;
112127
113128 fn is_temporal ( feature : i32 ) -> bool {
114129 feature == ( up:: Feature :: ContinuousTime as i32 ) || feature == ( up:: Feature :: DiscreteTime as i32 )
115130 }
116- if !_problem_request . features . iter ( ) . any ( |feature| is_temporal ( * feature) ) {
131+ if !problem_request . features . iter ( ) . any ( |feature| is_temporal ( * feature) ) {
117132 // the problem is not temporal, remove time annotations
118133 // Note that the sorting done earlier ensures the plan is a valid sequence
119134 for action in & mut actions {
@@ -122,15 +137,15 @@ pub fn serialize_plan(
122137 }
123138 }
124139
125- let hierarchy = if _problem_request . hierarchy . is_some ( ) {
140+ let hierarchy = if problem_request . hierarchy . is_some ( ) {
126141 Some ( hier)
127142 } else {
128143 None
129144 } ;
130145
131146 // If this is a scheduling problem, interpret all actions as activities
132147 // TODO: currently, variables are not supported.
133- let schedule = if _problem_request . scheduling_extension . is_some ( ) {
148+ let schedule = if problem_request . scheduling_extension . is_some ( ) {
134149 let mut schedule = Schedule {
135150 activities : vec ! [ ] ,
136151 variable_assignments : Default :: default ( ) ,
@@ -148,7 +163,7 @@ pub fn serialize_plan(
148163 ) ;
149164 if !a. parameters . is_empty ( ) {
150165 // Search for the corresponding activity definition
151- let act = _problem_request
166+ let act = problem_request
152167 . scheduling_extension
153168 . as_ref ( )
154169 . expect ( "Missing scheduling extension" )
0 commit comments