10#include "mcrl2/pg/SCC.h"
11#include "mcrl2/pg/shuffle.h"
12#include "mcrl2/utilities/logger.h"
55 successor_index_ = NULL;
67 predecessor_index_ = NULL;
74 return a.first < b.first || (a.first == b.first && a.second < b.second);
80 return a.second < b.second || (a.second == b.second && a.first < b.first);
86 decompose_graph(*
this, sccs);
95 const std::vector<verti> scc;
96 for (verti j = 0; j < scc.size(); ++j)
101 std::vector<
char> is_top(sccs.size(), 1),
102 is_bot(sccs.size(), 1);
108 if (index[v] != index[w])
110 is_bot[index[v]] = 0;
111 is_top[index[w]] = 0;
117
119 std::vector<verti> vertis;
122 if (is_top[i] || is_bot[i])
124 vertis.push_back(sccs[i][rand()%sccs[i].size()]);
127 mCRL2log(mcrl2::log::debug) <<
"Connecting " << vertis.size()
128 <<
" of " << V_ <<
" vertices to create an SCC." << std::endl;
129 shuffle_vector(vertis);
132 const verti v = vertis[i],
133 w = vertis[(i + 1)%sccs.size()];
134 edges.push_back(
std::make_pair(v, w));
149 assert(RAND_MAX >= 2*outdeg);
150 assert(RAND_MAX >= V);
153
154
156 std::vector<verti> neighbours(V);
157 for (verti i = 0; i < V; ++i) neighbours[i] = i;
158 for (
verti i = 0; i < V; ++i)
160 unsigned N = 1 + rand()%(2*outdeg - 1);
161 if (N >= V - 1) N = V - 1;
162 for (
unsigned n = 0; n < N; ++n)
164 std::swap(neighbours[n], neighbours[n + rand()%(V - n)]);
165 if (neighbours[n] == i)
167 std::swap( neighbours[n],
168 neighbours[n + 1 + rand()%(V - n - 1)] );
170 edges.push_back(std::make_pair(i, neighbours[n]));
185 decompose_graph(*
this, new_sccs);
186 assert(new_sccs.size() == 1);
194 assert(cluster_size > 1);
195 std::size_t clusters = V/cluster_size;
204 for (
std::size_t i = 0; i < clusters; ++i)
207 outdeg
, edge_dir
, true );
211 for (
int i = 0; clusters > 1; ++i)
214 << i <<
"..." <<
std::endl;
215 std::size_t next_clusters = (clusters + cluster_size - 1)/cluster_size;
217 std::vector<verti> offset(clusters, 0);
218 for (
std::size_t c = 0; c < next_clusters; ++c)
221 std::size_t i = c*clusters/next_clusters,
222 j = (c + 1)*clusters/next_clusters;
224 << i <<
" through " << j <<
" of "
225 << clusters <<
")" <<
std::endl;
228 for (
std::size_t k = i + 1; k < j; ++k)
230 offset[k] = offset[k - 1] + subgraphs[k - 1].V();
235 for (
std::size_t k = i; k < j; ++k)
238 for ( edge_list::const_iterator it = subedges.begin();
239 it != subedges.end(); ++it )
241 edges.push_back(std::make_pair( it->first + offset[k],
242 it->second + offset[k] ));
250 for (
std::size_t e = 0; e < paredges.size(); ++e)
252 verti v = paredges[e].first,
253 w = paredges[e].second;
254 edges.push_back(std::make_pair(
255 offset[i + v] + rand()%subgraphs[i + v].V(),
256 offset[i + w] + rand()%subgraphs[i + w].V() ));
261 subgraphs = next_subgraphs;
262 clusters = next_clusters;
264 assert(clusters == 1);
271 std::vector<verti> perm(V_);
272 for (verti i = 0; i < V_; ++i) perm[i] = i;
273 shuffle_vector(perm);
274 shuffle_vertices(perm);
280 for (edge_list::iterator it = edges.begin(); it != edges.end(); ++it)
282 it->first = perm[it->first];
283 it->second = perm[it->second];
290 if (&graph ==
this)
return;
312 for (edge_list::iterator it = edges.begin(); it != edges.end(); ++it)
314 if (it->first >= V) V = it->first + 1;
315 if (it->second >= V) V = it->second + 1;
320 assert(E == edges.size());
335 for (
verti v = 0; v < V; ++v)
337 while (pos < E && edges[pos].first < v) ++pos;
343 for (edgei e = 0; e < E; ++e) successors_[e] = edges[e].second;
353 for (
verti v = 0; v < V; ++v)
355 while (pos < E && edges[pos].second < v) ++pos;
361 for (edgei e = 0; e < E; ++e) predecessors_[e] = edges[e].first;
368 edges.push_back(
std::make_pair(
V_,
V_));
379 StaticGraph::edge_list::const_iterator it = edges.begin();
391 while (edge_cmp_forward(*it, edge)) ++it;
392 if (*it == edge) ++it;
else successors_[e++] = edge.second;
402 StaticGraph::edge_list::const_iterator it = edges.begin();
414 while (edge_cmp_backward(*it, edge)) ++it;
415 if (*it == edge) ++it;
else predecessors_[e++] = edge.first;
447 for (
edgei i = begin; i < end; ++i)
450 result.push_back(
std::make_pair(v, w));
453 assert(result.size() ==
E_);
459 os.write((
const char*)&
V_,
sizeof(
V_));
460 os.write((
const char*)&
E_,
sizeof(
E_));
480 is.read((
char*)&V,
sizeof(V));
481 is.read((
char*)&E,
sizeof(E));
482 is.read((
char*)&edge_dir,
sizeof(edge_dir));
500 if (
this == &g)
return;
511void StaticGraph::make_subgraph_threads(
const StaticGraph &graph,
513 const verti num_vertices,
515 EdgeDirection edge_dir )
517 assert(
this != &graph);
522 std::vector<verti> map(graph.V(), NO_VERTEX);
526 for (verti i = 0; i < num_vertices; ++i)
532 #pragma omp for reduction(+:num_edges)
533 for (verti i = 0; i < num_vertices; ++i)
535 const_iterator a = graph.succ_begin(verts[i]),
536 b = graph.succ_end(verts[i]);
537 while (a != b)
if (map[*a++] != NO_VERTEX) ++num_edges;
542 reset(num_vertices, num_edges, edge_dir ? edge_dir : graph.edge_dir());
548 if (edge_dir_ & EDGE_SUCCESSOR)
553 for (verti i = 0; i < num_vertices; ++i)
555 const verti u = verts[i];
556 successor_index_[v++] = e;
557 verti *begin = &successors_[e];
558 for (const_iterator succ_it = graph.succ_begin(u),
559 succ_end = graph.succ_end(u);
560 succ_it != succ_end; ++succ_it)
562 verti w = map[*succ_it];
563 if (w != NO_VERTEX) successors_[e++] = w;
565 verti *end = &successors_[e];
566 if (!std::is_sorted(begin, end, std::less<verti>()))
568 std::sort(begin, end);
570 if (proper) assert(begin != end);
572 assert(v == V_ && e == E_);
573 successor_index_[v] = e;
576 if (edge_dir_ & EDGE_PREDECESSOR)
581 for (verti i = 0; i < num_vertices; ++i)
583 const verti u = verts[i];
584 predecessor_index_[v++] = e;
585 verti *begin = &predecessors_[e];
586 for (const_iterator pred_it = graph.pred_begin(u),
587 pred_end = graph.pred_end(u);
588 pred_it != pred_end; ++pred_it)
590 verti w = map[*pred_it];
591 if (w != NO_VERTEX) predecessors_[e++] = w;
593 verti *end = &predecessors_[e];
594 if (!std::is_sorted(begin, end, std::less<verti>()))
596 std::sort(begin, end);
599 assert(v == V_ && e == E_);
600 predecessor_index_[v] = e;
static bool edge_cmp_backward(const std::pair< verti, verti > &a, const std::pair< verti, verti > &b)
static bool edge_cmp_forward(const std::pair< verti, verti > &a, const std::pair< verti, verti > &b)
std::size_t edgei
type used to number edges
std::size_t verti
type used to number vertices
std::vector< std::pair< verti, verti > > edge_list
void make_random(verti V, unsigned outdeg, EdgeDirection edge_dir, bool scc)
const_iterator succ_end(verti v) const
void reset(verti V, edgei E, EdgeDirection edge_dir)
edgei * predecessor_index_
void make_random_clustered(verti cluster_size, verti V, unsigned outdeg, EdgeDirection edge_dir)
void read_raw(std::istream &is)
void swap(StaticGraph &g)
const_iterator succ_begin(verti v) const
void assign(edge_list edges, EdgeDirection edge_dir)
void make_random_scc(edge_list &edges)
void write_raw(std::ostream &os) const
edge_list get_edges() const
void assign(const StaticGraph &graph)
void remove_edges(edge_list &edges)
void shuffle_vertices(const std::vector< verti > &perm)
const verti * const_iterator
logger(const log_level_t l)
Default constructor.
#define mCRL2log(LEVEL)
mCRL2log(LEVEL) provides the stream used to log.
std::size_t operator()(const atermpp::detail::reference_aterm< T > &t) const