package dgm.graphs;
import dgm.EdgeID;
import dgm.ID;
import java.util.*;
/**
*
*/
public class RandomizedGraphBuilder
{
final Random random;
final HashMap<String, String> environment = new HashMap<String, String>();
public RandomizedGraphBuilder(int randomSeed)
{
random = new Random(randomSeed);
}
// "(a,b,c,d) -- label --> (d,e,f,g)"
public EdgeID edge(String edgeSpec)
{
final String[] s = edgeSpec.trim().split(" ");
final String tail_str = s[0];
final String label = s[2];
final String head_str = s[4];
if(s[1].length() != 2 || s[3].length() != 3)
throw new RuntimeException("Invalid specification format, '--' and '-->' are used to specify edges");
final ID tail = parseIDStr(s[0], "Tail");
final ID head = parseIDStr(s[4], "Head");
return new EdgeID(tail, label, head);
}
// mutate the environment, place random values for the identifiers
private ID parseIDStr(String s, String whichOne)
{
if(! (s.startsWith("(") && s.endsWith(")")))
throw new RuntimeException(whichOne +
" vertex identifier must be enclosed within round brackets, '(' and ')'");
// split variable
final String[] vars = s.substring(1, s.length() - 1).split(",");
if(vars.length != 4)
throw new RuntimeException(whichOne +
" vertex identifier must have four elements, e.g. '(a,b,c,0)' or '(foo,bar,baz,123)'");
final String index = lookupOrCreate(vars[0], environment, false);
final String type = lookupOrCreate(vars[1], environment, false);
final String id = lookupOrCreate(vars[2], environment, false);
final String version = lookupOrCreate(vars[3], environment, true);
return new ID(index, type, id, Integer.parseInt(version));
}
private String lookupOrCreate(String key, Map<String,String> environment, boolean number)
{
// the symbolic version always resolves to 0
if(number && key.equals("0"))
return "0";
// create new random value, either an integer or a random string
if(!environment.containsKey(key))
{
final String value = freshName(environment, number);
environment.put(key, value);
return value;
}
return environment.get(key);
}
private String freshName(Map<String,String> environment, boolean numeric)
{
final int MAX_TRIES = 32;
for(int i = 0; i < MAX_TRIES; i++)
{
final String value;
if(numeric)
// create random positive number
value = Integer.toString(random.nextInt(Integer.MAX_VALUE-10)+1);
else
// take some random word
value = RandomIdentifierGenerator.randomWord(random.nextInt(Integer.MAX_VALUE));
// value already exists in our environment
if(environment.values().contains(value))
continue;
return value;
}
throw new RuntimeException("Couldn't find a fresh value after " + MAX_TRIES + " tries");
}
}