1 /* ///////////////////////////////////////////////////////////////////////
7 * Brief: The net_base class - compact net
10 * Copyright (c) 2008-2020, Waruqi All rights reserved.
11 * //////////////////////////////////////////////////////////////////// */
13 #ifndef EXTL_CONTAINER_NET_BASE_H
14 #define EXTL_CONTAINER_NET_BASE_H
17 * \brief net_base class
20 /* ///////////////////////////////////////////////////////////////////////
24 #include "detail/net_base_impl.h"
25 #include "detail/net_node_iterator.h"
26 #include "detail/net_arc_iterator.h"
27 /* ///////////////////////////////////////////////////////////////////////
35 * \param is_dir returns \true if it's a directed net
36 * \param Nods the nodes type
37 * \param Mtx1 the adjacent matrix type for directed net
38 * \param Mtx2 the adjacent matrix type for indirected net - symmetrical matrix
40 * \ingroup extl_group_container
42 template< typename_param_k Dev
44 , typename_param_k Nods
45 , typename_param_k Mtx1
46 , typename_param_k Mtx2
49 : public EXTL_NS_DETAIL(net_base_impl
)<is_dir
>::template_qual_k impl
< Dev
55 /// \name Protected Types
58 typedef typename_type_k
EXTL_NS_DETAIL(net_base_impl
)<is_dir
>::
59 template_qual_k impl
< Dev
64 typedef Dev derived_type
;
65 typedef typename_type_k
base_type::adjmtx_type adjmtx_type
;
66 typedef typename_type_k
base_type::node_type node_type
;
67 typedef typename_type_k
base_type::nodes_type nodes_type
;
68 typedef typename_type_k
base_type::arc_type arc_type
;
69 typedef typename_type_k
base_type::weight_type weight_type
;
70 #ifdef EXTL_TYPE_ALIAS_FRIEND_SUPPORT
75 /// \name Public Types
78 typedef net_base class_type
;
79 typedef typename_type_k
base_type::value_type value_type
;
80 typedef typename_type_k
base_type::pointer pointer
;
81 typedef typename_type_k
base_type::const_pointer const_pointer
;
82 typedef typename_type_k
base_type::reference reference
;
83 typedef typename_type_k
base_type::const_reference const_reference
;
84 typedef typename_type_k
base_type::size_type size_type
;
85 typedef typename_type_k
base_type::bool_type bool_type
;
86 typedef typename_type_k
base_type::difference_type difference_type
;
87 typedef typename_type_k
base_type::int_type int_type
;
88 typedef typename_type_k
base_type::index_type index_type
;
90 // const_node_iterator
91 typedef EXTL_NS_DETAIL(const_net_node_iterator
)<nodes_type
> const_node_iterator
;
92 typedef const_reverse_bidirectional_iterator_base
<const_node_iterator
> const_reverse_node_iterator
;
95 typedef EXTL_NS_DETAIL(const_net_arc_iterator
)<adjmtx_type
> const_arc_iterator
;
96 typedef const_reverse_bidirectional_iterator_base
<const_arc_iterator
> const_reverse_arc_iterator
;
102 EXTL_STATIC_MEMBER_CONST(bool_type
, is_directed
= is_dir
);
109 adjmtx_type m_adjmtx
;
115 net_base(class_type
const& rhs
);
116 class_type
& operator =(class_type
& rhs
);
118 /// \name Constructors
121 explicit_k
net_base(size_type max_nodes_n
)
122 : m_nodes(max_nodes_n
)
123 , m_adjmtx(max_nodes_n
, max_nodes_n
)
128 EXTL_ASSERT(derive().is_valid());
130 net_base(derived_type
const& rhs
)
131 : m_nodes(rhs
.nodes())
132 , m_adjmtx(rhs
.adjmtx())
133 , m_arcs_n(rhs
.arcs_size())
134 , m_nodes_n(rhs
.nodes_size())
136 EXTL_ASSERT(derive().is_valid());
143 size_type
nodes_size() const { return m_nodes_n
; }
144 size_type
size() const { return derive().nodes_size(); }
145 size_type
arcs_size() const { return m_arcs_n
; }
146 bool_type
is_empty() const { return nodes().is_empty(); }
147 bool_type
empty() const { return derive().is_empty(); }
148 size_type
max_nodes_size() const { return nodes().size(); }
149 size_type
max_size() const { return derive().max_nodes_size(); }
150 size_type
max_arcs_size() const { return derive().max_arcs_size_impl(); }
151 bool_type
is_valid() const;
158 void swap(derived_type
& rhs
);
159 derived_type
& operator =(derived_type
& rhs
);
161 derived_type
& insert_arc(index_type bid
, index_type eid
, weight_type w
= weight_type());
162 derived_type
& remove_arc(index_type bid
, index_type eid
);
164 derived_type
& insert_node(index_type id
, const_reference val
= value_type());
165 derived_type
& remove_node(index_type id
);
171 bool_type
node_exists(index_type id
) const;
172 bool_type
arc_exists(index_type bid
, index_type eid
) const;
174 const_reference
at(index_type id
) const { return node_at(id
).value(); }
175 reference
at(index_type id
) { return node_at(id
).value(); }
177 weight_type
const& weight(index_type bid
, index_type eid
) const { return derive().adjmtx_at(bid
, eid
).weight(); }
178 weight_type
& weight(index_type bid
, index_type eid
) { return derive().adjmtx_at(bid
, eid
).weight(); }
180 size_type
degree(index_type id
) const { return node_at(id
).degree(); }
183 /// \name Node Iterators
184 /// \note cannot insert and erase nodes in the iteration
187 const_node_iterator
node_begin() const { return const_node_iterator(nodes().begin(), nodes()); }
188 const_node_iterator
node_end() const { return const_node_iterator(nodes().end(), nodes()); }
190 const_reverse_node_iterator
node_rbegin() const { return const_reverse_node_iterator(node_end()); }
191 const_reverse_node_iterator
node_rend() const { return const_reverse_node_iterator(node_begin()); }
194 /// \name Arc Iterators
195 /// \note cannot insert and erase arcs in the iteration
198 const_arc_iterator
arc_begin() const { return const_arc_iterator(adjmtx().begin(), adjmtx()); }
199 const_arc_iterator
arc_end() const { return const_arc_iterator(adjmtx().end(), adjmtx()); }
201 const_reverse_arc_iterator
arc_rbegin() const { return const_reverse_arc_iterator(arc_end()); }
202 const_reverse_arc_iterator
arc_rend() const { return const_reverse_arc_iterator(arc_begin()); }
205 /// \name Protected Accessors
207 #ifdef EXTL_TYPE_ALIAS_FRIEND_SUPPORT
212 nodes_type
& nodes() { return m_nodes
; }
213 nodes_type
const& nodes() const { return m_nodes
; }
215 adjmtx_type
& adjmtx() { return m_adjmtx
; }
216 adjmtx_type
const& adjmtx() const { return m_adjmtx
; }
219 /// \name Protected Unsafe Mutators
221 #ifdef EXTL_TYPE_ALIAS_FRIEND_SUPPORT
226 void unsafe_insert_arc(index_type bid
, index_type eid
, weight_type w
);
227 void unsafe_remove_arc(index_type bid
, index_type eid
);
228 void unsafe_insert_node(index_type id
, const_reference val
);
229 void unsafe_remove_node(index_type id
);
234 #ifdef EXTL_TYPE_ALIAS_FRIEND_SUPPORT
242 node_type
& node_at(index_type id
);
243 node_type
const& node_at(index_type id
) const;
245 node_type
& node_at_uncheck(index_type id
);
246 node_type
const& node_at_uncheck(index_type id
) const;
248 arc_type
& adjmtx_at(index_type bid
, index_type eid
);
249 arc_type
const& adjmtx_at(index_type bid
, index_type eid
) const;
251 arc_type
& adjmtx_at_uncheck(index_type bid
, index_type eid
);
252 arc_type
const& adjmtx_at_uncheck(index_type bid
, index_type eid
) const;
254 derived_type
& derive() { return static_cast<derived_type
&>(*this); }
255 derived_type
const& derive() const { return static_cast<derived_type
const&>(*this); }
259 /* ///////////////////////////////////////////////////////////////////////
262 // Template declaration
263 #ifdef EXTL_NET_BASE_TEMPLATE_DECL
264 # undef EXTL_NET_BASE_TEMPLATE_DECL
267 #define EXTL_NET_BASE_TEMPLATE_DECL \
268 template< typename_param_k Dev \
270 , typename_param_k Nods \
271 , typename_param_k Mtx1 \
272 , typename_param_k Mtx2 \
275 // Class qualification
276 #ifdef EXTL_NET_BASE_QUAL
277 # undef EXTL_NET_BASE_QUAL
280 #define EXTL_NET_BASE_QUAL net_base<Dev, is_dir, Nods, Mtx1, Mtx2>
282 // Class qualification
283 #ifdef EXTL_NET_BASE_RET_QUAL
284 # undef EXTL_NET_BASE_RET_QUAL
287 #define EXTL_NET_BASE_RET_QUAL(ret_type) \
288 typename_type_ret_k EXTL_NET_BASE_QUAL::ret_type \
291 /* ///////////////////////////////////////////////////////////////////////
295 EXTL_NET_BASE_TEMPLATE_DECL
296 inline void EXTL_NET_BASE_QUAL::unsafe_insert_node(index_type id
, const_reference val
)
299 //EXTL_ASSERT(derive().is_valid());
300 if (!derive().node_exists(id
)) // insert node if not exists
302 derive().node_at_uncheck(id
) = node_type(id
, val
);
305 else // update node if exists
307 EXTL_ASSERT(id
== derive().node_at_uncheck(id
).id());
308 derive().node_at_uncheck(id
) = node_type(id
, val
);
311 //EXTL_ASSERT(derive().is_valid());
313 EXTL_NET_BASE_TEMPLATE_DECL
314 inline void EXTL_NET_BASE_QUAL::unsafe_remove_node(index_type id
)
316 if (!derive().node_exists(id
)) return;
318 //EXTL_ASSERT(derive().is_valid());
320 derive().node_at_uncheck(id
).clear();
323 EXTL_ASSERT(!derive().node_exists(id
));
324 //EXTL_ASSERT(derive().is_valid());
326 EXTL_NET_BASE_TEMPLATE_DECL
327 inline void EXTL_NET_BASE_QUAL::unsafe_insert_arc(index_type bid
, index_type eid
, weight_type w
)
329 //EXTL_ASSERT(derive().is_valid());
331 if (!derive().arc_exists(bid
, eid
)) // insert arc if not exists
333 derive().adjmtx_at_uncheck(bid
, eid
) = arc_type(bid
, eid
, w
);
334 derive().inc_degree(bid
, eid
);
337 else // update arc if exists
339 derive().adjmtx_at_uncheck(bid
, eid
) = arc_type(bid
, eid
, w
);
342 //EXTL_ASSERT(derive().is_valid());
344 EXTL_NET_BASE_TEMPLATE_DECL
345 inline void EXTL_NET_BASE_QUAL::unsafe_remove_arc(index_type bid
, index_type eid
)
347 if (!derive().arc_exists(bid
, eid
)) return ;
349 //EXTL_ASSERT(derive().is_valid());
351 derive().adjmtx_at_uncheck(bid
, eid
).clear();
352 derive().dec_degree(bid
, eid
);
355 EXTL_ASSERT(!derive().arc_exists(bid
, eid
));
356 //EXTL_ASSERT(derive().is_valid());
359 EXTL_NET_BASE_TEMPLATE_DECL
360 inline EXTL_NET_BASE_RET_QUAL(derived_type
&)::insert_arc(index_type bid
, index_type eid
, weight_type w
)
362 EXTL_ASSERT(derive().is_valid());
366 // insert it at first if node not exist
367 if (derive().node_at_uncheck(bid
).is_empty())
369 derive().unsafe_insert_node(bid
, value_type());
373 if (derive().node_at_uncheck(eid
).is_empty())
375 derive().unsafe_insert_node(eid
, value_type());
379 unsafe_insert_arc(bid
, eid
, w
);
384 derive().unsafe_remove_node(eid
);
386 derive().unsafe_remove_node(bid
);
394 EXTL_ASSERT(derive().is_valid());
397 EXTL_NET_BASE_TEMPLATE_DECL
398 inline EXTL_NET_BASE_RET_QUAL(derived_type
&)::remove_arc(index_type bid
, index_type eid
)
400 EXTL_ASSERT(derive().is_valid());
401 derive().unsafe_remove_arc(bid
, eid
);
402 EXTL_ASSERT(derive().is_valid());
405 EXTL_NET_BASE_TEMPLATE_DECL
406 inline EXTL_NET_BASE_RET_QUAL(derived_type
&)::insert_node(index_type id
, const_reference val
)
408 EXTL_ASSERT(derive().is_valid());
409 derive().unsafe_insert_node(id
, val
);
410 EXTL_ASSERT(derive().is_valid());
414 EXTL_NET_BASE_TEMPLATE_DECL
415 inline EXTL_NET_BASE_RET_QUAL(derived_type
&)::remove_node(index_type id
)
417 EXTL_ASSERT(derive().is_valid());
418 #ifdef EXTL_EXCEPTION_ENABLE
419 // need erase arcs in the vicinity of the node at first
420 derived_type
tmp(derive());
421 tmp
.safe_remove_node(id
);
424 derive().safe_remove_node(id
);
426 EXTL_ASSERT(derive().is_valid());
430 EXTL_NET_BASE_TEMPLATE_DECL
431 inline void EXTL_NET_BASE_QUAL::clear_nodes()
433 typedef typename_type_k
nodes_type::iterator node_iterator_
;
434 for (node_iterator_ pn
= nodes().begin(); pn
!= nodes().end(); ++pn
)
438 EXTL_NET_BASE_TEMPLATE_DECL
439 inline void EXTL_NET_BASE_QUAL::clear_adjmtx()
441 typedef typename_type_k
adjmtx_type::iterator arc_iterator_
;
442 for (arc_iterator_ pa
= adjmtx().begin(); pa
!= adjmtx().end(); ++pa
)
446 EXTL_NET_BASE_TEMPLATE_DECL
447 inline void EXTL_NET_BASE_QUAL::clear()
449 derive().clear_nodes();
450 derive().clear_adjmtx();
455 EXTL_ASSERT(derive().is_valid());
458 EXTL_NET_BASE_TEMPLATE_DECL
459 inline void EXTL_NET_BASE_QUAL::swap(derived_type
& rhs
)
461 EXTL_ASSERT(derive().is_valid());
462 nodes().swap(static_cast<class_type
&>(rhs
).m_nodes
);
463 adjmtx().swap(static_cast<class_type
&>(rhs
).m_adjmtx
);
464 std_swap(m_arcs_n
, static_cast<class_type
&>(rhs
).m_arcs_n
);
465 std_swap(m_nodes_n
, static_cast<class_type
&>(rhs
).m_nodes_n
);
466 EXTL_ASSERT(derive().is_valid());
469 EXTL_NET_BASE_TEMPLATE_DECL
470 inline EXTL_NET_BASE_RET_QUAL(derived_type
&)::operator =(derived_type
& rhs
)
472 EXTL_ASSERT(derive().is_valid());
473 derived_type(rhs
).swap(derive());
474 EXTL_ASSERT(derive().is_valid());
477 EXTL_NET_BASE_TEMPLATE_DECL
478 inline EXTL_NET_BASE_RET_QUAL(node_type
const&)::node_at(index_type id
) const
480 EXTL_MESSAGE_ASSERT(id
< nodes().size(), "out of range");
481 EXTL_ASSERT_THROW(id
< nodes().size(), "out of range");
483 EXTL_MESSAGE_ASSERT(!nodes()[id
].is_empty(), "node not exists");
484 EXTL_ASSERT_THROW(!nodes()[id
].is_empty(), "node not exists");
488 EXTL_NET_BASE_TEMPLATE_DECL
489 inline EXTL_NET_BASE_RET_QUAL(node_type
&)::node_at(index_type id
)
491 return const_cast<node_type
&>(static_cast<derived_type
const&>(*this).node_at(id
));
493 EXTL_NET_BASE_TEMPLATE_DECL
494 inline EXTL_NET_BASE_RET_QUAL(node_type
const&)::node_at_uncheck(index_type id
) const
496 EXTL_MESSAGE_ASSERT(id
< nodes().size(), "out of range");
499 EXTL_NET_BASE_TEMPLATE_DECL
500 inline EXTL_NET_BASE_RET_QUAL(node_type
&)::node_at_uncheck(index_type id
)
502 return const_cast<node_type
&>(static_cast<derived_type
const&>(*this).node_at_uncheck(id
));
505 EXTL_NET_BASE_TEMPLATE_DECL
506 inline EXTL_NET_BASE_RET_QUAL(arc_type
&)::adjmtx_at(index_type bid
, index_type eid
)
508 return const_cast<arc_type
&>(static_cast<derived_type
const&>(*this).adjmtx_at(bid
, eid
));
510 EXTL_NET_BASE_TEMPLATE_DECL
511 inline EXTL_NET_BASE_RET_QUAL(arc_type
const&)::adjmtx_at(index_type bid
, index_type eid
) const
513 EXTL_MESSAGE_ASSERT ( bid
< adjmtx().dim0()
514 && eid
< adjmtx().dim1()
515 , "adjmtx_at: out of range");
517 EXTL_ASSERT_THROW ( bid
< adjmtx().dim0()
518 && eid
< adjmtx().dim1()
519 , "adjmtx_at: out of range");
521 EXTL_MESSAGE_ASSERT ( derive().arc_exists(bid
, eid
)
522 , "adjmtx_at: arc not exist");
524 EXTL_ASSERT_THROW ( derive().arc_exists(bid
, eid
)
525 , "adjmtx_at: arc not exist");
528 return adjmtx().at(bid
, eid
);
530 EXTL_NET_BASE_TEMPLATE_DECL
531 inline EXTL_NET_BASE_RET_QUAL(arc_type
&)::adjmtx_at_uncheck(index_type bid
, index_type eid
)
533 return const_cast<arc_type
&>(static_cast<derived_type
const&>(*this).adjmtx_at_uncheck(bid
, eid
));
535 EXTL_NET_BASE_TEMPLATE_DECL
536 inline EXTL_NET_BASE_RET_QUAL(arc_type
const&)::adjmtx_at_uncheck(index_type bid
, index_type eid
) const
538 EXTL_MESSAGE_ASSERT ( bid
< adjmtx().dim0()
539 && eid
< adjmtx().dim1()
540 , "adjmtx_at: out of range");
542 // note: can not call arc_exists(bid, eid) at this.
543 // note: can not call is_valid() at this.
545 return adjmtx().at(bid
, eid
);
548 EXTL_NET_BASE_TEMPLATE_DECL
549 inline EXTL_NET_BASE_RET_QUAL(bool_type
)::node_exists(index_type id
) const
551 if (!(id
< nodes().size())) return e_false_v
;
552 return !node_at_uncheck(id
).is_empty();
554 EXTL_NET_BASE_TEMPLATE_DECL
555 inline EXTL_NET_BASE_RET_QUAL(bool_type
)::arc_exists(index_type bid
, index_type eid
) const
557 // note: can not call is_valid() at this.
558 if (!(bid
< adjmtx().dim0() && eid
< adjmtx().dim1()))
560 return !this->adjmtx_at_uncheck(bid
, eid
).is_empty();
563 EXTL_NET_BASE_TEMPLATE_DECL
564 inline EXTL_NET_BASE_RET_QUAL(bool_type
)::is_valid() const
566 size_type n0
= adjmtx().dim0();
567 size_type n1
= adjmtx().dim1();
569 if (n0
!= n1
) return e_false_v
;
570 if (derive().nodes_size() > derive().max_nodes_size()) return e_false_v
;
571 if (derive().arcs_size() > derive().max_arcs_size()) return e_false_v
;
573 for (index_type i
= 0; i
< n0
; ++i
)
575 for (index_type j
= 0; j
< n1
; ++j
)
577 if (!derive().arc_exists(i
, j
)) continue;
580 if (!adjmtx().at(i
, j
).is_valid())
584 if ( adjmtx().at(i
, j
).begin_id() >= nodes().size()
585 || adjmtx().at(i
, j
).end_id() >= nodes().size())
591 if (adjmtx().at(i
, j
).begin_id() != i
|| adjmtx().at(i
, j
).end_id() != j
)
596 if ((adjmtx().at(i
, j
).begin_id() != i
&& adjmtx().at(i
, j
).begin_id() != j
)
597 || (adjmtx().at(i
, j
).end_id() != i
&& adjmtx().at(i
, j
).end_id() != j
))
602 if (nodes()[adjmtx().at(i
, j
).begin_id()].is_empty())
606 if (nodes()[adjmtx().at(i
, j
).end_id()].is_empty())
614 /* //////////////////////////////////////////////////////////////////// */
615 #undef EXTL_NET_BASE_TEMPLATE_DECL
616 #undef EXTL_NET_BASE_QUAL
617 #undef EXTL_NET_BASE_RET_QUAL
619 /* ///////////////////////////////////////////////////////////////////////
624 /* //////////////////////////////////////////////////////////////////// */
625 #endif /* EXTL_CONTAINER_NET_BASE_H */
626 /* //////////////////////////////////////////////////////////////////// */