src.it.unimi.dsi.law.graph.ShingleOrder Maven / Gradle / Ivy
Show all versions of law Show documentation
package it.unimi.dsi.law.graph;
/*
* Copyright (C) 2010-2020 Paolo Boldi, Massimo Santini and Sebastiano Vigna
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, see .
*
*/
import java.io.IOException;
import java.util.Random;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.martiansoftware.jsap.FlaggedOption;
import com.martiansoftware.jsap.JSAP;
import com.martiansoftware.jsap.JSAPException;
import com.martiansoftware.jsap.JSAPResult;
import com.martiansoftware.jsap.Parameter;
import com.martiansoftware.jsap.SimpleJSAP;
import com.martiansoftware.jsap.UnflaggedOption;
import it.unimi.dsi.Util;
import it.unimi.dsi.fastutil.ints.IntArrays;
import it.unimi.dsi.fastutil.io.BinIO;
import it.unimi.dsi.logging.ProgressLogger;
import it.unimi.dsi.util.XoRoShiRo128PlusRandom;
import it.unimi.dsi.webgraph.BVGraph;
import it.unimi.dsi.webgraph.ImmutableGraph;
import it.unimi.dsi.webgraph.LazyIntIterator;
import it.unimi.dsi.webgraph.NodeIterator;
// RELEASE-STATUS: BETA
/** An implementation of shingle ordering.
*
* A run of {@link #shinglePermutation(ImmutableGraph, Random)} requires three integers (12 bytes) of memory per node.
*
* @author Marco Rosa
*/
public class ShingleOrder {
private static final Logger LOGGER = LoggerFactory.getLogger(ShingleOrder.class);
/** Returns a shingle-based permutation for the specified graph.
*
* @param g a graph.
* @return a shingle-based permutation for g
.
*/
public static int[] shinglePermutation(final ImmutableGraph g) {
return shinglePermutation(g, new XoRoShiRo128PlusRandom());
}
/** Returns a shingle-based permutation for the specified graph.
*
* @param g a graph.
* @param r a pseudorandom number generator.
* @return a shingle-based permutation for g
.
*/
public static int[] shinglePermutation(final ImmutableGraph g, final Random r) {
final int n = g.numNodes();
final int[] shingle1 = computeShingles(g, r);
final int[] shingle2 = computeShingles(g, r);
final int[] perm = Util.identity(new int[n]);
IntArrays.quickSort(perm, 0, n, (x, y) -> {
int t = shingle1[x] - shingle1[y];
if (t != 0) return t;
t = shingle2[x] - shingle2[y];
if (t != 0) return t;
return x - y;
});
return it.unimi.dsi.Util.invertPermutationInPlace(perm);
}
/** Computes a vector of integer shingles for the specified graph.
*
* @param g a graph.
* @param r a pseudorandom number generator.
* @return an array of shingles for g
.
*/
public static int[] computeShingles(final ImmutableGraph g, final Random r) {
final int n = g.numNodes();
final int[] hash = IntArrays.shuffle(Util.identity(n), r);
final int[] minimum = new int[n];
final NodeIterator nodes = g.nodeIterator();
final ProgressLogger pl = new ProgressLogger(LOGGER, "nodes");
pl.expectedUpdates = n;
pl.start();
for(int i = n; i-- != 0; pl.lightUpdate()) {
final int src = nodes.nextInt();
int m = Integer.MAX_VALUE;
final LazyIntIterator successors = nodes.successors();
for(int outdegree = nodes.outdegree(); outdegree-- != 0;) {
final int dest = successors.nextInt();
if (dest != src && hash[dest] < m) m = hash[dest];
}
minimum[src] = m;
}
pl.done();
return minimum;
}
public static void main(final String[] args) throws JSAPException, IOException {
final SimpleJSAP jsap = new SimpleJSAP(ShingleOrder.class.getName(), "Sort a given graph by shingle ordering.", new Parameter[] {
new FlaggedOption("randomSeed", JSAP.LONG_PARSER, "0", JSAP.NOT_REQUIRED, 'r', "random-seed", "The random seed."),
//new Switch("random", 'p', "Start from a random permutation."),
new UnflaggedOption("graph", JSAP.STRING_PARSER, JSAP.REQUIRED, "The basename of the input graph"),
new UnflaggedOption("perm", JSAP.STRING_PARSER, JSAP.REQUIRED, "The name of the output permutation"), });
final JSAPResult jsapResult = jsap.parse(args);
if (jsap.messagePrinted()) System.exit(1);
final ImmutableGraph graph = BVGraph.loadOffline(jsapResult.getString("graph"));
final XoRoShiRo128PlusRandom r = jsapResult.userSpecified("randomSeed") ? new XoRoShiRo128PlusRandom(jsapResult.getLong("randomSeed")) : new XoRoShiRo128PlusRandom();
BinIO.storeInts(shinglePermutation(graph, r), jsapResult.getString("perm"));
}
}