@@ -2,47 +2,41 @@ use std::{collections::BTreeMap, time::Instant};
22
33use aries:: { core:: state:: Evaluable , prelude:: * } ;
44use aries_plan_engine:: {
5- encode:: {
6- encoding:: Encoding ,
7- tags:: { Tag , format_culprit_set} ,
5+ encode:: { encoding:: Encoding , tags:: Tag } ,
6+ plans:: {
7+ Operation ,
8+ lifted_plan:: { LiftedPlan , ObjectOrVariable } ,
89 } ,
9- plans:: lifted_plan:: { self , LiftedPlan } ,
1010} ;
11- use derive_more:: derive:: Display ;
12- use planx:: { Model , Res , errors:: * } ;
11+ use planx:: { Model , Res , Sym } ;
1312use timelines:: { Sched , explain:: ExplainableSolver } ;
1413
15- use crate :: optimize_plan;
14+ use crate :: optimize_plan:: { self , Objective } ;
1615
1716pub type RelaxableConstraint = Tag ;
1817
1918#[ derive( clap:: Args , Debug , Clone ) ]
2019pub struct Options {
20+ /// Defines the maximum number of instances per action template.
21+ ///
22+ /// For instance, if set to 3, the resulting plan may have *at most* three instances
23+ /// of a `pick` action and at most 3 instances of a `drop` action.
2124 #[ arg( short, long) ]
22- pub max_depth : usize ,
25+ pub max_instances : usize ,
2326
24- // #[arg(short, long, num_args(1..))]
25- // pub relaxation: Vec<Relaxation>,
26- #[ arg( short, long, default_value( "plan-length" ) ) ]
27+ /// Defines the objective to be minimized
28+ #[ arg( short, long, default_value( "original" ) ) ]
2729 pub objective : Objective ,
28- }
2930
30- // #[derive(clap::ValueEnum, Debug, Clone, Copy, Display, PartialEq, PartialOrd, Eq, Ord)]
31- // pub enum Relaxation {
32- // ActionPresence,
33- // StartTime,
34- // }
35-
36- #[ derive( clap:: ValueEnum , Debug , Clone , Copy , Display , PartialEq , Eq , PartialOrd , Ord ) ]
37- pub enum Objective {
38- /// The objective value defined in the domain
39- Original ,
40- PlanLength ,
41- Makespan ,
31+ /// If set, the planner will try tro find the optimal solution
32+ #[ arg( long) ]
33+ pub optimize : bool ,
4234}
4335
4436pub fn solve_finite_planning_problem ( model : & Model , options : & Options ) -> Res < ( ) > {
45- let plan = & lifted_plan:: new_empty_lifted_plan ( model, BTreeMap :: new ( ) , options. max_depth ) ?;
37+ // create a dummy plan with the appropriate number of actions
38+ // this is temporary a workaround to reuse the existing `optimize_plan` facilities
39+ let plan = & new_empty_lifted_plan ( model, BTreeMap :: new ( ) , options. max_instances ) ?;
4640
4741 let start = Instant :: now ( ) ;
4842 let ( mut solver, encoding, _sched) = encode_finite_planning_problem ( model, plan, options) ?;
@@ -51,37 +45,31 @@ pub fn solve_finite_planning_problem(model: &Model, options: &Options) -> Res<()
5145
5246 let objective = encoding. objective . unwrap ( ) ; //TODO: error message
5347
48+ // set the objective to a constant if we are not optimizing
49+ let solver_objective = if options. optimize { objective } else { 0 . into ( ) } ;
50+
5451 let print = |sol : & Solution | {
55- println ! ( "==== Plan (objective: {}) =====" , objective. evaluate( sol) . unwrap( ) ) ;
52+ println ! ( "\n ==== Plan (objective: {}) =====" , objective. evaluate( sol) . unwrap( ) ) ;
5653 println ! ( "{}\n " , encoding. plan( sol) ) ;
5754 } ;
5855
59- if let Some ( solution) = solver. find_optimal ( objective , & print) {
60- println ! ( "\n > Found optimal solution:" ) ;
56+ if let Some ( solution) = solver. find_optimal ( solver_objective , & print) {
57+ println ! ( "\n > Found {} solution:" , if options . optimize { "optimal " } else { "" } ) ;
6158 print ( & solution) ;
6259 } else {
6360 println ! ( "No solution !!!!" ) ;
64- for mus in solver. muses ( ) {
65- let msg = format_culprit_set ( Message :: error ( "Invalid in all relaxation" ) , & mus, model, plan) ;
66- println ! ( "\n {msg}\n " ) ;
67- }
6861 }
6962 Ok ( ( ) )
7063}
7164
72- pub fn encode_finite_planning_problem (
65+ fn encode_finite_planning_problem (
7366 model : & Model ,
7467 lifted_plan : & LiftedPlan ,
7568 options : & Options ,
7669) -> Res < ( ExplainableSolver < RelaxableConstraint > , Encoding , Sched ) > {
7770 // TODO: make specific function.
7871 // - ability to specify explanations vocabulary via RelaxableConstraint (Tag), including removing (pre)conditions (like in domain repair).
7972
80- let objective = match options. objective {
81- Objective :: Original => optimize_plan:: Objective :: Original ,
82- Objective :: PlanLength => optimize_plan:: Objective :: PlanLength ,
83- Objective :: Makespan => optimize_plan:: Objective :: Makespan ,
84- } ;
8573 optimize_plan:: encode_plan_optimization_problem (
8674 model,
8775 lifted_plan,
@@ -90,7 +78,54 @@ pub fn encode_finite_planning_problem(
9078 optimize_plan:: Relaxation :: ActionPresence ,
9179 optimize_plan:: Relaxation :: StartTime ,
9280 ] ,
93- objective,
81+ objective : options . objective ,
9482 } ,
9583 )
9684}
85+
86+ fn new_empty_lifted_plan (
87+ model : & Model ,
88+ a_instances_per_template : BTreeMap < planx:: ActionRef , usize > ,
89+ a_instances_default : usize ,
90+ ) -> Res < LiftedPlan > {
91+ let top_type = model. env . types . top_user_type ( ) ;
92+ use planx:: errors:: * ;
93+
94+ let num_instances = |a_name| * a_instances_per_template. get ( a_name) . unwrap_or ( & a_instances_default) ;
95+
96+ // all actions in the plan
97+ let mut operations = Vec :: with_capacity ( model. actions . iter ( ) . map ( |a| num_instances ( & a. name ) ) . sum ( ) ) ;
98+
99+ // all variables appearing in the plan
100+ let mut variables = BTreeMap :: new ( ) ;
101+
102+ for a in model. actions . iter ( ) {
103+ for aid in 0 ..num_instances ( & a. name ) {
104+ let mut arguments = Vec :: with_capacity ( a. parameters . len ( ) ) ;
105+
106+ for param in a. parameters . iter ( ) {
107+ let name = Sym :: with_source (
108+ format ! ( "{}.{}.{}" , a. name. canonical_str( ) , aid, param. name( ) . canonical_str( ) ) ,
109+ param. name ( ) . span_or_default ( ) ,
110+ ) ;
111+ let tpe = if let planx:: Type :: User ( tpe) = param. tpe ( ) {
112+ tpe. to_single_type ( ) . unwrap_or_else ( || top_type. clone ( ) )
113+ } else {
114+ top_type. clone ( )
115+ } ;
116+
117+ variables. insert ( name. clone ( ) , tpe) ;
118+
119+ arguments. push ( ObjectOrVariable :: Variable { name } ) ;
120+ }
121+ operations. push ( Operation {
122+ start : 0 ,
123+ duration : 0 ,
124+ action_ref : a. name . clone ( ) ,
125+ arguments,
126+ span : None ,
127+ } ) ;
128+ }
129+ }
130+ Ok ( LiftedPlan { operations, variables } )
131+ }
0 commit comments