<commit_before>/* vim:set ts=4 sw=4 sts=4 et: */

#include <set>
#include <stdexcept>
#include <igraph/cpp/edge.h>
#include <igraph/cpp/generators/line_graph.h>
#include <netctrl/model/liu.h>
#include <netctrl/model/switchboard.h>

namespace netctrl {

using namespace igraph;

SwitchboardControllabilityModel::~SwitchboardControllabilityModel() {
    clearControlPaths();
}

void SwitchboardControllabilityModel::calculate() {
    // Construct the line graph first
    Graph lg(line_graph(*m_pGraph));

    // Find the driver nodes in the line graph; these are the driver edges
    // in our model
    LiuControllabilityModel model(&lg);
    model.calculate();
    
    // Loop through the stems and buds of the line graph. The root of each
    // stem represents an edge in the original graph and its tail will
    // become a driver node.
    std::vector<ControlPath*> controlPaths = model.controlPaths();
    std::set<long int> driverNodeSet;

    for (std::vector<ControlPath*>::const_iterator it = controlPaths.begin();
            it != controlPaths.end(); it++) {
        ControlPath* path = *it;
        Stem* stem = dynamic_cast<Stem*>(path);
        if (stem != 0) {
            // Store the source vertex of the root of the stem
            driverNodeSet.insert(m_pGraph->edge(stem->root()).tail());
        }
    }
<commit_msg>fixed an edge case in the switchboard dynamics<commit_after>/* vim:set ts=4 sw=4 sts=4 et: */

#include <set>
#include <stdexcept>
#include <igraph/cpp/edge.h>
#include <igraph/cpp/generators/line_graph.h>
#include <netctrl/model/liu.h>
#include <netctrl/model/switchboard.h>

namespace netctrl {

using namespace igraph;

SwitchboardControllabilityModel::~SwitchboardControllabilityModel() {
    clearControlPaths();
}

void SwitchboardControllabilityModel::calculate() {
    // Construct the line graph first
    Graph lg(line_graph(*m_pGraph));

    // Find the driver nodes in the line graph; these are the driver edges
    // in our model
    LiuControllabilityModel model(&lg);
    model.calculate();
    
    // Loop through the stems and buds of the line graph. The root of each
    // stem represents an edge in the original graph and its tail will
    // become a driver node.
    std::vector<ControlPath*> controlPaths = model.controlPaths();
    std::set<long int> driverNodeSet;

    for (std::vector<ControlPath*>::const_iterator it = controlPaths.begin();
            it != controlPaths.end(); it++) {
        ControlPath* path = *it;
        Stem* stem = dynamic_cast<Stem*>(path);
        if (stem != 0) {
            // Store the source vertex of the root of the stem
            driverNodeSet.insert(m_pGraph->edge(stem->root()).tail());
        }
    }
    
    // Now, check the buds. Each bud that is not attached to a stem in the line
    // graph is problematic. For such buds, we have to iterate over its edges,
    // map the endpoints of the edges back to the original graph, and see if
    // any of these is already a driver node. If so, we are okay. If not, we
    // have to make one of the nodes a driver node.
    for (std::vector<ControlPath*>::const_iterator it = controlPaths.begin();
            it != controlPaths.end(); it++) {
        ControlPath* path = *it;
        Bud* bud = dynamic_cast<Bud*>(path);
        if (bud != 0 && bud->stem() == 0) {
            Vector::const_iterator it, end = bud->nodes().end();
            bool foundDriverNode = false;

            for (it = bud->nodes().begin(); it != end && !foundDriverNode; it++) {
                if (driverNodeSet.find(*it) != driverNodeSet.end())
                    foundDriverNode = true;
            }

            if (!foundDriverNode) {
                // TODO: better strategy; what if there is another node which
                // could control more than one bud? Is it possible?
                driverNodeSet.insert(bud->nodes().front());
            }
        }
    }

{'fraction_non_alphanumeric': 0.11967338606787446, 'fraction_numerical': 0.0025516713447307987, 'mean_word_length': 2.7086092715231787, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5370076', 'n_tokens_mistral': 1153, 'n_tokens_neox': 1116, 'n_words': 367}