1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
//! Contains durative action definitions via the [`DurativeActionDefinition`] type.
use crate::types::TypedVariables;
use crate::types::{
DurationConstraint, DurativeActionEffect, DurativeActionGoalDefinition, DurativeActionSymbol,
};
/// A durative action represents an action which takes an amount
/// of time to complete. The amount of time is expressible as either a value or as
/// an inequality (allow for both fixed duration and ranged duration actions).
///
/// Similar to traditional actions ([`ActionDefinition`](crate::types::ActionDefinition))
/// we have conditions and effects, but it should be noted that the keyword in
/// durative actions is [`condition`](DurativeActionDefinition::condition), not
/// [`precondition`](crate::types::ActionDefinition::precondition).
///
/// This semantic change is designed to represent that a durative action may not just
/// condition when the action starts, but may have conditions which need to be true
/// at the end or over the duration of the action. A good example of this can be
/// found in flight planning, where an action fly requires that a runway be free at
/// the start and end of an action, in order for the plane to take off and land
/// whilst the runway does not need to be free whilst the plane is flying.
///
/// ## Usage
/// Used by [`StructureDef`](crate::StructureDef).
#[derive(Debug, Clone, PartialEq)]
pub struct DurativeActionDefinition {
symbol: DurativeActionSymbol,
parameters: TypedVariables,
duration: Option<DurationConstraint>,
condition: Option<DurativeActionGoalDefinition>,
effect: Option<DurativeActionEffect>,
}
impl DurativeActionDefinition {
pub const fn new(
symbol: DurativeActionSymbol,
parameters: TypedVariables,
duration: Option<DurationConstraint>,
condition: Option<DurativeActionGoalDefinition>,
effect: Option<DurativeActionEffect>,
) -> Self {
Self {
symbol,
parameters,
duration,
condition,
effect,
}
}
pub const fn symbol(&self) -> &DurativeActionSymbol {
&self.symbol
}
/// The parameters defines the type of object we’re interested in.
/// Note that a parameter can take any type or subtype.
///
/// ## Example
///
/// ```pddl
/// (?s - site ?b - bricks)
/// ```
///
/// If we have for example three instances of site such as `s1`, `s2` and `s3`
/// and we have two instances of bricks `b1`, `b2`, our planner considers all
/// possible actions such as:
///
/// `(BUILD-WALL s1 b1)` `(BUILD-WALL s2 b1)` `(BUILD-WALL s3 b1)`
/// `(BUILD-WALL s1 b2)` `(BUILD-WALL s2 b2)` `(BUILD-WALL s3 b2)`
///
/// Therefore it is not up to us as a user to specify the specific object to which
/// an action applies but rather the type of objects to which the action applies.
///
/// In this case, when we build a wall we need to know what bricks we're using to build
/// it and where we’re building it. Our actions are specific to the problem we've chosen
/// to consider and model, therefore there might be additional things that other users
/// want/need to model that this model doesn't.
///
/// Your domain and problem should only consider and model the aspects of the problem
/// which you're trying to solve. For example here we haven't modelled the person who's
/// actually going to perform the work, but maybe if we were the manager of a larger
/// building site we might want to and therefore we would need to adapt my models.
pub const fn parameters(&self) -> &TypedVariables {
&self.parameters
}
/// A duration can be expressed as either a fixed value or an inequality.
/// It is also possible to express duration as the value of a Numeric Fluent
/// ([AtomicFunctionSkeleton](crate::types::AtomicFunctionSkeleton)), which means
/// an action such as move can have a duration dependent on say distance between two points.
///
/// ```pddl
/// :duration (= ?duration 10)
/// ```
pub const fn duration(&self) -> &Option<DurationConstraint> {
&self.duration
}
/// A condition is a logical and temporal expression which must be met in order for a
/// durative action to execute.
///
/// Because a durative action occurs over time, we may wish to express that additional
/// conditions be met for the duration or end of the action, not just the start.
/// This gives rise to three new keywords `at start`, `at end` and `over all`.
pub const fn condition(&self) -> &Option<DurativeActionGoalDefinition> {
&self.condition
}
/// An effect is a condition which is made true when an action is applied.
/// Note that the effect is always more restrictive than an action and typically only
/// allows `and` and `not` as logical expressions.
pub const fn effect(&self) -> &Option<DurativeActionEffect> {
&self.effect
}
}
impl AsRef<DurativeActionSymbol> for DurativeActionDefinition {
fn as_ref(&self) -> &DurativeActionSymbol {
self.symbol()
}
}
impl AsRef<TypedVariables> for DurativeActionDefinition {
fn as_ref(&self) -> &TypedVariables {
self.parameters()
}
}
impl AsRef<Option<DurationConstraint>> for DurativeActionDefinition {
fn as_ref(&self) -> &Option<DurationConstraint> {
self.duration()
}
}
impl AsRef<Option<DurativeActionGoalDefinition>> for DurativeActionDefinition {
fn as_ref(&self) -> &Option<DurativeActionGoalDefinition> {
self.condition()
}
}
impl AsRef<Option<DurativeActionEffect>> for DurativeActionDefinition {
fn as_ref(&self) -> &Option<DurativeActionEffect> {
self.effect()
}
}