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
//! Provides function requirements.
use crate::types::Requirement;
use std::collections::HashSet;
use std::ops::Deref;
/// A set of domain requirements.
///
/// ## Usage
/// Used by [`Domain`](crate::Domain) and [`Problem`](crate::Problem).
///
/// ## Example
/// ```
/// # use pddl::{Requirement, Requirements};
/// let requirements = Requirements::new([
/// Requirement::Adl,
/// Requirement::Strips,
/// Requirement::Constraints]);
///
/// // Three requirements were actively specified.
/// assert_eq!(requirements.len(), 3);
///
/// // The effective set of requirements contains eight values:
/// // :adl expands to eight values, including :strips;
/// // :constraints is not part of :adl and therefore added.
/// let effective = requirements.to_effective();
/// assert_eq!(effective.len(), 9);
///
/// // These are the effective values:
/// assert!(effective.contains(&Requirement::Strips));
/// assert!(effective.contains(&Requirement::Typing));
/// assert!(effective.contains(&Requirement::NegativePreconditions));
/// assert!(effective.contains(&Requirement::DisjunctivePreconditions));
/// assert!(effective.contains(&Requirement::Equality));
/// assert!(effective.contains(&Requirement::ExistentialPreconditions));
/// assert!(effective.contains(&Requirement::UniversalPreconditions));
/// assert!(effective.contains(&Requirement::ConditionalEffects));
/// assert!(effective.contains(&Requirement::Constraints));
/// ```
///
/// If no requirements are specified, [`Requirements::to_effective`] implicitly adds `:strips`:
/// ```
/// # use pddl::{Requirement, Requirements};
/// let requirements = Requirements::default();
/// assert_eq!(requirements.len(), 0);
///
/// let effective = requirements.to_effective();
/// assert_eq!(effective.len(), 1);
/// assert!(effective.contains(&Requirement::Strips));
/// ```
#[derive(Debug, Default, Clone, Eq, PartialEq)]
pub struct Requirements(Vec<Requirement>);
impl Requirements {
/// Constructs a new set of requirements from the specified values.
///
/// ## Requirement Expansion
/// The values will be taken as-is, no deduplication is performed and the
/// implicit `:strips` requirement will not be added when no values are provided.
/// To get the effective set of requirements, call [`Requirements::to_effective`].
pub fn new<I: IntoIterator<Item = Requirement>>(requirements: I) -> Self {
Self(requirements.into_iter().collect())
}
/// Returns the set of effective requirements.
/// This expands all shorthand requirements such as `:adl` and adds the implicit
/// `:strips` requirement if no requirements are specified.
pub fn to_effective(&self) -> HashSet<Requirement> {
let mut set = HashSet::from_iter(self.iter().flat_map(Requirement::expand));
// :strips is an implicit requirement that is always given
// when no requirement is specified.
if set.is_empty() {
set.insert(Requirement::Strips);
}
set
}
}
impl Deref for Requirements {
type Target = Vec<Requirement>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl From<Vec<Requirement>> for Requirements {
fn from(value: Vec<Requirement>) -> Self {
Requirements::new(value)
}
}
impl FromIterator<Requirement> for Requirements {
fn from_iter<T: IntoIterator<Item = Requirement>>(iter: T) -> Self {
Requirements::new(iter)
}
}