Ejemplo n.º 1
0
 void operator()(const size_t start, const size_t stop)
 {
   for (size_t i = start; i < stop; ++i)
   {
     accum_deg[i + 1] = in_degree(vlist[i], g);
   }
 }
Ejemplo n.º 2
0
static
void allowIllegal(NGHolder &g, NFAVertex v, u8 pred_char) {
    if (in_degree(v, g) != 1) {
        DEBUG_PRINTF("unexpected pred\n");
        assert(0); /* should be true due to the early stage of this analysis */
        return;
    }

    CharReach &cr = g[v].char_reach;
    if (pred_char == 0xe0) {
        assert(cr.isSubsetOf(CharReach(0xa0, 0xbf)));
        if (cr == CharReach(0xa0, 0xbf)) {
            cr |= CharReach(0x80, 0x9f);
        }
    } else if (pred_char == 0xf0) {
        assert(cr.isSubsetOf(CharReach(0x90, 0xbf)));
        if (cr == CharReach(0x90, 0xbf)) {
            cr |= CharReach(0x80, 0x8f);
        }
    } else if (pred_char == 0xf4) {
        assert(cr.isSubsetOf(CharReach(0x80, 0x8f)));
        if (cr == CharReach(0x80, 0x8f)) {
            cr |= CharReach(0x90, 0xbf);
        }
    } else {
        assert(0); /* unexpected pred */
    }
}
void prioritized_topological_sort(const Graph& g, Comp comp,
                                  UnaryFunction output_vertex) {
  const size_t num_vertices = g.num_vertices();
  const size_t num_edges = g.num_edges();
  std::priority_queue<size_t, std::vector<size_t>, Comp> queue(comp);
  std::vector<size_t> in_degree(num_vertices);

  for (size_t e = 0; e != num_edges; ++e)
    ++in_degree[g.target(e)];

  for (size_t v = 0; v != num_vertices; ++v)
    if (!in_degree[v])
      queue.push(v);

  while (!queue.empty()) {
    const size_t src = queue.top();
    queue.pop();
    output_vertex(src);

    for (const auto e : g.out_edges(src)) {
      const auto tgt = g.target(e);
      --in_degree[tgt];
      if (!in_degree[tgt])
        queue.push(tgt);
    }
  }
}
Ejemplo n.º 4
0
    bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {

        vector<int> in_degree(numCourses, 0);
        vector<vector<int> > out_node(numCourses, vector<int>());

        for (int i = 0; i < prerequisites.size(); ++i) {
            ++in_degree[prerequisites[i][0]];
            out_node[prerequisites[i][1]].push_back(prerequisites[i][0]);
        }
        
        queue<int> zero_in_degree_node;
        for (int i = 0; i < numCourses; ++i) {
            if (in_degree[i] == 0) {
                zero_in_degree_node.push(i);
            }
        }

        int fin_course_num = 0;
        while (!zero_in_degree_node.empty()) {
            int todo_course_num = zero_in_degree_node.size();
            while (todo_course_num--) {
                int course_index = zero_in_degree_node.front();
                zero_in_degree_node.pop();
                ++fin_course_num;

                for (int i = 0; i < out_node[course_index].size(); ++i) {
                    if (--in_degree[out_node[course_index][i]] == 0) {
                        zero_in_degree_node.push(out_node[course_index][i]);
                    }
                }
            }
        }

        return fin_course_num == numCourses;
    }
Ejemplo n.º 5
0
    void constraints() {
      function_requires< IncidenceGraphConcept<G> >();
      function_requires< MultiPassInputIteratorConcept<in_edge_iterator> >();

      p = in_edges(v, g);
      n = in_degree(v, g);
      e = *p.first;
      const_constraints(g);
    }
Ejemplo n.º 6
0
  void operator()(const size_t start, const size_t stop)
  {
    size_type start_pos = start;
    size_type end_pos = stop;

    thread_vertex_iterator tverts = thread_vertices(start_pos, g);
    for ( ; start_pos != end_pos; ++start_pos, ++tverts)
    {
      accum_deg[start_pos + 1] = in_degree(*tverts, g);
    }
  }
Ejemplo n.º 7
0
static
bool getTransientPrefixReach(const NGHolder &g, u32 lag,
                             map<s32, CharReach> &look) {
    if (in_degree(g.accept, g) != 1) {
        DEBUG_PRINTF("more than one accept\n");
        return false;
    }

    // Must be a floating chain wired to startDs.
    if (!hasSingleFloatingStart(g)) {
        DEBUG_PRINTF("not a single floating start\n");
        return false;
    }

    NFAVertex v = *(inv_adjacent_vertices(g.accept, g).first);
    u32 i = lag + 1;
    while (v != g.startDs) {
        DEBUG_PRINTF("i=%u, v=%u\n", i, g[v].index);
        if (is_special(v, g)) {
            DEBUG_PRINTF("special\n");
            return false;
        }

        look[0 - i] = g[v].char_reach;

        NFAVertex next = NGHolder::null_vertex();
        for (auto u : inv_adjacent_vertices_range(v, g)) {
            if (u == g.start) {
                continue; // Benign, checked by hasSingleFloatingStart
            }
            if (next == NGHolder::null_vertex()) {
                next = u;
                continue;
            }
            DEBUG_PRINTF("branch\n");
            return false;
        }

        if (next == NGHolder::null_vertex() || next == v) {
            DEBUG_PRINTF("no predecessor or only self-loop\n");
            // This graph is malformed -- all vertices in a graph that makes it
            // to this analysis should have predecessors.
            assert(0);
            return false;
        }

        v = next;
        i++;
    }

    DEBUG_PRINTF("done\n");
    return true;
}
Ejemplo n.º 8
0
    vector<int> findOrder(int numCourses, vector<pair<int, int>>& prerequisites) {
            vector<int> in_degree(numCourses, 0); //存储入度
			vector<unordered_set<int>> matrix(numCourses);//存储图
			vector<int> res;

			for (int i = 0; i < prerequisites.size(); i++)
			{
				matrix[prerequisites[i].second].insert(prerequisites[i].first);
			}
			//计算入度
			for (int i = 0; i < numCourses; i++)
			{
				for (auto it = matrix[i].begin(); it != matrix[i].end(); it++)
				{
					in_degree[*it]++;
				}
			}
			stack<int> zeor_degree_stack;//存储入度为0的节点
			int count = 0;//入度0的节点计数器
			for (int i = 0; i < numCourses; i++)
			{
				if (in_degree[i] == 0)
				{
					zeor_degree_stack.push(i);
					count++; //入度为0,计数加1
					res.push_back(i);
				}
			}
			//循环抽取入度为0的节点
			while (!zeor_degree_stack.empty())
			{
				int top = zeor_degree_stack.top();
				zeor_degree_stack.pop();
				for (auto it = matrix[top].begin(); it != matrix[top].end(); it++)
				{
					in_degree[*it]--;
					if (in_degree[*it] == 0)
					{
						zeor_degree_stack.push(*it);
						count++;
						res.push_back(*it);
					}
				}
			}
			if (count == numCourses)
				return res;
			else
			{
				vector<int> tmp; return tmp;
			}
    }
Ejemplo n.º 9
0
void AlnGraphBoost::mergeOutNodes(VtxDesc n) {
    std::map<char, std::vector<VtxDesc>> nodeGroups;     
    OutEdgeIter oi, oe;
    for(tie(oi, oe) = boost::out_edges(n, _g); oi != oe; ++oi) {
        VtxDesc outNode = boost::target(*oi, _g);
        if (in_degree(outNode, _g) == 1) {
            nodeGroups[_g[outNode].base].push_back(outNode);
        }
    }
    
    for(auto kvp = nodeGroups.cbegin(); kvp != nodeGroups.end(); ++kvp) {
        std::vector<VtxDesc> nodes = (*kvp).second;
        if (nodes.size() <= 1) 
            continue;

        std::vector<VtxDesc>::const_iterator ni = nodes.cbegin();
        VtxDesc an = *ni++;
        InEdgeIter anii, anie;
        tie(anii, anie) = boost::in_edges(an, _g);
        
        // Accumulate inner edge information
        for (; ni != nodes.cend(); ++ni) {
            InEdgeIter ii, ie;
            tie(ii, ie) = boost::in_edges(*ni, _g);
            _g[*anii].count += _g[*ii].count;    
            _g[an].weight += _g[*ni].weight;
        }

        // Accumulate and merge outer edge information
        ni = nodes.cbegin();
        ++ni;
        for (; ni != nodes.cend(); ++ni) {
            OutEdgeIter oi, oe;
            VtxDesc n = *ni;
            for (tie(oi, oe) = boost::out_edges(n, _g); oi != oe; ++oi) {
                VtxDesc n2 = boost::target(*oi, _g);
                EdgeDesc e;
                bool exists;
                tie(e, exists) = edge(an, n2, _g);
                if (exists) {
                    _g[e].count += _g[*oi].count;
                } else {
                    std::pair<EdgeDesc, bool> p = boost::add_edge(an, n2, _g);
                    _g[p.first].count = _g[*oi].count;
                    _g[p.first].visited = _g[*oi].visited;
                }
            }
            markForReaper(n);
        }
    }
}
Ejemplo n.º 10
0
void test_in_out_edges(const G& g) 
{
  typedef boost::graph_traits< G > Traits;
  typedef typename Traits::vertex_iterator vertex_iterator;
  typedef typename Traits::in_edge_iterator in_edge_iterator;
  typedef typename Traits::out_edge_iterator out_edge_iterator;
  typedef typename Traits::vertex_descriptor vertex_descriptor;

  // check that the sets of in out edges are the same
  vertex_iterator vb, ve;
  for(boost::tie(vb, ve) = vertices(g); vb != ve; ++vb) {
    id_map v_ids;
    std::vector<vertex_descriptor> in, out;
    in_edge_iterator ieb, iee;
    for(boost::tie(ieb, iee) = in_edges(*vb, g); ieb != iee; ++ieb) {
      std::pair<id_map::iterator, bool> r =
        v_ids.insert(get(boost::vertex_index, g, source(*ieb, g)));
      assert(r.second);
      in.push_back(source(*ieb, g));
    }
    out_edge_iterator oeb, oee;
    for(boost::tie(oeb, oee) = out_edges(*vb, g); oeb != oee; ++oeb) {
      std::pair<id_map::iterator, bool> r =
        v_ids.insert(get(boost::vertex_index, g, target(*oeb, g)));
      // insertion must fail
      assert(!r.second);
      out.push_back(target(*oeb, g));
    }
    // did we walk the vertices in the same order?
    assert(in.size() == out.size());
    assert(std::equal(in.begin(), in.end(), out.begin()));
    assert(in.size() == in_degree(*vb, g));
    assert(out.size() == out_degree(*vb, g));
    assert(in.size() == degree(*vb, g));
    assert(degree(*vb, g) == in_degree(*vb, g));
    assert(degree(*vb, g) == out_degree(*vb, g));
  }
}
Ejemplo n.º 11
0
    static void apply(TaskSystemType& task_system) {

        typedef typename TaskSystemType::GraphType GraphType;
        typedef typename TaskSystemType::ClusterType ClusterType;
        typedef typename TaskSystemType::ClusterIdType ClusterIdType;
        typedef typename TaskSystemType::vertex_iterator vertex_iterator;
        typedef typename TaskSystemType::adjacency_iterator adjacency_iterator;

        GraphType& sys_graph = task_system.sys_graph;

        vertex_iterator vert_iter, vert_end;
        boost::tie(vert_iter, vert_end) = vertices(sys_graph);
        /*! skip the root node. */
        ++vert_iter;
        for ( ; vert_iter != vert_end; ++vert_iter) {
            const ClusterIdType& curr_clust_id = *vert_iter;
            ClusterType& curr_clust = sys_graph[curr_clust_id];

            if(!curr_clust.is_valid()) {
                continue;
            }

            adjacency_iterator child_iter, child_end, curr_child_iter;
            boost::tie(child_iter, child_end) = adjacent_vertices(curr_clust_id, sys_graph);
            while (child_iter != child_end) {
				/*! Increment before concat. Apparently erasing an edge invalidates the vertex iterators in VS.
				  something is going on inside boost that I don't know yet. Or VS is just being VS as ususal.
				  (the edge container is in fact a set, but that should matter only if we iterate over ages.
				  well apparently not :) )*/
				curr_child_iter = child_iter;
				++child_iter;

                const ClusterIdType& curr_child_id = *curr_child_iter;
                // ClusterType& curr_child = sys_graph[curr_child_id];

                int nr_parents = in_degree(curr_child_id, sys_graph);
                if(nr_parents == 1) {
                    task_system.concat_with_parent(curr_clust_id, curr_child_id);
                }
            }

        }

        task_system.levels_valid = false;

    }
Ejemplo n.º 12
0
bool AlnGraphBoost::danglingNodes() {
    VtxIter curr, last;
    boost::tie(curr, last) = boost::vertices(_g);
    bool found = false;
    for (; curr != last; ++curr) {
        if (_g[*curr].deleted)
            continue;
        if (_g[*curr].base == _g[_enterVtx].base || _g[*curr].base == _g[_exitVtx].base)
            continue;

        int indeg = out_degree(*curr, _g);
        int outdeg = in_degree(*curr, _g);
        if (outdeg > 0 && indeg > 0) continue;

        found = true;
    }
    return found;
}
Ejemplo n.º 13
0
bool SingleChildMerge::apply(VertexID v)
{
  ChildrenIterator c,c_end;
  bool change = false;
  if (out_degree(v,*m_taskgraph) == 1) {
    // tie(e,e_end) = out_edges(v,*m_taskgraph);
    tie(c,c_end) = children(v,*m_taskgraph);
    if (in_degree(*c,*m_taskgraph) == 1) {
      //cerr << "SingleChildMerge, parent: " << getTaskID(v,m_taskgraph)
      //   << " child: " << getTaskID(*c,m_taskgraph) << endl;
      mergeTasks(v,*c);
      //cerr << "parent now contains: " ;
      //printContainTasks(v,cerr);
      //cerr << endl;
      change=true;
    }
  }
  return change;
}
Ejemplo n.º 14
0
bool MergeAllParents::apply(VertexID v)
{
  bool change = false;
  if (v != m_invartask && v != m_outvartask) {
    set<VertexID> A, B;
    if (in_degree(v,*m_taskgraph) > 1 &&

      tlevel(v) > maxTlevel(parents(v,*m_taskgraph))
               + totalExecCost(parents(v,*m_taskgraph),v)
      /* &&
         calculateAB(parents(v,*m_taskgraph),v,A,B) > 0  */
      ) {
    calculateAB(parents(v,*m_taskgraph),v,A,B);
    // Do the merge
    //cerr << "MergeAllParents, child: "<< getTaskID(v,m_taskgraph) << " (";
    //printContainTasks(v,cerr);
    //cerr << ")" << endl;
    //cerr << "parents :" ;
    //ParentsIterator p,p_end;
    //for (tie(p,p_end)=parents(v,*m_taskgraph); p != p_end; p++) {
    // cerr << getTaskID(*p,m_taskgraph) << "(" ;
    // printContainTasks(*p,cerr);
    // cerr << ")  " ;
    //  }
    //cerr << endl;
    // cerr << "siblings (A: " ;
    //printVertexSet(A,cerr);
    //cerr << endl << "A complement: " ;
    //printVertexSet(B,cerr);
    //cerr << endl;

    mergeAll(parents(v,*m_taskgraph),v,A,B);
    //cerr << "parent now contains: " ;
    //printContainTasks(v,cerr);
    //cerr << endl;
    change=true;
  }
  }
  return change;
}
Ejemplo n.º 15
0
int main()
{
	int i,j,k;
	char str[10];
	bool f;
	while (scanf("%d%d",&n,&m),n!=0 || m!=0)
	{
		memset(letter,false,sizeof(letter));
		f=false;
		for (i=1;i<=m;i++)
		{
			scanf("%s",str);
			if (f==true)
				continue;
			letter[str[0]-'A'][str[2]-'A']=true;
			memset(top,false,sizeof(top));
			sorted=false;
			for (j=0;j<n;j++)
			{
				if ((k=in_degree())==-1)
				{
					printf("Inconsistency found after %d relations.\n",i);
					f=true;
					break;
				}
				top[k]=true;
				sort[j]=k+'A';
			}
			if (j==n && sorted==false)
			{
				sort[n]='\0';
				printf("Sorted sequence determined after %d relations: %s.\n",i,sort);
				f=true;
			}
		}
		if (f==false)
			printf("Sorted sequence cannot be determined.\n");
	}
	return 0;
}
Ejemplo n.º 16
0
 vector<int> findMinHeightTrees(int n, vector<pair<int, int>>& edges) {
     if (n == 1) {
         return {0};
     }
     vector<int> result;
     vector<vector<int>> graph(n, vector<int>());
     vector<int> in_degree(n, 0);
     queue<int> q;
     for (auto edge : edges) {
         graph[edge.first].push_back(edge.second);
         in_degree[edge.first]++;
         graph[edge.second].push_back(edge.first);
         in_degree[edge.second]++;
     }
     for (int i = 0; i < n; i++) {
         if (in_degree[i] == 1) {
             q.push(i);
         }
     }
     while (n > 2) {
         int q_size = static_cast<int>(q.size());
         for (int i = 0; i < q_size; i++) {
             int cur_v = q.front();
             q.pop();
             n--;
             for (int i : graph[cur_v]) {
                 in_degree[i]--;
                 if (in_degree[i] == 1) {
                     q.push(i);
                 }
             }
         }
     }
     while (q.empty() == false) {
         result.push_back(q.front());
         q.pop();
     }
     return result;
 }
Ejemplo n.º 17
0
/** Cheaply check whether this graph can't be reduced at all, because it is
 * just a chain of vertices with no other edges. */
static
bool isIrreducible(const NGHolder &g) {
    for (auto v : vertices_range(g)) {
        // skip specials
        if (is_special(v, g)) {
            continue;
        }

        // we want meaningful in_degree to be 1. we also want to make sure we
        // don't count self-loop + 1 incoming edge as not irreducible
        if (in_degree(v, g) != 1 && !inIsIrreducible(v, g)) {
            return false;
        }
        // we want meaningful out_degree to be 1. we also want to make sure we
        // don't count self-loop + 1 outgoing edge as not irreducible
        if (out_degree(v, g) != 1 && !outIsIrreducible(v, g)) {
            return false;
        }
    }

    return true;
}
Ejemplo n.º 18
0
flat_set<NFAVertex> execute_graph(const NGHolder &running_g,
                                  const NGHolder &input_dag,
                                  const flat_set<NFAVertex> &input_start_states,
                                  const flat_set<NFAVertex> &initial_states) {
    DEBUG_PRINTF("g has %zu vertices, input_dag has %zu vertices\n",
                 num_vertices(running_g), num_vertices(input_dag));
    assert(hasCorrectlyNumberedVertices(running_g));
    assert(in_degree(input_dag.acceptEod, input_dag) == 1);

    map<NFAVertex, boost::default_color_type> colours;
    /* could just a topo order, but really it is time to pull a slightly bigger
     * gun: DFS */
    RevNFAGraph revg(input_dag.g);
    map<NFAVertex, dynamic_bitset<> > dfs_states;

    auto info = makeInfoTable(running_g);
    auto input_fs = makeStateBitset(running_g, initial_states);

    for (auto v : input_start_states) {
        dfs_states[v] = input_fs;
    }

    depth_first_visit(revg, input_dag.accept,
                      eg_visitor(running_g, info, input_dag, dfs_states),
                      make_assoc_property_map(colours));

    auto states = getVertices(dfs_states[input_dag.accept], info);

#ifdef DEBUG
    DEBUG_PRINTF("  output rstates:");
    for (const auto &v : states) {
        printf(" %u", running_g[v].index);
    }
    printf("\n");
#endif

    return states;
}
Ejemplo n.º 19
0
inline
void accumulate_in_degree(T* accum_deg, Graph& g)
{
  #pragma mta noalias *accum_deg
  #pragma mta noalias g

  typedef typename graph_traits<Graph>::size_type size_type;
  typedef typename graph_traits<Graph>::thread_vertex_iterator
          thread_vertex_iterator;

  size_type order = num_vertices(g);

  accum_deg[0] = 0;

#ifdef USING_QTHREADS
  detail::qt_accum_in_deg<Graph, T> qaid(g, accum_deg);
  qt_loop_balance(0, order, qaid);
#else
  size_type stream_id = 0;
  size_type num_streams = 1;

  #pragma mta assert nodep
  #pragma mta for all streams stream_id of num_streams
  {
    size_type start_pos = begin_block_range(order, stream_id, num_streams);
    size_type end_pos = end_block_range(order, stream_id, num_streams);

    thread_vertex_iterator tverts = thread_vertices(start_pos, g);
    for ( ; start_pos != end_pos; ++start_pos, ++tverts)
    {
      accum_deg[start_pos + 1] = in_degree(*tverts, g);
    }
  }
#endif

  for (size_type i = 1; i <= order; ++i) accum_deg[i] += accum_deg[i - 1];
}
Ejemplo n.º 20
0
bool AlnGraphBoost::danglingNodes() {
    log4cpp::Category& logger = 
        log4cpp::Category::getInstance("AlnGraph");
    boost::format msg("Found dangling node. No %s edges: %d");
    VtxIter curr, last;
    tie(curr, last) = boost::vertices(_g);
    bool found = false;
    for (;curr != last; ++curr) {
        if (_g[*curr].deleted)
            continue;
        if (_g[*curr].base == _g[_enterVtx].base || _g[*curr].base == _g[_exitVtx].base) 
            continue;

        int indeg = out_degree(*curr, _g); 
        int outdeg = in_degree(*curr, _g); 
        if (outdeg > 0 && indeg > 0) continue;

        msg % (outdeg == 0 ? "outgoing" : "incoming");
        msg % *curr;
        logger.errorStream() << msg.str();
        found = true;
    }
    return found;
}
Ejemplo n.º 21
0
inline
void
accumulate_in_degree(T* accum_deg,
                     typename graph_traits<Graph>::vertex_descriptor* vlist,
                     T2 vlist_size, Graph& g)
{
  #pragma mta noalias *accum_deg
  #pragma mta noalias *vlist
  #pragma mta noalias g

  accum_deg[0] = 0;

#ifdef USING_QTHREADS
  detail::qt_accum_in_deg_list<Graph, T> qaidl(g, accum_deg, vlist);
  qt_loop_balance(0, vlist_size, qaidl);
#else
  for (T2 i = 0; i < vlist_size; ++i)
  {
    accum_deg[i + 1] = in_degree(vlist[i], g);
  }
#endif

  for (T2 i = 1; i <= vlist_size; ++i) accum_deg[i] += accum_deg[i - 1];
}
Ejemplo n.º 22
0
uint32_t BBSISPOptimizerWCP::generateOptimalILPFormulationForSequentialCode(CFGVertex start, CFGVertex end, uint32_t running_id, vector<CFGEdge>& leavingEdges)
{
	vector<CFGVertex> processing;
	vector<CFGVertex> processed;

	processing.push_back(start);

	cfgOutEdgeIter ep;

	LOG_DEBUG(logger, "Processing from: " << start  << " [" << get(startAddrStringNProp, start) << "]" << " to " << end << " [" << get(startAddrStringNProp, end) << "]" << ".");

	while(processing.size() != 0)
	{
		if(logger->isDebugEnabled())
		{
			ostringstream s;
			for(uint32_t i = 0; i < processing.size(); i++)
			{
				s << "(" << processing[i] << ")";
			}
			LOG_DEBUG(logger, "Size of processing list: " << processing.size() << " contains:" << s.str());
		}

		CFGVertex actual_cfg = processing.back();
		processing.pop_back();

		LOG_DEBUG(logger, "Processing " << actual_cfg << " " << get(startAddrStringNProp, actual_cfg));

		// ensure that each node is only handled once.
		bool node_already_processed = false;
		for(uint32_t j = 0; j<processed.size(); j++)
		{
			if(actual_cfg == processed[j])
			{
				node_already_processed = true;
			}
		}
		if(!node_already_processed)
		{
			if(actual_cfg != end)
			{
				if(get(nodeTypeNProp, actual_cfg) == CallPoint)
				{
					// create virtual node for function
					CFGVertex v;
					uint32_t function_id = running_id;
					CFGVertex cfg_return_point = actual_cfg; // to temporally initialize the vertex
					cfgVertexIter vp;
					bool found_return = false;
					// find the right return point for the call point
					uint32_t context_addr = get(endAddrNProp, actual_cfg);
					for (vp = vertices(cfg); (vp.first != vp.second)&&(!found_return); ++vp.first)
					{
						v = *vp.first;
						if((get(nodeTypeNProp, v) == ReturnPoint) && (context_addr == get(endAddrNProp, v)))
						{
							found_return = true;
							cfg_return_point = v;
						}
					}
					assert(found_return);


					stringstream cfg_ilp;

					assert(out_degree(actual_cfg, cfg) == 1);
					cfgOutEdgeIter eop = out_edges(actual_cfg, cfg);
					CFGVertex function_entry_cfg = target(*eop.first, cfg);
					assert(in_degree(cfg_return_point, cfg) == 1);
					cfgInEdgeIter eip = in_edges(cfg_return_point, cfg);
					CFGVertex function_exit_cfg = source(*eip.first, cfg);

					FunctionMap::iterator pos = functionMap.find(function_entry_cfg);

					if(pos == functionMap.end())
					{
						vector<CFGEdge> function_leaving_edges;
						// create ilp for the function body
						running_id = generateOptimalILPFormulationForSequentialCode(function_entry_cfg, function_exit_cfg, ++running_id, function_leaving_edges);
						LOG_DEBUG(logger, "Returned from function to processing from: " << start << " to " << end << ".");
						assert(function_leaving_edges.empty());
						
						FunctionMap::iterator ins_pos;
						bool ins_bool;
						tie(ins_pos, ins_bool) = functionMap.insert(make_pair(function_entry_cfg, function_id));
						assert(ins_bool);
						// create cost for the function with function_id
						cfg_ilp << "cf" << function_id << " = " << " w" << function_entry_cfg  << ";" << endl;

					}
					else
					{
						function_id = pos->second;
					}
					// connect call point with virtual function node wfXctxY
					cfg_ilp << "w" << actual_cfg << " >= wf" << function_id << "c" << hex << context_addr << dec << getPenaltyForFunctionEntering(actual_cfg, function_entry_cfg) << ";" << endl;
					// connect virtual function node with return point, and taking cost of function into account
					// NOTICE the cost of the function exit node (which is an Exit node) to the node to which it is returned (which is an ReturnPoint node) does not need to be considered, because it is free of cost.
					cfg_ilp << "wf" << function_id << "c" << hex << context_addr << dec <<  " >= w" << cfg_return_point << " + cf" << function_id << getPenaltyForFunctionExit(cfg_return_point, function_exit_cfg) << ";" << endl;

					cfg_ilps.push_back(cfg_ilp.str());
					processing.push_back(cfg_return_point);

				}
				else
				{
					for(ep = out_edges(actual_cfg, cfg); ep.first != ep.second; ++ep.first) 
					{
						bool found_loop_head = false;
						uint32_t loop_id = running_id;
						vector<CFGVertex> loop_exits;
						vector<CFGEdge> irregular_loop_exit_edges;
						CFGEdge eo = *ep.first;
						CFGEdge back_edge;
						CFGVertex target_cfg = target(eo, cfg);

						edge_type_t etype = get(edgeTypeEProp, eo);
						if((etype == ForwardStep) || (etype == ForwardJump) || (etype == Meta))
						{

							LOG_DEBUG(logger, "Checking out-edges From: " << actual_cfg << " " << get(startAddrStringNProp, actual_cfg) << " To: " << target_cfg << " " << get(startAddrStringNProp, target_cfg) << " Type: " << etype << " Edge " << eo);

							LoopDataMap::iterator pos = loopMap.find(target_cfg);
							if(pos != loopMap.end())
							{
								if((target_cfg != start) &&  (pos->second.exitNode != end))
								{
									LOG_DEBUG(logger, "Target of out edge " <<  eo << ". " << target_cfg << " is a loop head. Backedge is: " <<  pos->second.backEdge << " exit node is: " <<  pos->second.exitNode);

									loop_exits.push_back(pos->second.exitNode);
									found_loop_head = true;

									stringstream cfg_ilp;
									int32_t loop_bound = getLoopBoundForLoopHead(target_cfg, pos->second.backEdge);
									cfg_ilp << "cl" << loop_id << " = " << loop_bound+1 /* the value from the flow facts determines the number of invocations of the back_edge, i.e. the number of times the loop is entered  */ << " w" << pos->second.startNode;
									if(get(nodeTypeNProp, pos->second.exitNode) == BasicBlock)
									{
										// charge the cost of the loop conserving edge, i.e. of the bottom node of the loop body
										// The cost of this basic block for the loop exiting edge is charged, on connection of the virtual loop node with the code after the loop (see calculation of wlXX and the usage of the variable loop_exits).
										if(!conf->getBool(CONF_BBSISP_WCP_SHRINK_ILP_FORMULATION))
										{
											cfg_ilp << " + " << loop_bound << " ce" << source(pos->second.backEdge,cfg) << "t" << target(pos->second.backEdge, cfg);
										}
										else // conf->getBool(CONF_BBSISP_WCP_SHRINK_ILP_FORMULATION)
										{
											cfg_ilp << " + " << getEdgeCostConstraint(pos->second.backEdge, loop_bound);
										}
									}
									else
									{
										assert(false); // could there be a loop with a non basic block node at the end??
									}

									cfg_ilp << ";" << endl;
									cfg_ilps.push_back(cfg_ilp.str());

									// create ilp for the loop body
									running_id = generateOptimalILPFormulationForSequentialCode(pos->second.startNode, pos->second.exitNode, ++running_id, irregular_loop_exit_edges);
									LOG_DEBUG(logger, "Returned loop to processing from: " << start << " to " << end << ".");
								}
							}

							stringstream cfg_ilp;

							if(!found_loop_head)
							{
								bool is_on_path = isNodeOnPath(target_cfg, start, end, false);
								LOG_DEBUG(logger, "Successor of actual node " << actual_cfg << " " << get(startAddrStringNProp, actual_cfg) << " (edge: " << eo << ") is no loop head. The node is " << ((!is_on_path)?("not "):("")) << "within the sequential code part");
								cfg_ilp << "w" << actual_cfg << " >= ";
								if(is_on_path)
								{
									cfg_ilp << "w" << target_cfg;
								}
								if(get(nodeTypeNProp, actual_cfg) == BasicBlock)
								{
									if(is_on_path)
									{
										cfg_ilp << " + ";
									}

									if(!conf->getBool(CONF_BBSISP_WCP_SHRINK_ILP_FORMULATION))
									{
										cfg_ilp << "ce" << source(eo,cfg) << "t" << target(eo, cfg);
									}
									else // conf->getBool(CONF_BBSISP_WCP_SHRINK_ILP_FORMULATION)
									{
										cfg_ilp << getEdgeCostConstraint(eo);
									}
								}


								cfg_ilp << ";" << endl;

								cfg_ilps.push_back(cfg_ilp.str());
								
								// checking if target node is within loop body
								if(is_on_path)
								{
									LOG_DEBUG(logger, "Pushing " << target_cfg << " " << get(startAddrStringNProp, target_cfg) << " to process list");
									processing.push_back(target_cfg);
								}
								else
								{
									LOG_DEBUG(logger, "Node " << target_cfg << " " << get(startAddrStringNProp, target_cfg) << " is not within currently processing code part (function or loop body), cannot add to process list.");
									leavingEdges.push_back(eo);
								}

							}
							else
							{
								LOG_DEBUG(logger, "Successor of actual node " << actual_cfg << " " << get(startAddrStringNProp, actual_cfg) << " (edge: " << eo << ") is loop head");
								cfg_ilp << "w" << actual_cfg << " >= wl" << loop_id;
								if(get(nodeTypeNProp, actual_cfg) == BasicBlock)
								{
									if(!conf->getBool(CONF_BBSISP_WCP_SHRINK_ILP_FORMULATION))
									{
										cfg_ilp << " + ce" << source(eo,cfg) << "t" << target(eo, cfg);
									}
									else // conf->getBool(CONF_BBSISP_WCP_SHRINK_ILP_FORMULATION)
									{
										cfg_ilp << " + " << getEdgeCostConstraint(eo);
									}
								}
								cfg_ilp << ";" <<  endl;
								cfg_ilps.push_back(cfg_ilp.str());

								for(uint32_t i = 0; i < loop_exits.size(); i++)
								{
									LOG_DEBUG(logger, "Loop exit nodes are: " << loop_exits[i]);
									for(cfgOutEdgeIter ep2 = out_edges(loop_exits[i], cfg); ep2.first != ep2.second; ++ep2.first) 
									{
										CFGEdge el = *ep2.first;
										CFGVertex post_loop_node = target(el, cfg);

										edge_type_t etype = get(edgeTypeEProp, el);
										if((etype == ForwardStep) || (etype == ForwardJump) || (etype == Meta))
										{
											stringstream tmp;
											// the wcet of the loop is the wcet of the following node + the cost of the loop + the cost of the loop out edge

											if(!conf->getBool(CONF_BBSISP_WCP_SHRINK_ILP_FORMULATION))
											{
												tmp << "wl" << loop_id << " >= w" << post_loop_node <<  " + cl" << loop_id << " + ce" << source(el,cfg) << "t" << target(el, cfg) << ";" << endl;
											}
											else // conf->getBool(CONF_BBSISP_WCP_SHRINK_ILP_FORMULATION)
											{
												tmp << "wl" << loop_id << " >= w" << post_loop_node <<  " + cl" << loop_id << " + " << getEdgeCostConstraint(el) << ";" << endl;
											}

											cfg_ilps.push_back(tmp.str());

											// checking if target node is within loop body
											if(isNodeOnPath(target_cfg, start, end, false))
											{
												LOG_DEBUG(logger, "Pushing post loop node " << post_loop_node << " " << get(startAddrStringNProp, post_loop_node) << " to process list");
												processing.push_back(post_loop_node);
											}
											else
											{
												LOG_DEBUG(logger, "Post loop node " << target_cfg << " " << get(startAddrStringNProp, target_cfg) << " is not on path, cannot add to process list.");
												leavingEdges.push_back(eo);
												assert(false);
											}
										}
									}

								}
								for(uint32_t i = 0; i < irregular_loop_exit_edges.size(); i++)
								{
									CFGEdge e = irregular_loop_exit_edges[i];
									LOG_DEBUG(logger, "Irregular loop exit edge: " << e);
									// checking if the target of the loop leaving edge can be found whithin the currently activw loop body
									if(isNodeOnPath(target(e, cfg), start, end, false))
									{

										stringstream tmp;
										// If a loop is unexpectively left by an edge e, the target of e may be reached by the loop body (in the worst case at the end of the loop, since the structure of the loop is hidden by the cost of the loop (clXX).
										// The cost of the irregular loop exit edge does not need to be charged here, because it is implicitely already in the cost of the loop (which is maximizes over all possible paths, including the dead end of an irregular leaving edge.
										tmp << "wl" << loop_id << " >= w" << target(e, cfg) <<  " + cl" << loop_id << ";" << endl; 
										cfg_ilps.push_back(tmp.str());
									}
									else
									{
										// The irregular loop leaving edge leaves multiple levels of loop nests. Delegate handling to next loop level.
										leavingEdges.push_back(e);
										assert(false);
									}
								}


							}

						}
					}
				}
			}
			else
			{
				LOG_DEBUG(logger, "Found end node");

				stringstream cfg_ilp;

				// The cost of the loop conserving edge (the bottom basic block) is charged in the loop cost variable: clXX = loop_bound+1 * wLoopHead + ceLoopConservingEdgeXX
				// This is because the loop body is ececuted loop_bound+1, whereas the cost of the loop conserving edge needs to be taken only loop_bound times into account, because the last iteration of the loop uses another edge, which is charged in wlXX >= wYY + clXX + ceExitEdgeOfLoopXX
				cfg_ilp << "w" << actual_cfg << " = 0;" << endl;

				cfg_ilps.push_back(cfg_ilp.str());
			}
			processed.push_back(actual_cfg);
		}
	}
	return running_id;

}
Ejemplo n.º 23
0
void LRACC::LRACC_dual()
{
///*
 	//float stepsize = 0.00025*(1-iter_lagrangian+MAX_LAGRANGIAN_NUM);
  float stepsize = 0.001;
  cout<<"#"<<iter_lagrangian<< "\t LRACC_DUAL parameters"<< endl;
	for(TPLGY_EITER eiter = edges(circuit).first;eiter!=edges(circuit).second;eiter++)
	{
		TPLGY_VDES src = source(*eiter,circuit);
		TPLGY_VDES tgt = target(*eiter,circuit);
		float ai,aj,di;
		if ((circuit[src].info->type == IN1) || (circuit[src].info->type == FFMS&&in_degree(src, circuit) == 0)){
			aj = 0;
		}
		else{
			aj = mu_sigma[circuit[src].info->name].first;
		}
		if ((circuit[tgt].info->type == OUT1) || (circuit[tgt].info->type == FFMS&&out_degree(tgt, circuit) == 0))
		{
			ai = Time_Limit;
			di = 0;
		}
		else
		{
			ai = mu_sigma[circuit[tgt].info->name].first;
			di = gate_sizes[circuit[tgt].info->name][1]*gate_sizes[circuit[tgt].info->name][2];
		}
		circuit[*eiter].lm+=stepsize*(aj+di-ai);
		//cout<<"new lm = "<<circuit[*eiter].lm<<std::endl;
		if(circuit[*eiter].lm<0)
			circuit[*eiter].lm = 0;
	}
	//project to KKT condition space
	for (VDES_CONTAINER::iterator ii = order.begin(); ii != order.end(); ++ii)
  {
		if(circuit[*ii].info->type==OUT1) continue;
		if(circuit[*ii].info->type==FFMS&&out_degree(*ii,circuit)==0) continue;
		float out_lm = 0;
		for(TPLGY_OEITER oeiter = out_edges(*ii,circuit).first;oeiter!=out_edges(*ii,circuit).second;oeiter++)
		{
			out_lm+=circuit[*oeiter].lm;
		}
		circuit[*ii].lm = out_lm;
		float in_lm = 0;
		for(TPLGY_IEITER ieiter = in_edges(*ii,circuit).first;ieiter!=in_edges(*ii,circuit).second;ieiter++)
		{
			in_lm+=circuit[*ieiter].lm;
		}
		if(in_lm==0) continue;
		for(TPLGY_IEITER ieiter = in_edges(*ii,circuit).first;ieiter!=in_edges(*ii,circuit).second;ieiter++)
		{
			circuit[*ieiter].lm*=out_lm/in_lm;
		}
	}
	float tmp = (total_a-Area_Limit)/Area_Limit; 
	//if(tmp>0.01) tmp = (1*tmp);
	//else if(tmp<0.01&&tmp>0) tmp = 0.01*1;
	//lm_a += stepsize*tmp;
  //if (lm_a < 0)
  {
  	lm_a = 0;
  }
	cout<<"Area_lm ="<<lm_a<<endl<<endl;
	//*/
	//float stepsize = 0.002*(1-iter_lagrangian+MAX_LAGRANGIAN_NUM);
 	/*float stepsize = 0.02;
  cout<<"#"<<iter_lagrangian<< "\t LRACC_DUAL parameters"<< endl;
	//update lm based on this hyperplane
	for (VDES_CONTAINER::iterator ii = order.begin(); ii != order.end(); ++ii)
  {
		TPLGY_VDES fgate = *ii;
    if (BIT_TEST(circuit[fgate].info->flag, OUTPUT_LOAD))
    {
    	continue;//skip the OUTPUT gate
    }
   	if (BIT_TEST(circuit[fgate].info->flag, INPUT_DRIVER))
    {
    	circuit[fgate].lm = 0;///???????????? just for simplicity
      continue;
    } 
 		string nm = (circuit[fgate].info)->name;
		//cout<<nm<<": "<<circuit[fgate].lm;
		float tmp = -arrival_time_slack[nm].second/Time_Limit;
		if(tmp>=0.01) tmp = (15*tmp);
		else if(tmp<0.01&&tmp>0) tmp = 15*0.01;
		tmp*=gate_sizes[circuit[fgate].info->name][1]*gate_sizes[circuit[fgate].info->name][2];
		circuit[fgate].lm += stepsize*tmp;
    if (circuit[fgate].lm <= 0)
    {
    	circuit[fgate].lm = 0;
    }
		//cout<<" -> lm="<<circuit[fgate].lm<<endl;//the Lagrangian value after calculate
  }
	float tmp = (total_a-Area_Limit)/Area_Limit; 
	//if(tmp>0.01) tmp = (1*tmp);
	//else if(tmp<0.01&&tmp>0) tmp = 0.01*1;
	//lm_a += stepsize*tmp;
  //if (lm_a < 0)
  {
  	lm_a = 0;
  }
	cout<<"Area_lm ="<<lm_a<<endl<<endl;//*/


	/*
	//update history based on last iteration
	dual_hist_obj.push_back(total_p);
	dual_hist_subg.push_back(make_pair(total_a-Area_Limit,arrival_time_slack));	
	//find the supporting hyperplane(this hyperplane will correspond to a history)
	vector<float> min(dual_hist_obj.size(),0);
	for(int i=0;i<dual_hist_obj.size();i++)
	{
		for (VDES_CONTAINER::iterator ii = order.begin(); ii != order.end(); ++ii)
    {
        fgate = *ii;
        if (BIT_TEST(circuit[fgate].info->flag, OUTPUT_LOAD||INPUT_DRIVER))
        {
            continue;//skip the OUTPUT gate
        }
    	  string nm = (circuit[fgate].info)->name;
        min[i] -= ((dual_hist_subg[i].second)[nm].second)*circuit[fgate].lm;
		}
		min[i] += (dual_hist_obj[i]);
		min[i] += (dual_hist_subg[i].first)*lm_a;
	}
	int idx = distance(min.begin(),min_element(min.begin(),min.end()));
	//update lm based on this hyperplane
	for (VDES_CONTAINER::iterator ii = order.begin(); ii != order.end(); ++ii)
  {
		fgate = *ii;
    if (BIT_TEST(circuit[fgate].info->flag, OUTPUT_LOAD))
    {
    	continue;//skip the OUTPUT gate
    }
   	if (BIT_TEST(circuit[fgate].info->flag, INPUT_DRIVER))
    {
    	circuit[fgate].lm = 0;///???????????? just for simplicity
      continue;
    } 
	
 		string nm = (circuit[fgate].info)->name;
		float tmp = -(dual_hist_subg.back().second)[nm].second*(dual_hist_subg.back().second)[nm].first/Time_Limit;
		if(tmp>=0.01) tmp = (30*tmp);
		else if(tmp<0.01&&tmp>0) tmp = 30*0.01;
		circuit[fgate].lm += stepsize*tmp;
    if (circuit[fgate].lm <= 0)
    {
    	circuit[fgate].lm = 0;
    }
		else cout<<nm<<" -> lm="<<circuit[fgate].lm<<endl;//the Lagrangian value after calculate
  }
	float tmp = (dual_hist_subg.back().first)/Area_Limit; 
	if(tmp>0.01) tmp = (20*tmp);
	else if(tmp<0.01&&tmp>0) tmp = 20*0.05;
	lm_a += stepsize*tmp;
  if (lm_a < 0)
  {
  	lm_a = 0;
  }
	cout<<"Area_lm ="<<lm_a<<endl<<endl;//*/
}
Ejemplo n.º 24
0
    static void apply(TaskSystemType& task_system) {

        typedef typename TaskSystemType::GraphType GraphType;
        typedef typename TaskSystemType::ClusterLevels ClusterLevels;
        typedef typename TaskSystemType::ClusterType ClusterType;
        typedef typename TaskSystemType::ClusterIdType ClusterIdType;
        typedef typename TaskSystemType::inv_adjacency_iterator inv_adjacency_iterator;
        typedef typename ClusterLevels::value_type SameLevelClusterIdsType;

        GraphType& sys_graph = task_system.sys_graph;
        ClusterLevels& clusters_by_level = task_system.clusters_by_level;


        if(task_system.levels_valid == false)
            task_system.update_node_levels();


        typename ClusterLevels::iterator level_iter = clusters_by_level.begin();
        /*! Skip the first level. Which contains only the root node and some invlaidated clusters.*/
        ++level_iter;
        /*! Skip the second level as well. All nodes here have root as parent.*/
        ++level_iter;

        int level_number = 2;
        for( ;level_iter != clusters_by_level.end(); ++level_iter, ++level_number) {
            SameLevelClusterIdsType& current_level = *level_iter;

            typename SameLevelClusterIdsType::iterator clustid_iter = current_level.begin();
            for( ;clustid_iter != current_level.end(); ++clustid_iter) {
                ClusterIdType& curr_clust_id = *clustid_iter;
                ClusterType& curr_clust = sys_graph[curr_clust_id];

                if(!curr_clust.is_valid()) {
                    continue;
                }

                if(in_degree(curr_clust_id, sys_graph) == 1) {
                    continue;
                }

                std::vector<ClusterIdType> parent_ids;
                inv_adjacency_iterator parent_iter, parent_end;
                boost::tie(parent_iter, parent_end) = inv_adjacent_vertices(curr_clust_id, sys_graph);
                const ClusterIdType& main_parent_id = *parent_iter;
                ClusterType& main_parent = sys_graph[main_parent_id];

                /*! start from the second parent.*/
                parent_iter++;
                for ( ; parent_iter != parent_end; ++parent_iter) {
                    const ClusterIdType& other_parent_id = *parent_iter;
                    ClusterType& other_parent = sys_graph[other_parent_id];
                    /*! Don't merge different level parents for now.*/
                    if(other_parent.level == main_parent.level)
                        parent_ids.push_back(*parent_iter);
                }

                typename std::vector<ClusterIdType>::iterator id_iter;
                for(id_iter = parent_ids.begin(); id_iter != parent_ids.end(); ++id_iter) {
                    task_system.concat_same_level_clusters(main_parent_id, *id_iter);
                }




            }

        }


        task_system.levels_valid = false;

    }
Ejemplo n.º 25
0
inline typename DIRECTED_GRAPH::degree_size_type
in_degree(typename DIRECTED_GRAPH::vertex_descriptor v, DIRECTED_GRAPH const& g)
{ return in_degree(v, g.impl()); }
Ejemplo n.º 26
0
    static int concat_children_recursive(TaskSystemType& task_system,
                                            const typename TaskSystemType::ClusterIdType& curr_clust_id) {

        typedef typename TaskSystemType::GraphType GraphType;
        typedef typename TaskSystemType::ClusterType ClusterType;
        typedef typename TaskSystemType::ClusterIdType ClusterIdType;
        typedef typename TaskSystemType::adjacency_iterator adjacency_iterator;
		typedef typename TaskSystemType::out_edge_iterator out_edge_iterator;

        GraphType& sys_graph = task_system.sys_graph;

        ClusterType& curr_clust = sys_graph[curr_clust_id];

        double target_cost = 20;

        int nr_of_parents;
        adjacency_iterator child_iter, child_end, next_child_iter;
        boost::tie(child_iter, child_end) = adjacent_vertices(curr_clust_id, sys_graph);

        std::vector<ClusterIdType> child_ids;
        for ( ; child_iter != child_end; ++child_iter) {
            const ClusterIdType& curr_child_id = *child_iter;

            nr_of_parents = in_degree(curr_child_id, sys_graph);
            if(nr_of_parents == 1)
                child_ids.push_back(curr_child_id);
        }

        cluster_cost_comparator_by_id<GraphType> cccbi(sys_graph);
        std::sort(child_ids.begin(), child_ids.end(), cccbi);

        typename std::vector<ClusterIdType>::iterator id_iter = child_ids.begin();
        for ( ; id_iter != child_ids.end(); ++id_iter) {
            const ClusterIdType& curr_child_id = *id_iter;
            ClusterType& curr_child = sys_graph[curr_child_id];

            double gap = target_cost - curr_child.cost;
            if(gap < 0.005) {
                continue;
            }


            typename std::vector<ClusterIdType>::iterator othersid_iter = id_iter;
            /*! start from the next node.*/
            ++othersid_iter;
            while(othersid_iter != child_ids.end()) {
                ClusterIdType& other_child_id = *othersid_iter;
                ClusterType& other_child = sys_graph[other_child_id];

                if(other_child.cost <= gap) {
                    gap = gap - other_child.cost;
                    task_system.concat_same_level_clusters(curr_child_id, other_child_id);
                    othersid_iter = child_ids.erase(othersid_iter);
                }
                else {
                    ++othersid_iter;
                }
            }



        }


		adjacency_iterator curr_child_iter;
        boost::tie(child_iter, child_end) = adjacent_vertices(curr_clust_id, sys_graph);
		while(child_iter != child_end) {

			/*! Increment before concat. Apparently erasing an edge invalidates the vertex iterators in VS.
			  something is going on inside boost that I don't know yet. Or VS is just being VS as ususal.
			  (the edge container is in fact a set, but that should matter only if we iterate over ages.
			  well apparently not :) )*/
			curr_child_iter = child_iter;
			++child_iter;


			const ClusterIdType& curr_child_id = *curr_child_iter;
            ClusterType& curr_child = sys_graph[curr_child_id];

            nr_of_parents = concat_children_recursive(task_system, curr_child_id);
            if(nr_of_parents == 1) {
                if(curr_clust.cost + curr_child.cost < target_cost) {
                    task_system.concat_with_parent(curr_clust_id, curr_child_id);
				}
            }

		}


        return in_degree(curr_clust_id, sys_graph);

    }
Ejemplo n.º 27
0
void handleExtendedParams(ReportManager &rm, NGWrapper &g,
                          UNUSED const CompileContext &cc) {
    if (!hasExtParams(g)) {
        return;
    }

    depth minWidth = findMinWidth(g);
    depth maxWidth = findMaxWidth(g);
    bool is_anchored = !has_proper_successor(g.startDs, g)
                     && out_degree(g.start, g);
    bool has_offset_adj = hasOffsetAdjustments(rm, g);

    DEBUG_PRINTF("minWidth=%s, maxWidth=%s, anchored=%d, offset_adj=%d\n",
                 minWidth.str().c_str(), maxWidth.str().c_str(), is_anchored,
                 has_offset_adj);

    DepthMinMax match_depths = findMatchLengths(rm, g);
    DEBUG_PRINTF("match depths %s\n", match_depths.str().c_str());

    if (is_anchored && maxWidth.is_finite() && g.min_offset > maxWidth) {
        ostringstream oss;
        oss << "Expression is anchored and cannot satisfy min_offset="
            << g.min_offset << " as it can only produce matches of length "
            << maxWidth << " bytes at most.";
        throw CompileError(g.expressionIndex, oss.str());
    }

    if (minWidth > g.max_offset) {
        ostringstream oss;
        oss << "Expression has max_offset=" << g.max_offset << " but requires "
             << minWidth << " bytes to match.";
        throw CompileError(g.expressionIndex, oss.str());
    }

    if (maxWidth.is_finite() && match_depths.max < g.min_length) {
        ostringstream oss;
        oss << "Expression has min_length=" << g.min_length << " but can "
            "only produce matches of length " << match_depths.max <<
            " bytes at most.";
        throw CompileError(g.expressionIndex, oss.str());
    }

    if (g.min_length && g.min_length <= match_depths.min) {
        DEBUG_PRINTF("min_length=%llu constraint is unnecessary\n",
                     g.min_length);
        g.min_length = 0;
    }

    if (!hasExtParams(g)) {
        return;
    }

    pruneVacuousEdges(g);
    pruneUnmatchable(g, rm);

    if (!has_offset_adj) {
        pruneExtUnreachable(g);
    }

    // We may have removed all the edges to accept, in which case this
    // expression cannot match.
    if (in_degree(g.accept, g) == 0 && in_degree(g.acceptEod, g) == 1) {
        throw CompileError(g.expressionIndex, "Extended parameter "
                "constraints can not be satisfied for any match from "
                "this expression.");
    }

    // Remove reports on vertices without an edge to accept (which have been
    // pruned above).
    clearReports(g);

    // Recalc.
    minWidth = findMinWidth(g);
    maxWidth = findMaxWidth(g);
    is_anchored = proper_out_degree(g.startDs, g) == 0 &&
                  out_degree(g.start, g);
    has_offset_adj = hasOffsetAdjustments(rm, g);

    // If the pattern is completely anchored and has a min_length set, this can
    // be converted to a min_offset.
    if (g.min_length && (g.min_offset <= g.min_length) && is_anchored) {
        DEBUG_PRINTF("converting min_length to min_offset=%llu for "
                     "anchored case\n", g.min_length);
        g.min_offset = g.min_length;
        g.min_length = 0;
    }

    if (g.min_offset && g.min_offset <= minWidth && !has_offset_adj) {
        DEBUG_PRINTF("min_offset=%llu constraint is unnecessary\n",
                     g.min_offset);
        g.min_offset = 0;
    }

    if (!hasExtParams(g)) {
        return;
    }

    // If the pattern has a min_length and is of "ratchet" form with one
    // unbounded repeat, that repeat can become a bounded repeat.
    // e.g. /foo.*bar/{min_length=100} --> /foo.{94,}bar/
    if (g.min_length && transformMinLengthToRepeat(rm, g)) {
        DEBUG_PRINTF("converted min_length to bounded repeat\n");
        // recalc
        minWidth = findMinWidth(g);
    }

    // If the pattern is unanchored, has a max_offset and has not asked for
    // SOM, we can use that knowledge to anchor it which will limit its
    // lifespan. Note that we can't use this transformation if there's a
    // min_length, as it's currently handled using "sly SOM".

    // Note that it is possible to handle graphs that have a combination of
    // anchored and unanchored paths, but it's too tricky for the moment.

    if (g.max_offset != MAX_OFFSET && !g.som && !g.min_length &&
                !has_offset_adj && isUnanchored(g)) {
        if (anchorPatternWithBoundedRepeat(g, minWidth, maxWidth)) {
            DEBUG_PRINTF("minWidth=%s, maxWidth=%s\n", minWidth.str().c_str(),
                         maxWidth.str().c_str());
            if (minWidth == maxWidth) {
                // For a fixed width pattern, we can retire the offsets as they
                // are implicit in the graph now.
                g.min_offset = 0;
                g.max_offset = MAX_OFFSET;
            }
        }
    }
    //dumpGraph("final.dot", g.g);

    if (!hasExtParams(g)) {
        return;
    }

    set<NFAVertex> done;
    updateReportBounds(rm, g, g.accept, done);
    updateReportBounds(rm, g, g.acceptEod, done);
}
Ejemplo n.º 28
0
	degree_t getInDegree( const vertex_descriptor& v ) const { return in_degree( v, _graph ); }
Ejemplo n.º 29
0
	friend degree_size_type in_degree(vertex_descriptor v, const Self &g) {
		return in_degree(v, g.g);
	}
Ejemplo n.º 30
0
map<NFAVertex, NFAStateSet> findSquashers(const NGHolder &g, som_type som) {
    map<NFAVertex, NFAStateSet> squash;

    // Number of bits to use for all our masks. If we're a triggered graph,
    // tops have already been assigned, so we don't have to account for them.
    const u32 numStates = num_vertices(g);

    // Build post-dominator tree.
    PostDomTree pdom_tree;
    buildPDomTree(g, pdom_tree);

    // Build list of vertices by state ID and a set of init states.
    vector<NFAVertex> vByIndex(numStates, NFAGraph::null_vertex());
    NFAStateSet initStates(numStates);
    smgb_cache cache(g);

    // Mappings used for SOM mode calculations, otherwise left empty.
    unordered_map<NFAVertex, u32> region_map;
    vector<DepthMinMax> som_depths;
    if (som) {
        region_map = assignRegions(g);
        som_depths = getDistancesFromSOM(g);
    }

    for (auto v : vertices_range(g)) {
        const u32 vert_id = g[v].index;
        DEBUG_PRINTF("vertex %u/%u\n", vert_id, numStates);
        assert(vert_id < numStates);
        vByIndex[vert_id] = v;

        if (is_any_start(v, g) || !in_degree(v, g)) {
            initStates.set(vert_id);
        }
    }

    for (u32 i = 0; i < numStates; i++) {
        NFAVertex v = vByIndex[i];
        assert(v != NFAGraph::null_vertex());
        const CharReach &cr = g[v].char_reach;

        /* only non-init cyclics can be squashers */
        if (!hasSelfLoop(v, g) || initStates.test(i)) {
            continue;
        }

        DEBUG_PRINTF("state %u is cyclic\n", i);

        NFAStateSet mask(numStates), succ(numStates), pred(numStates);
        buildSquashMask(mask, g, v, cr, initStates, vByIndex, pdom_tree, som,
                        som_depths, region_map, cache);
        buildSucc(succ, g, v);
        buildPred(pred, g, v);
        const auto &reports = g[v].reports;

        for (size_t j = succ.find_first(); j != succ.npos;
             j = succ.find_next(j)) {
            NFAVertex vj = vByIndex[j];
            NFAStateSet pred2(numStates);
            buildPred(pred2, g, vj);
            if (pred2 == pred) {
                DEBUG_PRINTF("adding the sm from %zu to %u's sm\n", j, i);
                NFAStateSet tmp(numStates);
                buildSquashMask(tmp, g, vj, cr, initStates, vByIndex, pdom_tree,
                                som, som_depths, region_map, cache);
                mask &= tmp;
            }
        }

        for (size_t j = pred.find_first(); j != pred.npos;
             j = pred.find_next(j)) {
            NFAVertex vj = vByIndex[j];
            NFAStateSet succ2(numStates);
            buildSucc(succ2, g, vj);
            /* we can use j as a basis for squashing if its succs are a subset
             * of ours */
            if ((succ2 & ~succ).any()) {
                continue;
            }

            if (som) {
                /* We cannot use j to add to the squash mask of v if it may
                 * have an earlier start of match offset. ie for us j as a
                 * basis for the squash mask of v we require:
                 * maxSomDist(j) <= minSomDist(v)
                 */

                /* ** TODO ** */

                const depth &max_som_dist_j =
                    som_depths[g[vj].index].max;
                const depth &min_som_dist_v =
                    som_depths[g[v].index].min;
                if (max_som_dist_j > min_som_dist_v ||
                    max_som_dist_j.is_infinite()) {
                    /* j can't be used as it may be storing an earlier SOM */
                    continue;
                }
            }

            const CharReach &crv = g[vj].char_reach;

            /* we also require that j's report information be a subset of ours
             */
            bool seen_special = false;
            for (auto w : adjacent_vertices_range(vj, g)) {
                if (is_special(w, g)) {
                    if (!edge(v, w, g).second) {
                        goto next_j;
                    }
                    seen_special = true;
                }
            }

            // FIXME: should be subset check?
            if (seen_special && g[vj].reports != reports) {
                continue;
            }

            /* ok we can use j */
            if ((crv & ~cr).none()) {
                NFAStateSet tmp(numStates);
                buildSquashMask(tmp, g, vj, cr, initStates, vByIndex, pdom_tree,
                                som, som_depths, region_map, cache);
                mask &= tmp;
                mask.reset(j);
            }

        next_j:;
        }

        mask.set(i); /* never clear ourselves */

        if ((~mask).any()) { // i.e. some bits unset in mask
            DEBUG_PRINTF("%u squashes %zu other states\n", i, (~mask).count());
            squash.emplace(v, mask);
        }
    }

    findDerivedSquashers(g, vByIndex, pdom_tree, initStates, &squash, som,
                         som_depths, region_map, cache);

    clearMutualSquashers(g, vByIndex, squash);

    return squash;
}