Avoid dynamic_cast<..>
This commit is contained in:
parent
dd452f73da
commit
a9010855a5
|
@ -201,6 +201,9 @@ struct Blossom
|
|||
/** Label S or T if this is a top-level blossom in an alternating tree. */
|
||||
BlossomLabel label;
|
||||
|
||||
/** True if this is an instance of NonTrivialBlossom. */
|
||||
const bool is_nontrivial_blossom;
|
||||
|
||||
/** Optional edge that attaches this blossom to the alternating tree. */
|
||||
VertexPair tree_edge;
|
||||
|
||||
|
@ -212,16 +215,32 @@ struct Blossom
|
|||
// TODO : consider storing a copy of the edge instead of pointer
|
||||
const Edge<WeightType>* best_edge;
|
||||
|
||||
/** Initialize a trivial (single-vertex) blossom. */
|
||||
explicit Blossom(VertexId base_vertex)
|
||||
protected:
|
||||
/** Initialize base class. */
|
||||
Blossom(VertexId base_vertex, bool is_nontrivial_blossom)
|
||||
: parent(nullptr),
|
||||
base_vertex(base_vertex),
|
||||
label(LABEL_NONE),
|
||||
is_nontrivial_blossom(is_nontrivial_blossom),
|
||||
best_edge(nullptr)
|
||||
{ }
|
||||
|
||||
// Dummy virtual method to allow the use of dynamic_cast<>.
|
||||
virtual ~Blossom() = default;
|
||||
public:
|
||||
/** Initialize a trivial (single-vertex) blossom. */
|
||||
explicit Blossom(VertexId base_vertex)
|
||||
: Blossom(base_vertex, false)
|
||||
{ }
|
||||
|
||||
/**
|
||||
* Cast this Blossom instance to NonTrivialBlossom if possible,
|
||||
* otherwise return "nullptr".
|
||||
*/
|
||||
NonTrivialBlossom<WeightType>* nontrivial()
|
||||
{
|
||||
return (is_nontrivial_blossom ?
|
||||
static_cast<NonTrivialBlossom<WeightType>*>(this)
|
||||
: nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -279,7 +298,7 @@ struct NonTrivialBlossom : public Blossom<WeightType>
|
|||
NonTrivialBlossom(
|
||||
const std::vector<Blossom<WeightType>*>& subblossoms,
|
||||
const std::deque<VertexPair>& edges)
|
||||
: Blossom<WeightType>(subblossoms.front()->base_vertex),
|
||||
: Blossom<WeightType>(subblossoms.front()->base_vertex, true),
|
||||
dual_var(0)
|
||||
{
|
||||
assert(subblossoms.size() == edges.size());
|
||||
|
@ -543,11 +562,10 @@ struct MatchingContext
|
|||
template <typename Func>
|
||||
void for_vertices_in_blossom(BlossomT* blossom, Func func)
|
||||
{
|
||||
NonTrivialBlossomT* ntb = dynamic_cast<NonTrivialBlossomT*>(blossom);
|
||||
NonTrivialBlossomT* ntb = blossom->nontrivial();
|
||||
if (ntb) {
|
||||
// Visit all vertices in the non-trivial blossom.
|
||||
// Use an explicit stack to avoid deep call chains.
|
||||
// TODO : re-use a global stack instance
|
||||
std::vector<NonTrivialBlossomT*> stack;
|
||||
stack.push_back(ntb);
|
||||
|
||||
|
@ -556,7 +574,7 @@ struct MatchingContext
|
|||
stack.pop_back();
|
||||
|
||||
for (const auto& sub : b->subblossoms) {
|
||||
ntb = dynamic_cast<NonTrivialBlossomT*>(sub.blossom);
|
||||
ntb = sub.blossom->nontrivial();
|
||||
if (ntb) {
|
||||
stack.push_back(ntb);
|
||||
} else {
|
||||
|
@ -673,7 +691,7 @@ struct MatchingContext
|
|||
void lset_new_blossom(BlossomT* blossom)
|
||||
{
|
||||
assert(blossom->best_edge == nullptr);
|
||||
NonTrivialBlossomT* ntb = dynamic_cast<NonTrivialBlossomT*>(blossom);
|
||||
NonTrivialBlossomT* ntb = blossom->nontrivial();
|
||||
if (ntb) {
|
||||
assert(ntb->best_edge_set.empty());
|
||||
}
|
||||
|
@ -695,7 +713,7 @@ struct MatchingContext
|
|||
blossom->best_edge = edge;
|
||||
}
|
||||
|
||||
NonTrivialBlossomT* ntb = dynamic_cast<NonTrivialBlossomT*>(blossom);
|
||||
NonTrivialBlossomT* ntb = blossom->nontrivial();
|
||||
if (ntb) {
|
||||
ntb->best_edge_set.push_back(edge);
|
||||
}
|
||||
|
@ -716,8 +734,7 @@ struct MatchingContext
|
|||
for (auto& subblossom_item : blossom->subblossoms) {
|
||||
BlossomT* sub = subblossom_item.blossom;
|
||||
if (sub->label == LABEL_S) {
|
||||
NonTrivialBlossomT* ntb =
|
||||
dynamic_cast<NonTrivialBlossomT*>(sub);
|
||||
NonTrivialBlossomT* ntb = sub->nontrivial();
|
||||
if (ntb) {
|
||||
// Take least-slack edge set from this subblossom.
|
||||
blossom->best_edge_set.splice(
|
||||
|
@ -1175,14 +1192,14 @@ struct MatchingContext
|
|||
vertex_mate[y] = x;
|
||||
|
||||
// Augment through any non-trivial subblossoms touching this edge.
|
||||
NonTrivialBlossomT* bx_nt = dynamic_cast<NonTrivialBlossomT*>(bx);
|
||||
if (bx_nt != nullptr) {
|
||||
rec_stack.emplace(bx_nt, &trivial_blossom[x]);
|
||||
NonTrivialBlossomT* bx_ntb = bx->nontrivial();
|
||||
if (bx_ntb != nullptr) {
|
||||
rec_stack.emplace(bx_ntb, &trivial_blossom[x]);
|
||||
}
|
||||
|
||||
NonTrivialBlossomT* by_nt = dynamic_cast<NonTrivialBlossomT*>(by);
|
||||
if (by_nt != nullptr) {
|
||||
rec_stack.emplace(by_nt, &trivial_blossom[y]);
|
||||
NonTrivialBlossomT* by_ntb = by->nontrivial();
|
||||
if (by_ntb != nullptr) {
|
||||
rec_stack.emplace(by_ntb, &trivial_blossom[y]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1260,17 +1277,15 @@ struct MatchingContext
|
|||
|
||||
// Augment any non-trivial blossoms that touch this edge.
|
||||
BlossomT* bx = vertex_top_blossom[x];
|
||||
NonTrivialBlossomT* bx_nt =
|
||||
dynamic_cast<NonTrivialBlossomT*>(bx);
|
||||
if (bx_nt != nullptr) {
|
||||
augment_blossom(bx_nt, &trivial_blossom[x]);
|
||||
NonTrivialBlossomT* bx_ntb = bx->nontrivial();
|
||||
if (bx_ntb != nullptr) {
|
||||
augment_blossom(bx_ntb, &trivial_blossom[x]);
|
||||
}
|
||||
|
||||
BlossomT* by = vertex_top_blossom[y];
|
||||
NonTrivialBlossomT* by_nt =
|
||||
dynamic_cast<NonTrivialBlossomT*>(by);
|
||||
if (by_nt != nullptr) {
|
||||
augment_blossom(by_nt, &trivial_blossom[y]);
|
||||
NonTrivialBlossomT* by_ntb = by->nontrivial();
|
||||
if (by_ntb != nullptr) {
|
||||
augment_blossom(by_ntb, &trivial_blossom[y]);
|
||||
}
|
||||
|
||||
// Pull this edge into the matching.
|
||||
|
@ -1358,12 +1373,12 @@ struct MatchingContext
|
|||
// If "y" is part of a zero-dual blossom, expand it.
|
||||
// This would otherwise likely happen through a zero-delta4 step,
|
||||
// so we can just do it now and avoid a substage.
|
||||
NonTrivialBlossomT* ntb = dynamic_cast<NonTrivialBlossomT*>(by);
|
||||
NonTrivialBlossomT* ntb = by->nontrivial();
|
||||
while (ntb != nullptr && ntb->dual_var == 0) {
|
||||
expand_unlabeled_blossom(ntb);
|
||||
by = vertex_top_blossom[y];
|
||||
assert(by->label == LABEL_NONE);
|
||||
ntb = dynamic_cast<NonTrivialBlossomT*>(by);
|
||||
ntb = by->nontrivial();
|
||||
}
|
||||
|
||||
// Assign label T to the top-level blossom that contains vertex "y".
|
||||
|
@ -1787,7 +1802,7 @@ struct MatchingContext
|
|||
|
||||
// Examine the current sub-blossom.
|
||||
BlossomT* sub = subblossom_it->blossom;
|
||||
NonTrivialBlossomT* ntb = dynamic_cast<NonTrivialBlossomT*>(sub);
|
||||
NonTrivialBlossomT* ntb = sub->nontrivial();
|
||||
if (ntb) {
|
||||
// Prepare to descend into this sub-blossom.
|
||||
stack.emplace(std::make_pair(ntb, ntb->subblossoms.begin()));
|
||||
|
|
Loading…
Reference in New Issue