problemreductions/models/misc/
dynamic_storage_allocation.rs1use crate::registry::{FieldInfo, ProblemSchemaEntry, ProblemSizeFieldEntry};
9use crate::traits::Problem;
10use crate::types::Or;
11use serde::de::Error as _;
12use serde::{Deserialize, Deserializer, Serialize};
13
14inventory::submit! {
15 ProblemSchemaEntry {
16 name: "DynamicStorageAllocation",
17 display_name: "Dynamic Storage Allocation",
18 aliases: &[],
19 dimensions: &[],
20 module_path: module_path!(),
21 description: "Assign starting addresses for items with time intervals and sizes within bounded memory",
22 fields: &[
23 FieldInfo { name: "items", type_name: "Vec<(usize, usize, usize)>", description: "Items as (arrival, departure, size) tuples" },
24 FieldInfo { name: "memory_size", type_name: "usize", description: "Total memory size D" },
25 ],
26 }
27}
28
29inventory::submit! {
30 ProblemSizeFieldEntry {
31 name: "DynamicStorageAllocation",
32 fields: &["num_items", "memory_size"],
33 }
34}
35
36#[derive(Debug, Clone, Serialize)]
42pub struct DynamicStorageAllocation {
43 items: Vec<(usize, usize, usize)>,
44 memory_size: usize,
45}
46
47impl DynamicStorageAllocation {
48 fn validate_inputs(items: &[(usize, usize, usize)], memory_size: usize) -> Result<(), String> {
49 if items.is_empty() {
50 return Err("DynamicStorageAllocation requires at least one item".to_string());
51 }
52 if memory_size == 0 {
53 return Err("DynamicStorageAllocation requires a positive memory_size".to_string());
54 }
55 for (i, &(arrival, departure, size)) in items.iter().enumerate() {
56 if size == 0 {
57 return Err(format!("Item {i} has zero size; all sizes must be >= 1"));
58 }
59 if departure <= arrival {
60 return Err(format!(
61 "Item {i} has departure ({departure}) <= arrival ({arrival}); departure must be strictly greater"
62 ));
63 }
64 if size > memory_size {
65 return Err(format!(
66 "Item {i} has size ({size}) > memory_size ({memory_size}); every item must fit in memory"
67 ));
68 }
69 }
70 Ok(())
71 }
72
73 pub fn try_new(items: Vec<(usize, usize, usize)>, memory_size: usize) -> Result<Self, String> {
75 Self::validate_inputs(&items, memory_size)?;
76 Ok(Self { items, memory_size })
77 }
78
79 pub fn new(items: Vec<(usize, usize, usize)>, memory_size: usize) -> Self {
85 Self::try_new(items, memory_size).unwrap_or_else(|message| panic!("{message}"))
86 }
87
88 pub fn items(&self) -> &[(usize, usize, usize)] {
90 &self.items
91 }
92
93 pub fn memory_size(&self) -> usize {
95 self.memory_size
96 }
97
98 pub fn num_items(&self) -> usize {
100 self.items.len()
101 }
102}
103
104#[derive(Deserialize)]
105struct DynamicStorageAllocationData {
106 items: Vec<(usize, usize, usize)>,
107 memory_size: usize,
108}
109
110impl<'de> Deserialize<'de> for DynamicStorageAllocation {
111 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
112 where
113 D: Deserializer<'de>,
114 {
115 let data = DynamicStorageAllocationData::deserialize(deserializer)?;
116 Self::try_new(data.items, data.memory_size).map_err(D::Error::custom)
117 }
118}
119
120impl Problem for DynamicStorageAllocation {
121 const NAME: &'static str = "DynamicStorageAllocation";
122 type Value = Or;
123
124 fn variant() -> Vec<(&'static str, &'static str)> {
125 crate::variant_params![]
126 }
127
128 fn dims(&self) -> Vec<usize> {
129 self.items
130 .iter()
131 .map(|&(_, _, s)| self.memory_size - s + 1)
132 .collect()
133 }
134
135 fn evaluate(&self, config: &[usize]) -> Or {
136 Or({
137 if config.len() != self.num_items() {
138 return Or(false);
139 }
140
141 for (i, &(_, _, size)) in self.items.iter().enumerate() {
143 let start = config[i];
144 if start + size > self.memory_size {
145 return Or(false);
146 }
147 }
148
149 for (i, &(r_i, d_i, s_i)) in self.items.iter().enumerate() {
151 let sigma_i = config[i];
152 for (j, &(r_j, d_j, s_j)) in self.items.iter().enumerate().skip(i + 1) {
153 if r_i < d_j && r_j < d_i {
155 let sigma_j = config[j];
156 let no_memory_overlap =
158 sigma_i + s_i <= sigma_j || sigma_j + s_j <= sigma_i;
159 if !no_memory_overlap {
160 return Or(false);
161 }
162 }
163 }
164 }
165 true
166 })
167 }
168}
169
170crate::declare_variants! {
171 default DynamicStorageAllocation => "(memory_size + 1)^num_items",
172}
173
174#[cfg(feature = "example-db")]
175pub(crate) fn canonical_model_example_specs() -> Vec<crate::example_db::specs::ModelExampleSpec> {
176 vec![crate::example_db::specs::ModelExampleSpec {
177 id: "dynamic_storage_allocation",
178 instance: Box::new(DynamicStorageAllocation::new(
179 vec![(0, 3, 2), (0, 2, 3), (1, 4, 1), (2, 5, 3), (3, 5, 2)],
180 6,
181 )),
182 optimal_config: vec![0, 2, 5, 2, 0],
183 optimal_value: serde_json::json!(true),
184 }]
185}
186
187#[cfg(test)]
188#[path = "../../unit_tests/models/misc/dynamic_storage_allocation.rs"]
189mod tests;