Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
dp_optimizations_example.cc
Go to the documentation of this file.
1/*
2 Aleph_w
3
4 Data structures & Algorithms
5 version 2.0.0b
6 https://github.com/lrleon/Aleph-w
7
8 This file is part of Aleph-w library
9
10 Copyright (c) 2002-2026 Leandro Rabindranath Leon
11
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files (the "Software"), to deal
14 in the Software without restriction, including without limitation the rights
15 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be included in all
20 copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 SOFTWARE.
29*/
30
31
37# include <iomanip>
38# include <iostream>
39
40# include <DP_Optimizations.H>
41
42using namespace Aleph;
43
44namespace
45{
51 void rule()
52 {
53 std::cout << "------------------------------------------------------------\n";
54 }
55
67 {
68 std::cout << "[1] Divide & Conquer DP optimization\n";
69 rule();
70
71 // Partition route-demand prefixes into balanced segments.
72 Array<long long> demand = {5, 2, 7, 4, 6, 3, 8, 5, 9, 4};
73 const size_t n = demand.size();
74 const size_t groups = 3;
75
77 pref(0) = 0;
78 for (size_t i = 0; i < n; ++i)
79 pref(i + 1) = pref[i] + demand[i];
80
81 const auto cost = [&] (const size_t k, const size_t i) -> long long
82 {
83 const long long seg = pref[i] - pref[k];
84 return seg * seg;
85 };
86
88 groups, n, cost
89 );
90
91 std::cout << "Demand sequence: ";
92 for (size_t i = 0; i < n; ++i)
93 std::cout << demand[i] << (i + 1 == n ? '\n' : ' ');
94
95 std::cout << "Groups: " << groups << "\n";
96 std::cout << "Optimal cost: " << res.optimal_cost << "\n";
97
98 Array<size_t> bounds;
99 bounds.append(n);
100
101 size_t i = n;
102 for (size_t g = groups; g-- > 1; )
103 {
104 const size_t k = res.split[g + 1][i];
105 bounds.append(k);
106 i = k;
107 }
108 bounds.append(0);
109
110 std::cout << "Split points (prefix indices): ";
111 for (size_t p = bounds.size(); p-- > 0; )
112 {
113 std::cout << bounds[p];
114 if (p > 0)
115 std::cout << " -> ";
116 }
117 std::cout << "\n";
118
119 rule();
120 std::cout << "\n";
121 }
122
130 {
131 std::cout << "[2] Knuth optimization (optimal adjacent merge)\n";
132 rule();
133
134 Array<size_t> blocks = {18, 7, 11, 5, 20, 9, 14};
135 const auto res = optimal_merge_knuth(blocks);
136
137 std::cout << "Blocks: ";
138 for (size_t i = 0; i < blocks.size(); ++i)
139 std::cout << blocks[i] << (i + 1 == blocks.size() ? '\n' : ' ');
140
141 std::cout << "Minimum merge cost: " << res.optimal_cost << "\n";
142 std::cout << "Top split (k for [0,n)): "
143 << res.opt[0][blocks.size()] << "\n";
144
145 rule();
146 std::cout << "\n";
147 }
148
159 {
160 std::cout << "[3] CHT + Li Chao (geometry-friendly lower envelopes)\n";
161 rule();
162
163 std::cout << "Monotone-slope CHT for min y = m*x + b:\n";
165 cht.add_line(5, -20);
166 cht.add_line(2, -3);
167 cht.add_line(-1, 10);
168 cht.add_line(-4, 25);
169
170 for (long long x = -4; x <= 8; x += 3)
171 std::cout << " x=" << std::setw(3) << x
172 << " min=" << std::setw(5) << cht.query(x) << "\n";
173
174 std::cout << "\nGeometric application: weighted squared distance\n";
175 std::cout << " min_j ((x_i - x_j)^2 + w_j) via Li Chao\n\n";
176
177 Array<long long> xs = {-10, -6, -1, 0, 4, 9, 13};
178 Array<long long> ws = {9, 3, 7, 2, 5, 4, 8};
179
181
182 std::cout << " "
183 << std::left << std::setw(8) << "x_i"
184 << std::setw(8) << "w_i"
185 << std::setw(12) << "min value"
186 << "\n";
187
188 for (size_t i = 0; i < xs.size(); ++i)
189 {
190 std::cout << " "
191 << std::left << std::setw(8) << xs[i]
192 << std::setw(8) << ws[i]
193 << std::setw(12) << best[i]
194 << "\n";
195 }
196
197 rule();
198 std::cout << "\n";
199 }
200
209 {
210 std::cout << "[4] Monotone queue optimization (windowed transitions)\n";
211 rule();
212
213 // dp[i] = base[i] + min(dp[j]), j in [i-window, i-1]
214 Array<long long> base = {6, 4, 7, 3, 5, 2, 8, 1, 4, 3};
215 const size_t window = 3;
216
217 const auto res = monotone_queue_min_dp<long long>(base, window);
218
219 std::cout << "Base cost: ";
220 for (size_t i = 0; i < base.size(); ++i)
221 std::cout << base[i] << (i + 1 == base.size() ? '\n' : ' ');
222
223 std::cout << "Window: " << window << "\n";
224 std::cout << "Final minimum cost: " << res.dp[base.size() - 1] << "\n";
225
226 Array<size_t> path;
227 size_t i = base.size() - 1;
228 path.append(i);
229 while (i > 0)
230 {
231 i = res.parent[i];
232 path.append(i);
233 }
234
235 std::cout << "Chosen chain: ";
236 for (size_t p = path.size(); p-- > 0; )
237 {
238 std::cout << path[p];
239 if (p > 0)
240 std::cout << " -> ";
241 }
242 std::cout << "\n";
243
244 rule();
245 std::cout << "\n";
246 }
247}
248
259int main()
260{
261 std::cout << "\n=== DP Optimizations: D&C, Knuth, CHT/Li Chao, Monotone Queue ===\n\n";
262
267
268 std::cout << "Done.\n";
269 return 0;
270}
Classical DP optimization toolkit: D&C DP, Knuth, CHT, Li Chao, and monotone-queue transitions.
Simple dynamic array with automatic resizing and functional operations.
Definition tpl_array.H:139
static Array create(size_t n)
Create an array with n logical elements.
Definition tpl_array.H:194
constexpr size_t size() const noexcept
Return the number of elements stored in the stack.
Definition tpl_array.H:351
T & append(const T &data)
Append a copy of data
Definition tpl_array.H:245
Convex Hull Trick for minimum queries.
void add_line(const T slope, const T intercept)
Insert a new line; slopes must be non-increasing.
int main()
Runs the DP optimization demonstration suite and exits.
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
Array< T > min_weighted_squared_distance_1d(const Array< T > &xs, const Array< T > &weights)
Weighted squared-distance lower envelope on a line.
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
Knuth_Optimization_Result< size_t > optimal_merge_knuth(const Array< size_t > &weights)
Optimal adjacent merge cost via Knuth optimization.
static int * k