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