Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
ida_star_no_solution_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
58#include <cstddef>
59#include <iostream>
60#include <limits>
61
63
64using namespace Aleph;
65
66// ---------------------------------------------------------------------------
67// Shared state type
68// ---------------------------------------------------------------------------
69
71{
72 size_t node = 0;
73};
74
75// ---------------------------------------------------------------------------
76// Scenario A: unreachable goal on a small DAG
77// ---------------------------------------------------------------------------
78
80{
81public:
82 struct Move
83 {
84 size_t to = 0;
85 int cost = 1;
86 };
87
89 using State_Key = size_t;
90 using Distance = int;
91
92 [[nodiscard]] State_Key state_key(const State &s) const noexcept
93 {
94 return s.node;
95 }
96
97 [[nodiscard]] bool is_goal(const State &s) const noexcept
98 {
99 return s.node == 9; // node 9 has no incoming edges
100 }
101
102 void apply(State &s, const Move &m) const noexcept
103 {
104 s.node = m.to;
105 }
106
107 void undo(State &s, const Move &m) const noexcept
108 {
109 // Restore the parent node using the move's destination (DAG: to==1 ⟹ came from 0).
110 s.node = (m.to == 1) ? 0 : (m.to == 2) ? 1 : s.node;
111 }
112
113 template <typename Visitor>
114 bool for_each_successor(const State &s, Visitor visit) const
115 {
116 if (s.node == 0)
117 return visit(Move{1, 1});
118 if (s.node == 1)
119 return visit(Move{2, 1});
120 return true; // node 2 is a dead end; node 9 is unreachable
121 }
122
123 [[nodiscard]] Distance heuristic(const State &) const noexcept
124 {
125 return 1; // constant — admissible (never overestimates for an unreachable goal)
126 }
127
128 [[nodiscard]] Distance cost(const State &, const Move &m) const noexcept
129 {
130 return m.cost;
131 }
132};
133
134// ---------------------------------------------------------------------------
135// Scenario B: inadmissible heuristic on a reachable goal
136//
137// Graph: 0 ──(1)──► 1 ──(1)──► 2 (goal)
138// Heuristic h(0) = h(1) = 100, h(2) = 0 (massively overestimates)
139// Optimal cost = 2; because h is inadmissible IDA* is NOT guaranteed
140// to find the optimum, but it MUST find some solution.
141// ---------------------------------------------------------------------------
142
144{
145public:
146 struct Move
147 {
148 size_t to = 0;
149 int cost = 1;
150 };
151
153 using State_Key = size_t;
154 using Distance = int;
155
156 [[nodiscard]] State_Key state_key(const State &s) const noexcept
157 {
158 return s.node;
159 }
160
161 [[nodiscard]] bool is_goal(const State &s) const noexcept
162 {
163 return s.node == 2;
164 }
165
166 void apply(State &s, const Move &m) const noexcept
167 {
168 s.node = m.to;
169 }
170
171 void undo(State &s, const Move &m) const noexcept
172 {
173 s.node = (m.to == 1) ? 0 : 1;
174 }
175
176 template <typename Visitor>
177 bool for_each_successor(const State &s, Visitor visit) const
178 {
179 if (s.node == 0)
180 return visit(Move{1, 1});
181 if (s.node == 1)
182 return visit(Move{2, 1});
183 return true;
184 }
185
186 [[nodiscard]] Distance heuristic(const State &s) const noexcept
187 {
188 return s.node == 2 ? 0 : 100; // inadmissible overestimate
189 }
190
191 [[nodiscard]] Distance cost(const State &, const Move &m) const noexcept
192 {
193 return m.cost;
194 }
195};
196
197// ---------------------------------------------------------------------------
198// Main
199// ---------------------------------------------------------------------------
200
201int main()
202{
203 // --- Scenario A ---
204 {
207 const auto result = engine.search(NodeState{});
208
209 std::cout << "=== Scenario A: unreachable goal ===\n";
210 std::cout << "Found solution : " << (result.found_solution() ? "yes" : "no") << "\n";
211 std::cout << "Status : " << (result.exhausted() ? "Exhausted" : "other") << "\n";
212 std::cout << "States visited : " << result.stats.visited_states << "\n";
213 std::cout << "IDA* iterations: " << result.iterations.size() << "\n";
214 }
215
216 std::cout << "\n";
217
218 // --- Scenario B ---
219 {
220 InadmissibleDomain domain;
222 const auto result = engine.search(NodeState{});
223
224 std::cout << "=== Scenario B: inadmissible heuristic ===\n";
225 std::cout << "Found solution : " << (result.found_solution() ? "yes" : "no") << "\n";
226 std::cout << "Total cost : " << result.total_cost << "\n";
227 std::cout << "Note: optimal cost is 2; inadmissible h may or may not match it.\n";
228 }
229
230 return 0;
231}
IDA* (Iterative Deepening A*) over implicit state spaces.
IDA* engine for implicit state spaces with an admissible heuristic.
Distance heuristic(const State &s) const noexcept
void apply(State &s, const Move &m) const noexcept
bool is_goal(const State &s) const noexcept
void undo(State &s, const Move &m) const noexcept
State_Key state_key(const State &s) const noexcept
bool for_each_successor(const State &s, Visitor visit) const
Distance cost(const State &, const Move &m) const noexcept
State_Key state_key(const State &s) const noexcept
void apply(State &s, const Move &m) const noexcept
void undo(State &s, const Move &m) const noexcept
bool for_each_successor(const State &s, Visitor visit) const
Distance heuristic(const State &) const noexcept
Distance cost(const State &, const Move &m) const noexcept
bool is_goal(const State &s) const noexcept
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
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.
Distance accessor.
FooMap m(5, fst_unit_pair_hash, snd_unit_pair_hash)
static mt19937 engine