Example #1
0
static
bool pruneForwardUseless(NGHolder &h, const nfag_t &g, NFAVertex s,
                         vector<default_color_type> &vertexColor) {
    // Begin with all vertices set to white, as DFV only marks visited
    // vertices.
    fill(vertexColor.begin(), vertexColor.end(), boost::white_color);

    auto index_map = get(&NFAGraphVertexProps::index, g);

    depth_first_visit(g, s, make_dfs_visitor(boost::null_visitor()),
                      make_iterator_property_map(vertexColor.begin(),
                                                 index_map));

    vector<NFAVertex> dead;

    // All non-special vertices that are still white can be removed.
    for (auto v : vertices_range(g)) {
        u32 idx = g[v].index;
        if (!is_special(v, g) && vertexColor[idx] == boost::white_color) {
            DEBUG_PRINTF("vertex %u is unreachable from %u\n",
                         g[v].index, g[s].index);
            dead.push_back(v);
        }
    }

    if (dead.empty()) {
        return false;
    }

    DEBUG_PRINTF("removing %zu vertices\n", dead.size());
    remove_vertices(dead, h, false);
    return true;
}
Example #2
0
// Remove boundary vertices (and faces that touch them)
void erode(TriMesh *mesh)
{
	int nv = mesh->vertices.size();
	vector<bool> bdy(nv);
	for (int i = 0; i < nv; i++)
		bdy[i] = mesh->is_bdy(i);
	remove_vertices(mesh, bdy);
}
Example #3
0
// Clip mesh to the given bounding box 
void clip(TriMesh *mesh, const box &b)
{
	int nv = mesh->vertices.size();
	vector<bool> toremove(nv, false);
	for (int i = 0; i < nv; i++)
		if (mesh->vertices[i][0] < b.min[0] ||
		    mesh->vertices[i][0] > b.max[0] ||
		    mesh->vertices[i][1] < b.min[1] ||
		    mesh->vertices[i][1] > b.max[1] ||
		    mesh->vertices[i][2] < b.min[2] ||
		    mesh->vertices[i][2] > b.max[2])
			toremove[i] = true;

	remove_vertices(mesh, toremove);
}
Example #4
0
/** Remove any vertices that can't be reached by traversing the graph in
 * reverse from acceptEod. */
void pruneUnreachable(NGHolder &g) {
    deque<NFAVertex> dead;

    if (!hasGreaterInDegree(1, g.acceptEod, g) &&
            !hasGreaterInDegree(0, g.accept, g) &&
            edge(g.accept, g.acceptEod, g).second) {
        // Trivial case: there are no in-edges to our accepts (other than
        // accept->acceptEod), so all non-specials are unreachable.
        for (auto v : vertices_range(g)) {
            if (!is_special(v, g)) {
                dead.push_back(v);
            }
        }
    } else {
        // Walk a reverse graph from acceptEod with Boost's depth_first_visit
        // call.
        typedef reverse_graph<NFAGraph, NFAGraph&> RevNFAGraph;
        RevNFAGraph revg(g.g);

        map<NFAVertex, default_color_type> colours;

        depth_first_visit(revg, g.acceptEod,
                          make_dfs_visitor(boost::null_visitor()),
                          make_assoc_property_map(colours));

        DEBUG_PRINTF("color map has %zu entries after DFV\n", colours.size());

        // All non-special vertices that aren't in the colour map (because they
        // weren't reached) can be removed.
        for (auto v : vertices_range(revg)) {
            if (is_special(v, revg)) {
                continue;
            }
            if (!contains(colours, v)) {
                dead.push_back(v);
            }
        }
    }

    if (dead.empty()) {
        DEBUG_PRINTF("no unreachable vertices\n");
        return;
    }

    remove_vertices(dead, g, false);
    DEBUG_PRINTF("removed %zu unreachable vertices\n", dead.size());
}
Example #5
0
/** This code removes any vertices which do not accept any symbols. Any
 * vertices which no longer lie on a path from a start to an accept are also
 * pruned. */
void pruneEmptyVertices(NGHolder &g) {
    DEBUG_PRINTF("pruning empty vertices\n");
    vector<NFAVertex> dead;
    for (auto v : vertices_range(g)) {
        if (is_special(v, g)) {
            continue;
        }

        const CharReach &cr = g[v].char_reach;
        if (cr.none()) {
            DEBUG_PRINTF("empty: %u\n", g[v].index);
            dead.push_back(v);
        }
    }

    if (dead.empty()) {
        return;
    }

    remove_vertices(dead, g);
    pruneUseless(g);
}
Example #6
0
// walk through vertices of an equivalence class and replace them with a single
// vertex (or, in rare cases for left equiv, a pair if we cannot satisfy the
// report behaviour with a single vertex).
static
bool mergeEquivalentClasses(vector<VertexInfoSet> &classes,
                            ptr_vector<VertexInfo> &infos, NGHolder &g) {
    bool merged = false;
    set<NFAVertex> toRemove;

    // go through all classes and merge classes with more than one vertex
    for (unsigned eq_class = 0; eq_class < classes.size(); eq_class++) {
        // get all vertices in current equivalence class
        VertexInfoSet &cur_class_vertices = classes[eq_class];

        // we don't care for single-vertex classes
        if (cur_class_vertices.size() > 1) {
            merged = true;
            mergeClass(infos, g, eq_class, cur_class_vertices, &toRemove);
        }
    }

    // remove all dead vertices
    DEBUG_PRINTF("removing %zd vertices.\n", toRemove.size());
    remove_vertices(toRemove, g);

    return merged;
}
Example #7
0
static
u32 findMaxInfixMatches(const NGHolder &h, const set<ue2_literal> &lits) {
    DEBUG_PRINTF("h=%p, %zu literals\n", &h, lits.size());
    //dumpGraph("infix.dot", h.g);

    if (!onlyOneTop(h)) {
        DEBUG_PRINTF("more than one top!n");
        return NO_MATCH_LIMIT;
    }

    // Indices of vertices that could terminate any of the literals in 'lits'.
    set<u32> terms;

    for (const auto &s : lits) {
        DEBUG_PRINTF("lit s='%s'\n", escapeString(s).c_str());
        if (s.empty()) {
            // Likely an anchored case, be conservative here.
            return NO_MATCH_LIMIT;
        }

        for (auto v : vertices_range(h)) {
            if (is_special(v, h)) {
                continue;
            }

            if (couldEndLiteral(s, v, h)) {
                u32 idx = h[v].index;
                DEBUG_PRINTF("vertex %u could terminate lit\n", idx);
                terms.insert(idx);
            }
        }
    }

    if (terms.empty()) {
        DEBUG_PRINTF("literals cannot match inside infix\n");
        return 0;
    }

    NGHolder g;
    cloneHolder(g, h);
    vector<NFAVertex> dead;

    // The set of all edges in the graph is used for existence checks in contractVertex.
    ue2::unordered_set<pair<NFAVertex, NFAVertex>> all_edges;
    for (const auto &e : edges_range(g)) {
        all_edges.emplace(source(e, g), target(e, g));
    }

    for (auto v : vertices_range(g)) {
        if (is_special(v, g)) {
            continue;
        }
        if (contains(terms, g[v].index)) {
            continue;
        }

        contractVertex(g, v, all_edges);
        dead.push_back(v);
    }

    remove_vertices(dead, g);
    //dumpGraph("relaxed.dot", g.g);

    depth maxWidth = findMaxWidth(g);
    DEBUG_PRINTF("maxWidth=%s\n", maxWidth.str().c_str());
    assert(maxWidth.is_reachable());

    if (maxWidth.is_infinite()) {
        // Cycle detected, so we can likely squeeze an unlimited number of
        // matches into this graph.
        return NO_MATCH_LIMIT;
    }

    assert(terms.size() >= maxWidth);
    return maxWidth;
}