Java源码示例:it.unimi.dsi.webgraph.ArrayListMutableGraph
示例1
/** Generate a random DAG using preferential attachment. First an independent set of <code>n0</code> nodes is generated.
* Then <code>n-n0</code> more nodes are generated: for each node, the outdegree is determined using <code>outdegreeDistribution.nextInt()</code>
* minimized with the number of existing nodes. For each arc, the target is the existing node <code>i</code> with probability proportional to
* <code>k+1</code> where <code>k</code> is <code>i</code>'s current outdegree.
*
* @param n number of nodes.
* @param n0 number of initial nodes.
* @param outdegreeDistribution distribution from which outdegrees are sampled.
* @param random generator used to produce the arcs.
* @return the generated DAG.
*/
public static ArrayListMutableGraph preferentialAttachmentDAG(final int n, final int n0, final IntegerDistribution outdegreeDistribution, final RandomGenerator random) {
final ArrayListMutableGraph g = new ArrayListMutableGraph(n);
final FenwickTree ft = new FenwickTree(n);
// Initial independent set
for (int source = 0; source < n0; source++) ft.incrementCount(source + 1);
// Rest of the graph
final IntOpenHashSet s = new IntOpenHashSet();
for (int source = n0; source < n; source++) {
final int m = Math.min(outdegreeDistribution.sample(), source - 1); // Outdegree
s.clear();
while(s.size() < m) {
final int t = ft.sample(random);
if (s.add(t)) {
ft.incrementCount(t);
g.addArc(source, t - 1);
}
}
ft.incrementCount(source + 1);
}
return g;
}
示例2
@Test(expected=IllegalArgumentException.class)
public void testWrongBound() throws IOException, JSAPException {
// (0,1) (0,2) (0,3) (1,7)
ImmutableGraph graph1 = new XImmutableGraph(ImmutableGraph.wrap(new ArrayListMutableGraph(8, new int[][] { { 0, 1 }, { 0, 2 }, { 0, 3 }, { 1, 7 } }).immutableView()), 4);
// (4,2) (4,3) (7,4) (7,6)
ImmutableGraph graph2 = new XImmutableGraph(ImmutableGraph.wrap(new ArrayListMutableGraph(8, new int[][] { { 0, 2 }, { 0, 3 }, { 3, 4 }, { 3, 6 } }).immutableView()), 4);
File ef1 = new File(dir, "graph1.ef");
EFGraph.store(graph1, 10, ef1.getAbsolutePath(), null);
File ef2 = new File(dir, "graph2.ef");
EFGraph.store(graph2, 8, ef2.getAbsolutePath(), null);
File result = new File(dir, "result-ef"); result.delete();
CatEFGraphs.main(new String[] { "-m", result.getAbsolutePath(), ef1.getAbsolutePath(), ef2.getAbsolutePath() });
}
示例3
/** Generates <code>np</code> call graphs. Each call graph is obtained using {@link #preferentialAttachmentDAG(int, int, IntegerDistribution, RandomGenerator)} (with
* specified initial graph size (<code>initialGraphSizeDistribution</code>), graph size (<code>graphSizeDistribution</code>), outdegree distribution (<code>outdegreeDistribution</code>).
* Then a dependency DAG is generated between the call graphs, once more using {@link #preferentialAttachmentDAG(int, int, IntegerDistribution, RandomGenerator)} (this
* time the initial graph size is 1, whereas the outdegree distribution is <code>outdegreeDistribution</code>).
* Then to each node of each call graph a new set of outgoing arcs is generated (their number is chosen using <code>externalOutdegreeDistribution</code>): the target
* call graph is generated using the indegree distribution of the dependency DAG; the target node is chosen according to the reverse indegree distribution within the revision call graph.
*
* @param np number of revision call graphs to be generated.
* @param graphSizeDistribution the distribution of the graph sizes (number of functions per call graph).
* @param initialGraphSizeDistribution the distribution of the initial graph sizes (the initial independent set from which the preferential attachment starts).
* @param outdegreeDistribution the distribution of internal outdegrees (number of internal calls per function).
* @param externalOutdegreeDistribution the distribution of external outdegrees (number of external calls per function).
* @param depExponent exponent of the Zipf distribution used to establish the dependencies between call graphs.
* @param random the random object used for the generation.
*/
public void generate(final int np, final IntegerDistribution graphSizeDistribution, final IntegerDistribution initialGraphSizeDistribution,
final IntegerDistribution outdegreeDistribution, final IntegerDistribution externalOutdegreeDistribution, final IntegerDistribution dependencyOutdegreeDistribution, final RandomGenerator random) {
rcgs = new ArrayListMutableGraph[np];
nodePermutation = new int[np][];
final FenwickTree[] td = new FenwickTree[np];
deps = new IntOpenHashSet[np];
source2Targets = new ObjectOpenCustomHashSet[np];
// Generate rcg of the np revisions, and the corresponding reverse preferential distribution; cumsize[i] is the sum of all nodes in packages <i
for ( int i = 0; i < np; i++) {
deps[i] = new IntOpenHashSet();
final int n = graphSizeDistribution.sample();
final int n0 = Math.min(initialGraphSizeDistribution.sample(), n);
rcgs[i] = preferentialAttachmentDAG(n, n0, outdegreeDistribution, random);
td[i] = getPreferentialDistribution(rcgs[i].immutableView(), true);
nodePermutation[i] = Util.identity(n);
Collections.shuffle(IntArrayList.wrap(nodePermutation[i]), new Random(random.nextLong()));
}
// Generate the dependency DAG between revisions using preferential attachment starting from 1 node
final ArrayListMutableGraph depDAG = preferentialAttachmentDAG(np, 1, dependencyOutdegreeDistribution, random);
// For each source package, generate function calls so to cover all dependencies
for (int sourcePackage = 0; sourcePackage < np; sourcePackage++) {
source2Targets[sourcePackage] = new ObjectOpenCustomHashSet<>(IntArrays.HASH_STRATEGY);
final int outdegree = depDAG.outdegree(sourcePackage);
if (outdegree == 0) continue; // No calls needed (I'm kinda busy)
final int numFuncs = rcgs[sourcePackage].numNodes();
final int[] externalArcs = new int[numFuncs];
int allExternalArcs = 0;
// We decide how many calls to dispatch from each function
for (int sourceNode = 0; sourceNode < numFuncs; sourceNode++) allExternalArcs += (externalArcs[sourceNode] = externalOutdegreeDistribution.sample());
// We create a global list of external successors by shuffling
final int[] targetPackage = new int[allExternalArcs];
final int[] succ = depDAG.successorArray(sourcePackage);
for(int i = 0; i < outdegree; i++) deps[sourcePackage].add(succ[i]);
for(int i = 0; i < allExternalArcs; i++) targetPackage[i] = succ[i % outdegree];
MathArrays.shuffle(targetPackage, random);
for (int sourceNode = allExternalArcs = 0; sourceNode < numFuncs; sourceNode++) {
final int externalOutdegree = externalArcs[sourceNode];
for (int t = 0; t < externalOutdegree; t++) {
final int targetNode = td[targetPackage[allExternalArcs + t]].sample(random) - 1;
source2Targets[sourcePackage].add(new int[] { sourceNode, targetPackage[allExternalArcs + t], targetNode });
}
allExternalArcs += externalOutdegree;
}
}
}
示例4
private static String graph2String(final CallGraphGenerator callGraphGenerator, final int i, final RandomGenerator randomGenerator) {
final ArrayListMutableGraph g = callGraphGenerator.rcgs[i];
final StringBuilder sb = new StringBuilder();
sb.append("{\n");
sb.append("\t\"product\": \"graph-" + i + "\",\n");
sb.append("\t\"forge\": \"f\",\n");
sb.append("\t\"generator\": \"OPAL\",\n");
sb.append("\t\"version\": \"1.0\",\n");
sb.append("\t\"timestamp\": \"0\",\n");
sb.append("\t\"depset\": [\n\t\t");
// All generated DNFs are singletons
for(final IntIterator d = callGraphGenerator.deps[i].iterator(); d.hasNext(); ) {
sb.append( "[{ \"forge\": \"f\", \"product\": \"graph-" + d.nextInt() + "\", \"constraints\": [\"[1.0]\"] }]");
if (d.hasNext()) sb.append(", ");
}
sb.append("\n\t],\n");
sb.append("\t\"cha\": {\n");
for (int jj = 0; jj < g.numNodes() / 3; jj++) {
sb.append("\t\t\"/p" + i + "/A" + jj + "\": {\n");
sb.append("\t\t\t\"methods\": {\n");
for (int j = 3 * jj; j < 3 * jj + 3 && j < g.numNodes(); j++) {
sb.append("\t\t\t\t\"" + j + "\": \"/p" + i + "/A" + jj + ".f" + j + "()v\"");
if (j < 3 * jj + 2 && j < g.numNodes() + 1) sb.append(",");
sb.append("\n");
}
sb.append("\t\t\t},\n");
sb.append("\t\t\t\"superInterfaces\": [],\n");
sb.append("\t\t\t\"sourceFile\": \"A" + jj + ".java\",\n");
sb.append("\t\t\t\"superClasses\": [\"/java.lang/Object\"]\n");
sb.append("\t\t}");
if (jj < g.numNodes() / 3 - 1) sb.append(",");
sb.append("\n");
}
sb.append("\t},\n");
sb.append("\t\"graph\": {\n");
// Internal calls
sb.append("\t\t\"internalCalls\": [\n");
final ObjectArrayList<String> lines = new ObjectArrayList<>(); // Graph lines
for(int j = 0; j < g.numNodes(); j++) {
for(final IntIterator s = g.successors(j); s.hasNext();)
lines.add("\t\t\t[\n\t\t\t\t" + callGraphGenerator.nodePermutation[i][j] + ",\n\t\t\t\t" + callGraphGenerator.nodePermutation[i][s.nextInt()] + "\n\t\t\t]");
}
Collections.shuffle(lines, new Random(randomGenerator.nextLong())); // Permute graph lines
for (int j = 0; j < lines.size(); j++) {
sb.append(lines.get(j));
if (j < lines.size() - 1) sb.append(",");
sb.append("\n");
}
sb.append("\t\t],\n");
// External calls
sb.append("\t\t\"externalCalls\": [\n");
lines.clear();
for(final int[] t: callGraphGenerator.source2Targets[i]) {
lines.add("\t\t\t[\n\t\t\t\t\"" + callGraphGenerator.nodePermutation[i][t[0]] + "\",\n\t\t\t\t\"/p" + t[1] + "/A"+ callGraphGenerator.nodePermutation[t[1]][t[2]] / 3 + ".f" + callGraphGenerator.nodePermutation[t[1]][t[2]] +"()v\",\n"
+ "\t\t\t\t{\"invokevirtual\": \"1\"}\n"
+ "\t\t\t]");
}
Collections.shuffle(lines, new Random(randomGenerator.nextLong())); // Permute graph lines
for (int j = 0; j < lines.size(); j++) {
sb.append(lines.get(j));
if (j < lines.size() - 1) sb.append(",");
sb.append("\n");
}
sb.append("\t\t]\n");
sb.append("\t}\n");
sb.append("}");
return sb.toString();
}