72 template <
class Derived2,
class Tree2>
85 static constexpr MapType
const Type = MapType::COST;
94 using coord_t =
typename Tree::coord_t;
95 using depth_t =
typename Tree::depth_t;
96 using offset_t =
typename Tree::offset_t;
97 using length_t =
typename Tree::length_t;
98 using pos_t =
typename Tree::pos_t;
101 using cost_t =
typename CostBlock<BF>::cost_t;
110 template <
class NodeType,
111 std::enable_if_t<Tree::template is_node_type_v<NodeType>,
bool> =
true>
112 [[nodiscard]] cost_t cost(NodeType node)
const
114 Index n = derived().index(node);
115 return costBlock(n.pos)[n.offset].cost;
135 template <
class NodeType,
136 std::enable_if_t<Tree::template is_node_type_v<NodeType>,
bool> =
true>
137 void costSet(NodeType node, cost_t value,
bool propagate =
true)
141 auto node_f = [
this, elem](Index node) { costBlock(node.pos)[node.offset] = elem; };
142 auto block_f = [
this, elem](pos_t pos) { costBlock(pos).fill(elem); };
144 if constexpr (std::is_same_v<Index, std::decay_t<NodeType>>) {
146 derived().recursParentFirst(node, node_f, block_f);
148 derived().recursLeaves(node, node_f, block_f);
152 auto propagate_f = [
this](Index node, pos_t children) {
153 onPropagateChildren(node, children);
156 derived().recursLeaves(derived().code(node), node_f, block_f, propagate_f,
159 derived().recursParentFirst(derived().code(node), node_f, block_f);
164 template <
class NodeType,
165 std::enable_if_t<Tree::template is_node_type_v<NodeType>,
bool> =
true>
166 void costUpdate(NodeType node, cost_t change,
bool propagate =
true)
170 [
this, change](Index node) {
171 return CostBlock(node.pos)[node.offset].cost + change;
176 template <
class NodeType,
class UnaryOp,
177 std::enable_if_t<Tree::template is_node_type_v<NodeType>,
bool> =
true,
178 std::enable_if_t<std::is_invocable_r_v<cost_t, UnaryOp, Index>,
bool> =
true>
179 void costUpdate(NodeType node, UnaryOp unary_op,
bool propagate =
true)
181 auto node_f = [
this, unary_op](Index node) {
182 cost_t value = unary_op(node);
184 auto& cb = CostBlock(node.pos)[node.offset];
188 auto block_f = [
this, node_f](pos_t pos) {
189 for (std::size_t i{}; BF > i; ++i) {
190 node_f(Index(pos, i));
194 auto propagate_f = [
this](Index node, pos_t children) {
195 onPropagateChildren(node, children);
198 if constexpr (std::is_same_v<Index, std::decay_t<NodeType>>) {
200 derived().recursLeaves(node, node_f, block_f, propagate_f);
202 derived().recursLeaves(node, node_f, block_f);
205 derived().recursLeaves(derived().code(node), node_f, block_f, propagate_f,
214 [[nodiscard]]
constexpr CostPropagationCriteria costPropagationCriteria() const noexcept
216 return prop_criteria_;
219 void costSetPropagationCriteria(CostPropagationCriteria prop_criteria,
220 bool propagate =
true)
222 if (CostPropagationCriteria() == prop_criteria) {
226 prop_criteria_ = prop_criteria;
230 derived().setModified();
233 derived().propagateModified();
244 CostMap() { onInitRoot(); }
246 CostMap(CostMap
const& other) =
default;
248 CostMap(CostMap&& other) =
default;
250 template <
class Derived2,
class Tree2>
251 CostMap(CostMap<Derived2, Tree2>
const& other) : prop_criteria_(other.prop_criteria_)
255 template <
class Derived2,
class Tree2>
256 CostMap(CostMap<Derived2, Tree2>&& other)
257 : prop_criteria_(
std::move(other.prop_criteria_))
267 ~CostMap() =
default;
275 CostMap& operator=(CostMap
const& rhs) =
default;
277 CostMap& operator=(CostMap&& rhs) =
default;
279 template <
class Derived2,
class Tree2>
280 CostMap& operator=(CostMap<Derived2, Tree2>
const& rhs)
282 prop_criteria_ = rhs.prop_criteria_;
286 template <
class Derived2,
class Tree2>
287 CostMap& operator=(CostMap<Derived2, Tree2>&& rhs)
289 prop_criteria_ = std::move(rhs.prop_criteria_);
297 void swap(CostMap& other)
noexcept { std::swap(prop_criteria_, other.prop_criteria_); }
305 [[nodiscard]]
constexpr Derived& derived() {
return *
static_cast<Derived*
>(
this); }
307 [[nodiscard]]
constexpr Derived
const& derived()
const
309 return *
static_cast<Derived const*
>(
this);
318 [[nodiscard]] CostBlock<BF>& costBlock(pos_t pos)
320 return derived().template data<CostBlock<BF>>(pos);
323 [[nodiscard]] CostBlock<BF>
const& costBlock(pos_t pos)
const
325 return derived().template data<CostBlock<BF>>(pos);
336 auto& block = costBlock(0);
339 block[0].cost = value;
342 void onInitChildren(Index node, pos_t children)
344 costBlock(children).fill(costBlock(node.pos)[node.offset]);
347 void onPruneChildren(Index node, pos_t children)
349 auto& v = costBlock(node.pos)[node.offset];
352 void onPropagateChildren(Index node, pos_t children)
354 auto const& children_block = costBlock(children);
356 auto& cb = costBlock(node.pos)[node.offset];
359 switch (prop_criteria_) {
360 case CostPropagationCriteria::MAX:
361 value = std::numeric_limits<cost_t>::lowest();
362 for (std::size_t i{}; BF > i; ++i) {
363 value = UFO_MAX(value, children_block[i].cost);
366 case CostPropagationCriteria::MIN:
367 value = std::numeric_limits<cost_t>::max();
368 for (std::size_t i{}; BF > i; ++i) {
369 value = UFO_MIN(value, children_block[i].cost);
372 case CostPropagationCriteria::MEAN: {
374 for (std::size_t i{}; BF > i; ++i) {
375 v +=
static_cast<int>(children_block[i].cost);
377 value =
static_cast<cost_t
>(v /
static_cast<int>(BF));
380 case CostPropagationCriteria::NONE:
return;
390 [[nodiscard]]
bool prunable(pos_t block)
const
395 begin(costBlock(block).data) + 1, end(costBlock(block).data),
396 [v = costBlock(block)[0].cost](
auto const& e) {
return v == e.cost; });
403 [[nodiscard]]
static constexpr std::size_t serializedSizeNode() noexcept
405 return sizeof(cost_t);
408 [[nodiscard]]
constexpr std::size_t serializedSize(
409 std::vector<std::pair<pos_t, BitSet<BF>>>
const& ,
410 std::size_t num_nodes)
const
412 return num_nodes * serializedSizeNode();
415 void onRead(ReadBuffer& in, std::vector<std::pair<pos_t, BitSet<BF>>>
const& nodes)
417 for (
auto [block, offset] : nodes) {
418 auto& cb = costBlock(block);
421 std::array<cost_t, BF> cost;
423 for (offset_t i{}; BF > i; ++i) {
424 cb[i] = CostElement(cost[i]);
427 for (offset_t i{}; BF > i; ++i) {
431 cb[i] = CostElement(value);
438 void onWrite(WriteBuffer& out, std::vector<std::pair<pos_t, BitSet<BF>>>
const& nodes)
440 for (
auto [block, offset] : nodes) {
441 auto const& cb = CostBlock(block);
444 std::array<cost_t, BF> cost;
445 for (offset_t i{}; BF > i; ++i) {
446 cost[i] = cb[i].cost;
450 for (offset_t i{}; BF > i; ++i) {
452 out.write(cb[i].cost);
463 void onDotFileInfo(std::ostream& out, Index node)
const
465 out <<
"Cost: " << cost(node);
470 CostPropagationCriteria prop_criteria_ = CostPropagationCriteria::MAX;