00001
00002
00003 #include "angel/include/graph_generator.hpp"
00004
00005 #include <vector>
00006 #include <cstdlib>
00007 #include <numeric>
00008
00009 #include "angel/include/angel_exceptions.hpp"
00010 #include "angel/include/angel_types.hpp"
00011 #include "angel/include/angel_tools.hpp"
00012
00013 #ifndef NDEBUG
00014 #include "angel/include/angel_io.hpp"
00015 #endif
00016
00017 namespace angel {
00018
00019 using namespace std;
00020 using namespace boost;
00021
00022
00023
00024 void random_statement (int inputs, int expr, const vector<double>& p,
00025 c_graph_t& statement) {
00026
00027 typedef c_graph_t::vertex_t vertex_t;
00028
00029 int maxar= int (p.size());
00030
00031
00032 throw_debug_exception (inputs + expr - 1 > expr * maxar, consistency_exception,
00033 "Un-usable inputs");
00034
00035
00036
00037
00038 int V= inputs + expr;
00039 vector<int> expi (V);
00040 for (int i= inputs; i < V; i++)
00041 expi[i]= angel::random (p) + 1;
00042
00043
00044
00045 for (int m= inputs + expr - 1 - accumulate (expi.begin(), expi.end(), 0);
00046 m > 0; m--)
00047 for (;;) {
00048 int e= angel::random (inputs, V-1);
00049 if (expi[e] < maxar) {expi[e]++; break; }}
00050
00051
00052 vector<vertex_t> deps (1);
00053 deps[0]= V - 1;
00054 c_graph_t gtmp (V, inputs, deps);
00055
00056
00057 for (int i= V - 2; i >= 0; i--) {
00058 vertex_t v= vertex (i, gtmp);
00059 for (;;) {
00060 int s= angel::random (max (i+1, inputs), V-1);
00061 vertex_t vs= vertex (s, gtmp);
00062 if (int (in_degree (vs, gtmp)) < expi[s]) {
00063 add_edge (v, vs, gtmp); break;}
00064 }}
00065
00066
00067
00068 for (int i= inputs; i < V; i++) {
00069 vertex_t v= vertex (i, gtmp);
00070 for (; int (in_degree (v, gtmp)) < expi[i];) {
00071 int pr= angel::random (0, inputs-1);
00072 vertex_t vpr= vertex (pr, gtmp);
00073
00074
00075
00076
00077 add_edge (vpr, v, gtmp);
00078 }
00079 }
00080
00081 statement.swap (gtmp);
00082 }
00083
00084
00085
00086 void random_statement_vector (int max_expr, double unary,
00087 std::vector<c_graph_t>& statement_vector) {
00088
00089 throw_debug_exception (unary < 0.0 || unary > 1.0, consistency_exception,
00090 "unary must be between 0 and 1");
00091 std::vector<double> p (2);
00092 p[0]= unary; p[1]= 1.0;
00093
00094
00095 throw_debug_exception (statement_vector.size() == 0, consistency_exception,
00096 "statement vector must be non-empty");
00097 for (size_t i= 0; i < statement_vector.size(); i++) {
00098 int expr= angel::random (1, max_expr);
00099
00100 int inputs= (angel::random (expr) + angel::random (expr)) / 2 + 1;
00101 random_statement (inputs, expr, p, statement_vector[i]);
00102 #ifndef NDEBUG
00103 write_graph ("random_statement", statement_vector[i]);
00104 #endif
00105 }
00106 }
00107
00108
00109
00110 void stats2block (int inputs, int outputs, const std::vector<c_graph_t>& stats,
00111 c_graph_t& block) {
00112 typedef c_graph_t::vertex_t vertex_t;
00113 typedef c_graph_t::oei_t oei_t;
00114
00115 int nstats= int (stats.size());
00116
00117 throw_debug_exception (nstats < outputs, consistency_exception,
00118 "More outputs than statements");
00119
00120 #ifndef NDEBUG
00121 for (int i= 0; i < nstats; i++) {
00122 const c_graph_t& stat= stats[i];
00123
00124 throw_debug_exception (stat.dependents.size() != 1, consistency_exception,
00125 "Statements must have 1 output");
00126
00127 throw_debug_exception (stat.dependents[0] != vertex (stat.v()-1, stat), consistency_exception,
00128 "Statements output must be last vertex"); }
00129 #endif
00130
00131 int V= inputs;
00132
00133 vector<int> soffset (nstats);
00134 for (int i= 0; i < nstats; i++) {
00135 soffset[i]= V - stats[i].x();
00136 V+= stats[i].v() - stats[i].x(); }
00137
00138
00139 vector<vertex_t> deps;
00140 c_graph_t gtmp (V, inputs, deps);
00141
00142
00143 int en= 0;
00144 for (int i= 0; i < nstats; i++) {
00145 const c_graph_t& stat= stats[i];
00146 int so= soffset[i];
00147 for (int iv= stat.x(); iv < stat.v(); iv++)
00148 take_over_successors (vertex (iv, stat), vertex (iv+so, gtmp),
00149 so, stat, en, gtmp); }
00150
00151
00152
00153 deps.resize (outputs);
00154
00155
00156
00157 typedef pair<int,int> succ_t;
00158 vector<succ_t> sl;
00159 for (int i= 0; i < outputs; i++)
00160 sl.push_back (make_pair (-1, i));
00161
00162
00163 for (int i= nstats-1; i >= 0; i--) {
00164 vertex_t vb= vertex (soffset[i] + stats[i].v() - 1, gtmp);
00165 int si= angel::random (int (sl.size()));
00166 succ_t succ= sl[si];
00167 int succs= succ.first, succi= succ.second;
00168 if (succs == -1)
00169 deps[succi]= vb;
00170 else {
00171 const c_graph_t& sstat= stats[succs];
00172 vertex_t ivs= vertex (succi, sstat);
00173
00174 take_over_successors (ivs, vb, soffset[succs], sstat, en, gtmp);
00175 }
00176
00177 remove (sl.begin(), sl.end(), succ); sl.resize (sl.size()-1);
00178
00179 for (int j= 0; j < stats[i].x(); j++)
00180 sl.push_back (make_pair (i, j));
00181 }
00182
00183
00184 while (sl.size() > 0 && sl[0].first == -1) {
00185 int output= sl[0].second;
00186
00187 remove (sl.begin(), sl.end(), sl[0]); sl.resize (sl.size()-1);
00188 vertex_t vb;
00189 do {
00190 int ss= angel::random (nstats);
00191 vb= vertex (soffset[ss] + stats[ss].v() - 1, gtmp);
00192 } while (find (deps.begin(), deps.end(), vb) != deps.end());
00193 deps[output]= vb;
00194 }
00195
00196
00197 for (int i= 0; i < inputs; i++) {
00198
00199 throw_exception (sl.size() == 0, consistency_exception, "Not enough inputs");
00200 vertex_t vi= vertex (i, gtmp);
00201 succ_t succ= sl[angel::random (int (sl.size()))];
00202 int succs= succ.first, succi= succ.second;
00203 const c_graph_t& sstat= stats[succs];
00204 vertex_t ivs= vertex (succi, sstat);
00205
00206 take_over_successors (ivs, vi, soffset[succs], sstat, en, gtmp);
00207
00208 remove (sl.begin(), sl.end(), succ); sl.resize (sl.size()-1);
00209 }
00210
00211
00212
00213
00214 vector<vertex_t> pl;
00215 for (int i= 0; i < inputs; i++) {
00216 vertex_t v= vertex (i, gtmp); pl.push_back (v); }
00217 for (int i= 0; i < nstats; i++) {
00218 vertex_t v= vertex (soffset[i] + stats[i].v() - 1, gtmp);
00219 pl.push_back (v); }
00220 while (sl.size() > 0) {
00221 succ_t succ= sl[sl.size()-1];
00222 int succs= succ.first, succi= succ.second;
00223 const c_graph_t& sstat= stats[succs];
00224 vertex_t ivs= vertex (succi, sstat);
00225 vertex_t vp= pl[angel::random (inputs+succs)];
00226 take_over_successors (ivs, vp, soffset[succs], sstat, en, gtmp);
00227 sl.resize (sl.size()-1);
00228 }
00229
00230 gtmp.dependents.swap (deps);
00231
00232 block.swap (gtmp);
00233 }
00234
00235
00236
00237 void random_block (int inputs, int outputs, int stats, int max_exp, double unary,
00238 c_graph_t& block) {
00239
00240 std::vector<c_graph_t> statement_vector (stats);
00241 random_statement_vector (max_exp, unary, statement_vector);
00242 stats2block (inputs, outputs, statement_vector, block);
00243
00244 }
00245
00246
00247
00248
00249 void block2loop (const c_graph_t& block, int loops,
00250 c_graph_t& loop) {
00251
00252
00253 typedef c_graph_t::vertex_t vertex_t;
00254 typedef c_graph_t::oei_t oei_t;
00255
00256
00257 int binputs= block.x(), boutputs= block.y(), bv= block.v(),
00258 linputs= binputs <= boutputs ? binputs : binputs + (loops-1)*(binputs-boutputs),
00259
00260 isize= min (binputs, boutputs),
00261 lv= loops * block.v() - (loops-1) * isize;
00262 vector<vertex_t> dependents;
00263 c_graph_t gtmp (lv, linputs, dependents);
00264
00265
00266 vector<vertex_t> input (binputs);
00267 for (int c= 0; c < binputs; c++) input[c]= c;
00268
00269
00270 int en= 0;
00271 c_graph_t::ei_t ei, e_end;
00272 for (tie (ei, e_end)= edges (block); ei != e_end; ++ei)
00273 add_edge (source (*ei, block), target (*ei, block), en++, gtmp);
00274
00275 for (int l= 1; l < loops; l++) {
00276
00277 vertex_t goffset= l * (bv - isize),
00278 lgoffset= goffset - bv + isize;
00279
00280
00281 for (int i= 0; i < isize; i++) {
00282 vertex_t bv= vertex (i, block);
00283
00284 vertex_t lv= lgoffset + block.dependents[i];
00285 oei_t oei, oe_end;
00286 for (tie (oei, oe_end)= out_edges (bv, block); oei != oe_end; ++oei) {
00287 add_edge (lv, goffset + target (*oei, block), en++, gtmp); }
00288 }
00289
00290
00291 for (int i= isize; i < binputs; i++)
00292 input.push_back (goffset + vertex_t (i));
00293 for (int i= isize; i < boutputs; i++)
00294 dependents.push_back (lgoffset + block.dependents[i]);
00295
00296
00297 for (int i= isize; i < bv; i++) {
00298 vertex_t bv= vertex (i, block),
00299 lv= goffset + vertex_t (i);
00300 oei_t oei, oe_end;
00301 for (tie (oei, oe_end)= out_edges (bv, block); oei != oe_end; ++oei)
00302 add_edge (lv, vertex_t (goffset + target (*oei, block)), en++, gtmp);
00303 }
00304 }
00305
00306
00307 vertex_t goffset= (loops - 1) * (bv - isize);
00308 for (int i= 0; i < boutputs; i++)
00309 dependents.push_back (goffset + block.dependents[i]);
00310
00311 gtmp.X= int (input.size());
00312 gtmp.dependents.swap (dependents);
00313
00314 independent_vertices_to_front (gtmp, input, loop);
00315
00316
00317
00318 loop.clear_graph ();
00319 loop.next_edge_number= renumber_edges (loop);
00320 }
00321
00322
00323 random_init_t random_init_object;
00324
00325 }