ThemeDataSetGenerator.java
/*******************************************************************************
* Copyright (c) 2025 Eclipse RDF4J contributors.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Distribution License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: BSD-3-Clause
*******************************************************************************/
// Some portions generated by Codex
package org.eclipse.rdf4j.benchmark.rio.util;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Random;
import java.util.function.Consumer;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Literal;
import org.eclipse.rdf4j.model.Model;
import org.eclipse.rdf4j.model.Resource;
import org.eclipse.rdf4j.model.Value;
import org.eclipse.rdf4j.model.ValueFactory;
import org.eclipse.rdf4j.model.impl.LinkedHashModel;
import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
import org.eclipse.rdf4j.model.vocabulary.RDF;
import org.eclipse.rdf4j.rio.RDFHandler;
import org.eclipse.rdf4j.rio.helpers.StatementCollector;
public final class ThemeDataSetGenerator {
public enum Theme {
MEDICAL_RECORDS,
SOCIAL_MEDIA,
LIBRARY,
ENGINEERING,
HIGHLY_CONNECTED,
TRAIN,
ELECTRICAL_GRID,
PHARMA
}
private static final String BASE = "http://example.com/theme/";
private static final String MEDICAL_NS = BASE + "medical/";
private static final String SOCIAL_NS = BASE + "social/";
private static final String LIBRARY_NS = BASE + "library/";
private static final String ENGINEERING_NS = BASE + "engineering/";
private static final String CONNECTED_NS = BASE + "connected/";
private static final String TRAIN_NS = BASE + "train/";
private static final String GRID_NS = BASE + "grid/";
private static final String PHARMA_NS = BASE + "pharma/";
private static final ValueFactory VF = SimpleValueFactory.getInstance();
private static final String[] WORDS = new String[] {
"alpha", "beta", "gamma", "delta", "epsilon", "omega", "vector", "node", "graph", "system",
"signal", "sensor", "dataset", "record", "event", "network", "route", "station", "engine",
"grid", "current", "voltage", "load", "train", "cable", "user", "profile", "post", "comment"
};
private static final long JITTER_SEED_XOR = 0x9E3779B97F4A7C15L;
private ThemeDataSetGenerator() {
}
public static MedicalConfig medicalConfig() {
return new MedicalConfig();
}
public static SocialMediaConfig socialMediaConfig() {
return new SocialMediaConfig();
}
public static LibraryConfig libraryConfig() {
return new LibraryConfig();
}
public static EngineeringConfig engineeringConfig() {
return new EngineeringConfig();
}
public static HighlyConnectedConfig highlyConnectedConfig() {
return new HighlyConnectedConfig();
}
public static TrainConfig trainConfig() {
return new TrainConfig();
}
public static ElectricalGridConfig electricalGridConfig() {
return new ElectricalGridConfig();
}
public static PharmaConfig pharmaConfig() {
return new PharmaConfig();
}
public static Model generate(Theme theme) {
return generateModel(handler -> generate(theme, handler));
}
public static void generate(Theme theme, RDFHandler handler) {
Objects.requireNonNull(theme, "theme");
Objects.requireNonNull(handler, "handler");
switch (theme) {
case MEDICAL_RECORDS:
generateMedicalRecords(medicalConfig(), handler);
break;
case SOCIAL_MEDIA:
generateSocialMedia(socialMediaConfig(), handler);
break;
case LIBRARY:
generateLibrary(libraryConfig(), handler);
break;
case ENGINEERING:
generateEngineering(engineeringConfig(), handler);
break;
case HIGHLY_CONNECTED:
generateHighlyConnected(highlyConnectedConfig(), handler);
break;
case TRAIN:
generateTrain(trainConfig(), handler);
break;
case ELECTRICAL_GRID:
generateElectricalGrid(electricalGridConfig(), handler);
break;
case PHARMA:
generatePharma(pharmaConfig(), handler);
break;
default:
throw new IllegalArgumentException("Unsupported theme " + theme);
}
}
public static Model generateMedicalRecords(MedicalConfig config) {
return generateModel(handler -> generateMedicalRecords(config, handler));
}
public static void generateMedicalRecords(MedicalConfig config, RDFHandler handler) {
Objects.requireNonNull(config, "config");
Objects.requireNonNull(handler, "handler");
config.validate();
Random contentRandom = new Random(config.seed);
Random jitterRandom = jitterRandom(config.seed);
IRI patientType = iri(MEDICAL_NS, "Patient");
IRI encounterType = iri(MEDICAL_NS, "Encounter");
IRI conditionType = iri(MEDICAL_NS, "Condition");
IRI medicationType = iri(MEDICAL_NS, "Medication");
IRI practitionerType = iri(MEDICAL_NS, "Practitioner");
IRI observationType = iri(MEDICAL_NS, "Observation");
IRI hasEncounter = iri(MEDICAL_NS, "hasEncounter");
IRI hasCondition = iri(MEDICAL_NS, "hasCondition");
IRI hasMedication = iri(MEDICAL_NS, "hasMedication");
IRI hasObservation = iri(MEDICAL_NS, "hasObservation");
IRI handledBy = iri(MEDICAL_NS, "handledBy");
IRI recordedOn = iri(MEDICAL_NS, "recordedOn");
IRI hasName = iri(MEDICAL_NS, "name");
IRI hasCode = iri(MEDICAL_NS, "code");
IRI dosage = iri(MEDICAL_NS, "dosage");
IRI observationValue = iri(MEDICAL_NS, "value");
handler.startRDF();
handler.handleNamespace("med", MEDICAL_NS);
int practitionerCount = jitterInt(jitterRandom, config.practitionerCount);
int patientCount = jitterInt(jitterRandom, config.patientCount);
List<IRI> practitioners = new ArrayList<>(practitionerCount);
for (int i = 0; i < practitionerCount; i++) {
IRI practitioner = entity(MEDICAL_NS, "practitioner", i);
practitioners.add(practitioner);
add(handler, practitioner, RDF.TYPE, practitionerType);
add(handler, practitioner, hasName, literal("Dr " + randomWord(contentRandom) + " " + i));
}
int medicationIndex = 0;
int encounterIndex = 0;
int conditionIndex = 0;
int observationIndex = 0;
for (int p = 0; p < patientCount; p++) {
IRI patient = entity(MEDICAL_NS, "patient", p);
add(handler, patient, RDF.TYPE, patientType);
add(handler, patient, hasName, literal("Patient " + p));
int medicationsPerPatient = jitterInt(jitterRandom, config.medicationsPerPatient);
for (int m = 0; m < medicationsPerPatient; m++) {
IRI medication = entity(MEDICAL_NS, "medication", medicationIndex++);
add(handler, medication, RDF.TYPE, medicationType);
add(handler, medication, hasCode, literal("MED-" + (1000 + m)));
add(handler, medication, dosage, literal((1 + contentRandom.nextInt(3)) + "x daily"));
add(handler, patient, hasMedication, medication);
}
int encountersPerPatient = jitterInt(jitterRandom, config.encountersPerPatient);
for (int e = 0; e < encountersPerPatient; e++) {
IRI encounter = entity(MEDICAL_NS, "encounter", encounterIndex++);
add(handler, encounter, RDF.TYPE, encounterType);
add(handler, patient, hasEncounter, encounter);
add(handler, encounter, recordedOn,
VF.createLiteral(LocalDate.of(2024, 1, 1).plusDays(contentRandom.nextInt(365))));
IRI practitioner = practitioners.get(contentRandom.nextInt(practitioners.size()));
add(handler, encounter, handledBy, practitioner);
int conditionsPerEncounter = jitterInt(jitterRandom, config.conditionsPerEncounter);
for (int c = 0; c < conditionsPerEncounter; c++) {
IRI condition = entity(MEDICAL_NS, "condition", conditionIndex++);
add(handler, condition, RDF.TYPE, conditionType);
add(handler, condition, hasCode, literal("DX-" + (200 + c)));
add(handler, encounter, hasCondition, condition);
}
int observationsPerEncounter = jitterInt(jitterRandom, config.observationsPerEncounter);
for (int o = 0; o < observationsPerEncounter; o++) {
IRI observation = entity(MEDICAL_NS, "observation", observationIndex++);
add(handler, observation, RDF.TYPE, observationType);
add(handler, observation, observationValue,
VF.createLiteral(50 + contentRandom.nextInt(50)));
add(handler, encounter, hasObservation, observation);
}
}
}
handler.endRDF();
}
public static Model generateSocialMedia(SocialMediaConfig config) {
return generateModel(handler -> generateSocialMedia(config, handler));
}
public static void generateSocialMedia(SocialMediaConfig config, RDFHandler handler) {
Objects.requireNonNull(config, "config");
Objects.requireNonNull(handler, "handler");
config.validate();
Random contentRandom = new Random(config.seed);
Random jitterRandom = jitterRandom(config.seed);
IRI userType = iri(SOCIAL_NS, "User");
IRI postType = iri(SOCIAL_NS, "Post");
IRI commentType = iri(SOCIAL_NS, "Comment");
IRI tagType = iri(SOCIAL_NS, "Tag");
IRI follows = iri(SOCIAL_NS, "follows");
IRI authored = iri(SOCIAL_NS, "authored");
IRI likedBy = iri(SOCIAL_NS, "likedBy");
IRI hasComment = iri(SOCIAL_NS, "hasComment");
IRI hasTag = iri(SOCIAL_NS, "hasTag");
IRI createdAt = iri(SOCIAL_NS, "createdAt");
IRI hasName = iri(SOCIAL_NS, "name");
IRI content = iri(SOCIAL_NS, "content");
handler.startRDF();
handler.handleNamespace("social", SOCIAL_NS);
int userCount = jitterInt(jitterRandom, config.userCount);
int tagCount = jitterInt(jitterRandom, config.tagCount);
int[] cliqueSizes = jitterCliqueSizes(jitterRandom, config.cliqueSizes, userCount);
List<IRI> users = new ArrayList<>(userCount);
for (int u = 0; u < userCount; u++) {
IRI user = entity(SOCIAL_NS, "user", u);
users.add(user);
add(handler, user, RDF.TYPE, userType);
add(handler, user, hasName, literal("user" + u));
}
int cliqueStart = 0;
for (int cliqueSize : cliqueSizes) {
List<IRI> clique = users.subList(cliqueStart, cliqueStart + cliqueSize);
for (int i = 0; i < clique.size(); i++) {
IRI source = clique.get(i);
for (int j = 0; j < clique.size(); j++) {
if (i == j) {
continue;
}
add(handler, source, follows, clique.get(j));
}
}
cliqueStart += cliqueSize;
}
List<IRI> tags = new ArrayList<>(tagCount);
for (int t = 0; t < tagCount; t++) {
IRI tag = entity(SOCIAL_NS, "tag", t);
tags.add(tag);
add(handler, tag, RDF.TYPE, tagType);
add(handler, tag, hasName, literal("tag" + t));
}
int postIndex = 0;
int commentIndex = 0;
for (IRI user : users) {
int followsPerUser = jitterInt(jitterRandom, config.followsPerUser);
for (int f = 0; f < followsPerUser; f++) {
IRI target = users.get(contentRandom.nextInt(users.size()));
if (!user.equals(target)) {
add(handler, user, follows, target);
}
}
int postsPerUser = jitterInt(jitterRandom, config.postsPerUser);
for (int p = 0; p < postsPerUser; p++) {
IRI post = entity(SOCIAL_NS, "post", postIndex++);
add(handler, post, RDF.TYPE, postType);
add(handler, post, authored, user);
add(handler, post, content, literal(randomSentence(contentRandom, 5, 12)));
add(handler, post, createdAt,
VF.createLiteral(LocalDateTime.of(2024, 1, 1, 8, 0).plusHours(contentRandom.nextInt(500))));
int tagsPerPost = jitterInt(jitterRandom, config.tagsPerPost);
for (int t = 0; t < tagsPerPost; t++) {
IRI tag = tags.get(contentRandom.nextInt(tags.size()));
add(handler, post, hasTag, tag);
}
int likesPerPost = jitterInt(jitterRandom, config.likesPerPost);
for (int l = 0; l < likesPerPost; l++) {
IRI liker = users.get(contentRandom.nextInt(users.size()));
add(handler, post, likedBy, liker);
}
int commentsPerPost = jitterInt(jitterRandom, config.commentsPerPost);
for (int c = 0; c < commentsPerPost; c++) {
IRI comment = entity(SOCIAL_NS, "comment", commentIndex++);
IRI commenter = users.get(contentRandom.nextInt(users.size()));
add(handler, comment, RDF.TYPE, commentType);
add(handler, comment, authored, commenter);
add(handler, comment, content, literal(randomSentence(contentRandom, 3, 8)));
add(handler, post, hasComment, comment);
}
}
}
handler.endRDF();
}
public static Model generateLibrary(LibraryConfig config) {
return generateModel(handler -> generateLibrary(config, handler));
}
public static void generateLibrary(LibraryConfig config, RDFHandler handler) {
Objects.requireNonNull(config, "config");
Objects.requireNonNull(handler, "handler");
config.validate();
Random contentRandom = new Random(config.seed);
Random jitterRandom = jitterRandom(config.seed);
IRI bookType = iri(LIBRARY_NS, "Book");
IRI authorType = iri(LIBRARY_NS, "Author");
IRI copyType = iri(LIBRARY_NS, "Copy");
IRI memberType = iri(LIBRARY_NS, "Member");
IRI loanType = iri(LIBRARY_NS, "Loan");
IRI branchType = iri(LIBRARY_NS, "Branch");
IRI writtenBy = iri(LIBRARY_NS, "writtenBy");
IRI hasCopy = iri(LIBRARY_NS, "hasCopy");
IRI locatedAt = iri(LIBRARY_NS, "locatedAt");
IRI borrowedBy = iri(LIBRARY_NS, "borrowedBy");
IRI loanedCopy = iri(LIBRARY_NS, "loanedCopy");
IRI loanDate = iri(LIBRARY_NS, "loanDate");
IRI dueDate = iri(LIBRARY_NS, "dueDate");
IRI hasName = iri(LIBRARY_NS, "name");
IRI title = iri(LIBRARY_NS, "title");
handler.startRDF();
handler.handleNamespace("lib", LIBRARY_NS);
int authorCount = jitterInt(jitterRandom, config.authorCount);
int branchCount = jitterInt(jitterRandom, config.branchCount);
int bookCount = jitterInt(jitterRandom, config.bookCount);
int memberCount = jitterInt(jitterRandom, config.memberCount);
List<IRI> authors = new ArrayList<>(authorCount);
for (int a = 0; a < authorCount; a++) {
IRI author = entity(LIBRARY_NS, "author", a);
authors.add(author);
add(handler, author, RDF.TYPE, authorType);
add(handler, author, hasName, literal("Author " + a));
}
List<IRI> branches = new ArrayList<>(branchCount);
for (int b = 0; b < branchCount; b++) {
IRI branch = entity(LIBRARY_NS, "branch", b);
branches.add(branch);
add(handler, branch, RDF.TYPE, branchType);
add(handler, branch, hasName, literal("Branch " + b));
}
List<IRI> copies = new ArrayList<>();
int copyIndex = 0;
for (int b = 0; b < bookCount; b++) {
IRI book = entity(LIBRARY_NS, "book", b);
add(handler, book, RDF.TYPE, bookType);
add(handler, book, title, literal("Book " + b + " " + randomWord(contentRandom)));
int authorsPerBook = jitterInt(jitterRandom, config.authorsPerBook);
for (int a = 0; a < authorsPerBook; a++) {
IRI author = authors.get(contentRandom.nextInt(authors.size()));
add(handler, book, writtenBy, author);
}
int copiesPerBook = jitterInt(jitterRandom, config.copiesPerBook);
for (int c = 0; c < copiesPerBook; c++) {
IRI copy = entity(LIBRARY_NS, "copy", copyIndex++);
copies.add(copy);
add(handler, copy, RDF.TYPE, copyType);
add(handler, copy, locatedAt, branches.get(contentRandom.nextInt(branches.size())));
add(handler, book, hasCopy, copy);
}
}
List<IRI> members = new ArrayList<>(memberCount);
for (int m = 0; m < memberCount; m++) {
IRI member = entity(LIBRARY_NS, "member", m);
members.add(member);
add(handler, member, RDF.TYPE, memberType);
add(handler, member, hasName, literal("Member " + m));
}
int loanIndex = 0;
for (IRI member : members) {
int loansPerMember = jitterInt(jitterRandom, config.loansPerMember);
for (int l = 0; l < loansPerMember; l++) {
IRI loan = entity(LIBRARY_NS, "loan", loanIndex++);
IRI copy = copies.get(contentRandom.nextInt(copies.size()));
add(handler, loan, RDF.TYPE, loanType);
add(handler, loan, borrowedBy, member);
add(handler, loan, loanedCopy, copy);
LocalDate date = LocalDate.of(2024, 1, 1).plusDays(contentRandom.nextInt(90));
add(handler, loan, loanDate, VF.createLiteral(date));
add(handler, loan, dueDate, VF.createLiteral(date.plusDays(14)));
}
}
handler.endRDF();
}
public static Model generateEngineering(EngineeringConfig config) {
return generateModel(handler -> generateEngineering(config, handler));
}
public static void generateEngineering(EngineeringConfig config, RDFHandler handler) {
Objects.requireNonNull(config, "config");
Objects.requireNonNull(handler, "handler");
config.validate();
Random contentRandom = new Random(config.seed);
Random jitterRandom = jitterRandom(config.seed);
IRI componentType = iri(ENGINEERING_NS, "Component");
IRI assemblyType = iri(ENGINEERING_NS, "Assembly");
IRI requirementType = iri(ENGINEERING_NS, "Requirement");
IRI testType = iri(ENGINEERING_NS, "TestCase");
IRI measurementType = iri(ENGINEERING_NS, "Measurement");
IRI partOf = iri(ENGINEERING_NS, "partOf");
IRI dependsOn = iri(ENGINEERING_NS, "dependsOn");
IRI satisfies = iri(ENGINEERING_NS, "satisfies");
IRI verifiedBy = iri(ENGINEERING_NS, "verifiedBy");
IRI measuredValue = iri(ENGINEERING_NS, "measuredValue");
IRI hasName = iri(ENGINEERING_NS, "name");
handler.startRDF();
handler.handleNamespace("eng", ENGINEERING_NS);
int assemblyCount = jitterInt(jitterRandom, config.assemblyCount);
int componentCount = jitterInt(jitterRandom, config.componentCount);
int requirementCount = jitterInt(jitterRandom, config.requirementCount);
List<IRI> assemblies = new ArrayList<>(assemblyCount);
for (int a = 0; a < assemblyCount; a++) {
IRI assembly = entity(ENGINEERING_NS, "assembly", a);
assemblies.add(assembly);
add(handler, assembly, RDF.TYPE, assemblyType);
add(handler, assembly, hasName, literal("Assembly " + a));
}
List<IRI> components = new ArrayList<>(componentCount);
for (int c = 0; c < componentCount; c++) {
IRI component = entity(ENGINEERING_NS, "component", c);
components.add(component);
add(handler, component, RDF.TYPE, componentType);
add(handler, component, hasName, literal("Component " + c));
add(handler, component, partOf, assemblies.get(contentRandom.nextInt(assemblies.size())));
if (components.size() > 1) {
IRI dependency = components.get(contentRandom.nextInt(components.size() - 1));
add(handler, component, dependsOn, dependency);
}
}
List<IRI> requirements = new ArrayList<>(requirementCount);
for (int r = 0; r < requirementCount; r++) {
IRI requirement = entity(ENGINEERING_NS, "requirement", r);
requirements.add(requirement);
add(handler, requirement, RDF.TYPE, requirementType);
add(handler, requirement, hasName, literal("REQ-" + (1000 + r)));
IRI component = components.get(contentRandom.nextInt(components.size()));
add(handler, requirement, satisfies, component);
}
int testIndex = 0;
int measurementIndex = 0;
for (IRI requirement : requirements) {
int testsPerRequirement = jitterInt(jitterRandom, config.testsPerRequirement);
for (int t = 0; t < testsPerRequirement; t++) {
IRI test = entity(ENGINEERING_NS, "test", testIndex++);
add(handler, test, RDF.TYPE, testType);
add(handler, requirement, verifiedBy, test);
IRI measurement = entity(ENGINEERING_NS, "measurement", measurementIndex++);
add(handler, measurement, RDF.TYPE, measurementType);
add(handler, measurement, measuredValue, VF.createLiteral(0.8 + contentRandom.nextDouble() * 0.2));
add(handler, test, verifiedBy, measurement);
}
}
handler.endRDF();
}
public static Model generateHighlyConnected(HighlyConnectedConfig config) {
return generateModel(handler -> generateHighlyConnected(config, handler));
}
public static void generateHighlyConnected(HighlyConnectedConfig config, RDFHandler handler) {
Objects.requireNonNull(config, "config");
Objects.requireNonNull(handler, "handler");
config.validate();
Random contentRandom = new Random(config.seed);
Random jitterRandom = jitterRandom(config.seed);
IRI nodeType = iri(CONNECTED_NS, "Node");
IRI connectsTo = iri(CONNECTED_NS, "connectsTo");
IRI linkWeight = iri(CONNECTED_NS, "weight");
handler.startRDF();
handler.handleNamespace("conn", CONNECTED_NS);
int nodeCount = jitterInt(jitterRandom, config.nodeCount);
int hubCount = jitterInt(jitterRandom, config.hubCount);
double hubBias = jitterDouble(jitterRandom, config.hubBias, 0.0, 1.0);
List<IRI> nodes = new ArrayList<>(nodeCount);
for (int i = 0; i < nodeCount; i++) {
IRI node = entity(CONNECTED_NS, "node", i);
nodes.add(node);
add(handler, node, RDF.TYPE, nodeType);
}
List<IRI> hubs = nodes.subList(0, Math.min(hubCount, nodes.size()));
for (IRI node : nodes) {
int edgesPerNode = jitterInt(jitterRandom, config.edgesPerNode);
for (int e = 0; e < edgesPerNode; e++) {
IRI target = contentRandom.nextDouble() < hubBias
? hubs.get(contentRandom.nextInt(hubs.size()))
: nodes.get(contentRandom.nextInt(nodes.size()));
if (!node.equals(target)) {
add(handler, node, connectsTo, target);
add(handler, node, linkWeight, VF.createLiteral(1 + contentRandom.nextInt(10)));
}
}
}
handler.endRDF();
}
public static Model generateTrain(TrainConfig config) {
return generateModel(handler -> generateTrain(config, handler));
}
public static void generateTrain(TrainConfig config, RDFHandler handler) {
Objects.requireNonNull(config, "config");
Objects.requireNonNull(handler, "handler");
config.validate();
Random contentRandom = new Random(config.seed);
Random jitterRandom = jitterRandom(config.seed);
IRI operationalPointType = iri(TRAIN_NS, "OperationalPoint");
IRI lineType = iri(TRAIN_NS, "Line");
IRI sectionType = iri(TRAIN_NS, "SectionOfLine");
IRI trackSectionType = iri(TRAIN_NS, "TrackSection");
IRI serviceType = iri(TRAIN_NS, "TrainService");
IRI partOfLine = iri(TRAIN_NS, "partOfLine");
IRI connectsOperationalPoint = iri(TRAIN_NS, "connectsOperationalPoint");
IRI hasTrackSection = iri(TRAIN_NS, "hasTrackSection");
IRI trackSectionOf = iri(TRAIN_NS, "trackSectionOf");
IRI runsOnSection = iri(TRAIN_NS, "runsOnSection");
IRI passesThrough = iri(TRAIN_NS, "passesThrough");
IRI scheduledTime = iri(TRAIN_NS, "scheduledTime");
IRI hasName = iri(TRAIN_NS, "name");
handler.startRDF();
handler.handleNamespace("train", TRAIN_NS);
int stationCount = jitterInt(jitterRandom, config.stationCount);
int routeCount = jitterInt(jitterRandom, config.routeCount);
int trainCount = jitterInt(jitterRandom, config.trainCount);
List<IRI> operationalPoints = new ArrayList<>(stationCount);
for (int s = 0; s < stationCount; s++) {
IRI operationalPoint = entity(TRAIN_NS, "operational-point", s);
operationalPoints.add(operationalPoint);
add(handler, operationalPoint, RDF.TYPE, operationalPointType);
add(handler, operationalPoint, hasName, literal("OP " + s));
}
List<IRI> lines = new ArrayList<>(routeCount);
for (int l = 0; l < routeCount; l++) {
IRI line = entity(TRAIN_NS, "line", l);
lines.add(line);
add(handler, line, RDF.TYPE, lineType);
add(handler, line, hasName, literal("Line " + l));
}
List<IRI> sections = new ArrayList<>();
int sectionIndex = 0;
int trackIndex = 0;
int stationOffset = 0;
for (int lineIndex = 0; lineIndex < lines.size(); lineIndex++) {
IRI line = lines.get(lineIndex);
int stopsPerRoute = jitterInt(jitterRandom, config.stopsPerRoute);
for (int s = 0; s < stopsPerRoute; s++) {
IRI section = entity(TRAIN_NS, "section", sectionIndex++);
sections.add(section);
add(handler, section, RDF.TYPE, sectionType);
add(handler, section, partOfLine, line);
IRI start = operationalPoints.get((stationOffset + s) % operationalPoints.size());
IRI end = operationalPoints.get((stationOffset + s + 1) % operationalPoints.size());
add(handler, section, connectsOperationalPoint, start);
add(handler, section, connectsOperationalPoint, end);
IRI trackSection = entity(TRAIN_NS, "track-section", trackIndex++);
add(handler, trackSection, RDF.TYPE, trackSectionType);
add(handler, section, hasTrackSection, trackSection);
add(handler, trackSection, trackSectionOf, section);
}
stationOffset += stopsPerRoute;
}
int serviceIndex = 0;
for (int t = 0; t < trainCount; t++) {
IRI service = entity(TRAIN_NS, "service", serviceIndex++);
add(handler, service, RDF.TYPE, serviceType);
add(handler, service, hasName, literal("Service " + t));
int tripsPerTrain = jitterInt(jitterRandom, config.tripsPerTrain);
for (int tr = 0; tr < tripsPerTrain; tr++) {
IRI section = sections.get(contentRandom.nextInt(sections.size()));
IRI operationalPoint = operationalPoints.get(contentRandom.nextInt(operationalPoints.size()));
add(handler, service, runsOnSection, section);
add(handler, service, passesThrough, operationalPoint);
add(handler, service, scheduledTime,
VF.createLiteral(LocalTime.of(5, 0).plusMinutes(contentRandom.nextInt(600))));
}
}
handler.endRDF();
}
public static Model generateElectricalGrid(ElectricalGridConfig config) {
return generateModel(handler -> generateElectricalGrid(config, handler));
}
public static void generateElectricalGrid(ElectricalGridConfig config, RDFHandler handler) {
Objects.requireNonNull(config, "config");
Objects.requireNonNull(handler, "handler");
config.validate();
Random contentRandom = new Random(config.seed);
Random jitterRandom = jitterRandom(config.seed);
IRI substationType = iri(GRID_NS, "Substation");
IRI transformerType = iri(GRID_NS, "Transformer");
IRI lineType = iri(GRID_NS, "Line");
IRI meterType = iri(GRID_NS, "Meter");
IRI loadType = iri(GRID_NS, "Load");
IRI generatorType = iri(GRID_NS, "Generator");
IRI feeds = iri(GRID_NS, "feeds");
IRI connectsTo = iri(GRID_NS, "connectsTo");
IRI hasMeter = iri(GRID_NS, "hasMeter");
IRI measures = iri(GRID_NS, "measures");
IRI loadValue = iri(GRID_NS, "loadValue");
IRI capacity = iri(GRID_NS, "capacity");
IRI hasName = iri(GRID_NS, "name");
handler.startRDF();
handler.handleNamespace("grid", GRID_NS);
int substationCount = jitterInt(jitterRandom, config.substationCount);
List<IRI> substations = new ArrayList<>(substationCount);
for (int s = 0; s < substationCount; s++) {
IRI substation = entity(GRID_NS, "substation", s);
substations.add(substation);
add(handler, substation, RDF.TYPE, substationType);
add(handler, substation, hasName, literal("Substation " + s));
}
int transformerIndex = 0;
int lineIndex = 0;
int meterIndex = 0;
int loadIndex = 0;
for (IRI substation : substations) {
int transformersPerSubstation = jitterInt(jitterRandom, config.transformersPerSubstation);
for (int t = 0; t < transformersPerSubstation; t++) {
IRI transformer = entity(GRID_NS, "transformer", transformerIndex++);
add(handler, transformer, RDF.TYPE, transformerType);
add(handler, transformer, feeds, substation);
int metersPerTransformer = jitterInt(jitterRandom, config.metersPerTransformer);
for (int m = 0; m < metersPerTransformer; m++) {
IRI meter = entity(GRID_NS, "meter", meterIndex++);
IRI load = entity(GRID_NS, "load", loadIndex++);
add(handler, meter, RDF.TYPE, meterType);
add(handler, load, RDF.TYPE, loadType);
add(handler, meter, measures, load);
add(handler, transformer, hasMeter, meter);
add(handler, load, loadValue, VF.createLiteral(50 + contentRandom.nextInt(150)));
}
}
int linesPerSubstation = jitterInt(jitterRandom, config.linesPerSubstation);
for (int l = 0; l < linesPerSubstation; l++) {
IRI line = entity(GRID_NS, "line", lineIndex++);
IRI target = substations.get(contentRandom.nextInt(substations.size()));
add(handler, line, RDF.TYPE, lineType);
add(handler, line, connectsTo, substation);
add(handler, line, connectsTo, target);
}
IRI generator = entity(GRID_NS, "generator", substationIndex(substation));
add(handler, generator, RDF.TYPE, generatorType);
add(handler, generator, feeds, substation);
add(handler, generator, capacity, VF.createLiteral(500 + contentRandom.nextInt(500)));
}
handler.endRDF();
}
public static Model generatePharma(PharmaConfig config) {
return generateModel(handler -> generatePharma(config, handler));
}
public static void generatePharma(PharmaConfig config, RDFHandler handler) {
Objects.requireNonNull(config, "config");
Objects.requireNonNull(handler, "handler");
config.validate();
Random contentRandom = new Random(config.seed);
Random jitterRandom = jitterRandom(config.seed);
IRI drugType = iri(PHARMA_NS, "Drug");
IRI moleculeType = iri(PHARMA_NS, "Molecule");
IRI chemicalClassType = iri(PHARMA_NS, "ChemicalClass");
IRI targetType = iri(PHARMA_NS, "Target");
IRI pathwayType = iri(PHARMA_NS, "Pathway");
IRI diseaseType = iri(PHARMA_NS, "Disease");
IRI trialType = iri(PHARMA_NS, "ClinicalTrial");
IRI armType = iri(PHARMA_NS, "TrialArm");
IRI resultType = iri(PHARMA_NS, "TrialResult");
IRI sideEffectType = iri(PHARMA_NS, "SideEffect");
IRI biomarkerType = iri(PHARMA_NS, "Biomarker");
IRI combinationType = iri(PHARMA_NS, "Combination");
IRI comparatorType = iri(PHARMA_NS, "Comparator");
IRI hasName = iri(PHARMA_NS, "name");
IRI hasMolecule = iri(PHARMA_NS, "hasMolecule");
IRI inClass = iri(PHARMA_NS, "inClass");
IRI targets = iri(PHARMA_NS, "targets");
IRI inPathway = iri(PHARMA_NS, "inPathway");
IRI indicatedFor = iri(PHARMA_NS, "indicatedFor");
IRI contraindicatedFor = iri(PHARMA_NS, "contraindicatedFor");
IRI testedIn = iri(PHARMA_NS, "testedIn");
IRI studiesDisease = iri(PHARMA_NS, "studiesDisease");
IRI hasArm = iri(PHARMA_NS, "hasArm");
IRI armDrug = iri(PHARMA_NS, "armDrug");
IRI armComparator = iri(PHARMA_NS, "armComparator");
IRI hasResult = iri(PHARMA_NS, "hasResult");
IRI endpoint = iri(PHARMA_NS, "endpoint");
IRI effectSize = iri(PHARMA_NS, "effectSize");
IRI pValue = iri(PHARMA_NS, "pValue");
IRI responseRate = iri(PHARMA_NS, "responseRate");
IRI observedSideEffect = iri(PHARMA_NS, "observedSideEffect");
IRI hasSideEffect = iri(PHARMA_NS, "hasSideEffect");
IRI severity = iri(PHARMA_NS, "severity");
IRI biomarker = iri(PHARMA_NS, "biomarker");
IRI biomarkerValue = iri(PHARMA_NS, "biomarkerValue");
IRI combinationOf = iri(PHARMA_NS, "combinationOf");
IRI synergyScore = iri(PHARMA_NS, "synergyScore");
IRI phase = iri(PHARMA_NS, "phase");
String[] severities = new String[] { "Mild", "Moderate", "Severe" };
String[] endpoints = new String[] { "OverallSurvival", "ProgressionFreeSurvival", "ResponseRate" };
int chemicalClassCount = jitterInt(jitterRandom, config.chemicalClassCount);
int pathwayCount = jitterInt(jitterRandom, config.pathwayCount);
int targetCount = jitterInt(jitterRandom, config.targetCount);
int moleculeCount = jitterInt(jitterRandom, config.moleculeCount);
int diseaseCount = jitterInt(jitterRandom, config.diseaseCount);
int sideEffectCount = jitterInt(jitterRandom, config.sideEffectCount);
int biomarkerCount = jitterInt(jitterRandom, config.biomarkerCount);
int drugCount = jitterInt(jitterRandom, config.drugCount);
int comparatorCount = jitterInt(jitterRandom, config.comparatorCount);
int trialCount = jitterInt(jitterRandom, config.trialCount);
int combinationCount = jitterInt(jitterRandom, config.combinationCount);
handler.startRDF();
handler.handleNamespace("pharma", PHARMA_NS);
List<IRI> chemicalClasses = new ArrayList<>(chemicalClassCount);
for (int c = 0; c < chemicalClassCount; c++) {
IRI chemicalClass = entity(PHARMA_NS, "class", c);
chemicalClasses.add(chemicalClass);
add(handler, chemicalClass, RDF.TYPE, chemicalClassType);
add(handler, chemicalClass, hasName, literal("Class " + c));
}
List<IRI> pathways = new ArrayList<>(pathwayCount);
for (int p = 0; p < pathwayCount; p++) {
IRI pathway = entity(PHARMA_NS, "pathway", p);
pathways.add(pathway);
add(handler, pathway, RDF.TYPE, pathwayType);
add(handler, pathway, hasName, literal("Pathway " + p));
}
List<IRI> targetsList = new ArrayList<>(targetCount);
for (int t = 0; t < targetCount; t++) {
IRI target = entity(PHARMA_NS, "target", t);
targetsList.add(target);
add(handler, target, RDF.TYPE, targetType);
add(handler, target, hasName, literal("Target " + t));
add(handler, target, inPathway, pathways.get(contentRandom.nextInt(pathways.size())));
}
List<IRI> molecules = new ArrayList<>(moleculeCount);
for (int m = 0; m < moleculeCount; m++) {
IRI molecule = entity(PHARMA_NS, "molecule", m);
molecules.add(molecule);
add(handler, molecule, RDF.TYPE, moleculeType);
add(handler, molecule, hasName, literal("Molecule " + m));
add(handler, molecule, inClass, chemicalClasses.get(contentRandom.nextInt(chemicalClasses.size())));
int targetsPerMolecule = jitterInt(jitterRandom, config.targetsPerMolecule);
for (int t = 0; t < targetsPerMolecule; t++) {
add(handler, molecule, targets, targetsList.get(contentRandom.nextInt(targetsList.size())));
}
}
List<IRI> diseases = new ArrayList<>(diseaseCount);
for (int d = 0; d < diseaseCount; d++) {
IRI disease = entity(PHARMA_NS, "disease", d);
diseases.add(disease);
add(handler, disease, RDF.TYPE, diseaseType);
add(handler, disease, hasName, literal("Disease " + d));
}
List<IRI> sideEffects = new ArrayList<>(sideEffectCount);
for (int s = 0; s < sideEffectCount; s++) {
IRI sideEffect = entity(PHARMA_NS, "side-effect", s);
sideEffects.add(sideEffect);
add(handler, sideEffect, RDF.TYPE, sideEffectType);
add(handler, sideEffect, hasName, literal("SideEffect " + s));
add(handler, sideEffect, severity, literal(severities[s % severities.length]));
}
List<IRI> biomarkers = new ArrayList<>(biomarkerCount);
for (int b = 0; b < biomarkerCount; b++) {
IRI marker = entity(PHARMA_NS, "biomarker", b);
biomarkers.add(marker);
add(handler, marker, RDF.TYPE, biomarkerType);
add(handler, marker, hasName, literal("Biomarker " + b));
}
List<IRI> drugs = new ArrayList<>(drugCount);
for (int d = 0; d < drugCount; d++) {
IRI drug = entity(PHARMA_NS, "drug", d);
drugs.add(drug);
add(handler, drug, RDF.TYPE, drugType);
add(handler, drug, hasName, literal("Drug " + d));
int moleculesPerDrug = jitterInt(jitterRandom, config.moleculesPerDrug);
for (int m = 0; m < moleculesPerDrug; m++) {
add(handler, drug, hasMolecule, molecules.get(contentRandom.nextInt(molecules.size())));
}
int targetsPerDrug = jitterInt(jitterRandom, config.targetsPerDrug);
for (int t = 0; t < targetsPerDrug; t++) {
add(handler, drug, targets, targetsList.get(contentRandom.nextInt(targetsList.size())));
}
int indicationsPerDrug = jitterInt(jitterRandom, config.indicationsPerDrug);
for (int i = 0; i < indicationsPerDrug; i++) {
add(handler, drug, indicatedFor, diseases.get(contentRandom.nextInt(diseases.size())));
}
add(handler, drug, contraindicatedFor, diseases.get(contentRandom.nextInt(diseases.size())));
int sideEffectsPerDrug = jitterInt(jitterRandom, config.sideEffectsPerDrug);
for (int s = 0; s < sideEffectsPerDrug; s++) {
add(handler, drug, hasSideEffect, sideEffects.get(contentRandom.nextInt(sideEffects.size())));
}
}
List<IRI> comparators = new ArrayList<>(comparatorCount);
for (int c = 0; c < comparatorCount; c++) {
IRI comparator = entity(PHARMA_NS, "comparator", c);
comparators.add(comparator);
add(handler, comparator, RDF.TYPE, comparatorType);
add(handler, comparator, hasName, literal("Comparator " + c));
}
List<IRI> trials = new ArrayList<>(trialCount);
int armIndex = 0;
int resultIndex = 0;
for (int t = 0; t < trialCount; t++) {
IRI trial = entity(PHARMA_NS, "trial", t);
trials.add(trial);
add(handler, trial, RDF.TYPE, trialType);
add(handler, trial, hasName, literal("Trial " + t));
add(handler, trial, studiesDisease, diseases.get(contentRandom.nextInt(diseases.size())));
add(handler, trial, phase, VF.createLiteral(1 + contentRandom.nextInt(3)));
int armsPerTrial = jitterInt(jitterRandom, config.armsPerTrial);
for (int a = 0; a < armsPerTrial; a++) {
IRI arm = entity(PHARMA_NS, "arm", armIndex++);
add(handler, arm, RDF.TYPE, armType);
add(handler, trial, hasArm, arm);
IRI drug = drugs.get(contentRandom.nextInt(drugs.size()));
add(handler, arm, armDrug, drug);
add(handler, drug, testedIn, trial);
add(handler, arm, armComparator, comparators.get(contentRandom.nextInt(comparators.size())));
IRI result = entity(PHARMA_NS, "result", resultIndex++);
add(handler, result, RDF.TYPE, resultType);
add(handler, arm, hasResult, result);
add(handler, result, endpoint, literal(endpoints[contentRandom.nextInt(endpoints.length)]));
add(handler, result, effectSize, VF.createLiteral(contentRandom.nextDouble()));
add(handler, result, pValue, VF.createLiteral(contentRandom.nextDouble() * 0.1));
add(handler, result, responseRate, VF.createLiteral(contentRandom.nextDouble()));
add(handler, result, observedSideEffect, sideEffects.get(contentRandom.nextInt(sideEffects.size())));
IRI marker = biomarkers.get(contentRandom.nextInt(biomarkers.size()));
add(handler, result, biomarker, marker);
add(handler, result, biomarkerValue, VF.createLiteral(0.1 + contentRandom.nextDouble() * 2.0));
}
}
for (int c = 0; c < combinationCount; c++) {
IRI combination = entity(PHARMA_NS, "combination", c);
add(handler, combination, RDF.TYPE, combinationType);
add(handler, combination, hasName, literal("Combination " + c));
add(handler, combination, synergyScore, VF.createLiteral(contentRandom.nextDouble()));
int members = jitterInt(jitterRandom, config.drugsPerCombination);
for (int m = 0; m < members; m++) {
add(handler, combination, combinationOf, drugs.get(contentRandom.nextInt(drugs.size())));
}
if (!trials.isEmpty()) {
IRI trial = trials.get(contentRandom.nextInt(trials.size()));
add(handler, combination, testedIn, trial);
}
}
handler.endRDF();
}
private static Random jitterRandom(long seed) {
return new Random(seed ^ JITTER_SEED_XOR);
}
private static int jitterInt(Random random, int base) {
return jitterInt(random, base, 1);
}
private static int jitterInt(Random random, int base, int minValue) {
int delta = base / 2;
int min = Math.max(minValue, base - delta);
int max = Math.max(min, base + delta);
if (min == max) {
return min;
}
return min + random.nextInt(max - min + 1);
}
private static double jitterDouble(Random random, double base, double minValue, double maxValue) {
double delta = base * 0.5;
double min = Math.max(minValue, base - delta);
double max = Math.min(maxValue, base + delta);
if (max < min) {
double tmp = min;
min = max;
max = tmp;
}
if (max == min) {
return min;
}
return min + random.nextDouble() * (max - min);
}
private static int[] jitterCliqueSizes(Random random, int[] baseSizes, int maxTotal) {
Objects.requireNonNull(baseSizes, "baseSizes");
List<Integer> sizes = new ArrayList<>(baseSizes.length);
int remaining = maxTotal;
for (int base : baseSizes) {
if (remaining < 2) {
break;
}
int size = jitterInt(random, base, 2);
if (size > remaining) {
size = remaining;
}
if (size < 2) {
break;
}
sizes.add(size);
remaining -= size;
}
int[] result = new int[sizes.size()];
for (int i = 0; i < sizes.size(); i++) {
result[i] = sizes.get(i);
}
return result;
}
private static int substationIndex(IRI substation) {
String local = substation.getLocalName();
int slash = local.lastIndexOf('/');
String value = slash >= 0 ? local.substring(slash + 1) : local;
try {
return Integer.parseInt(value);
} catch (NumberFormatException e) {
return Math.abs(local.hashCode());
}
}
private static Model generateModel(Consumer<RDFHandler> generator) {
Model model = new LinkedHashModel();
StatementCollector collector = new StatementCollector(model);
generator.accept(collector);
return model;
}
private static IRI iri(String namespace, String localName) {
return VF.createIRI(namespace, localName);
}
private static IRI entity(String namespace, String category, int id) {
return VF.createIRI(namespace, category + "/" + id);
}
private static Literal literal(String value) {
return VF.createLiteral(value);
}
private static void add(RDFHandler handler, Resource subject, IRI predicate, Value object) {
handler.handleStatement(VF.createStatement(subject, predicate, object));
}
private static String randomWord(Random random) {
return WORDS[random.nextInt(WORDS.length)];
}
private static String randomSentence(Random random, int minWords, int maxWords) {
int total = minWords + random.nextInt(Math.max(1, maxWords - minWords + 1));
StringBuilder builder = new StringBuilder();
for (int i = 0; i < total; i++) {
if (i > 0) {
builder.append(' ');
}
builder.append(randomWord(random));
}
return builder.toString();
}
public static final class MedicalConfig {
private int patientCount = 10000;
private int encountersPerPatient = 3;
private int conditionsPerEncounter = 2;
private int medicationsPerPatient = 2;
private int observationsPerEncounter = 2;
private int practitionerCount = 10000;
private long seed = 42L;
public MedicalConfig withPatientCount(int patientCount) {
this.patientCount = requirePositive(patientCount, "patientCount");
return this;
}
public MedicalConfig withEncountersPerPatient(int encountersPerPatient) {
this.encountersPerPatient = requirePositive(encountersPerPatient, "encountersPerPatient");
return this;
}
public MedicalConfig withConditionsPerEncounter(int conditionsPerEncounter) {
this.conditionsPerEncounter = requirePositive(conditionsPerEncounter, "conditionsPerEncounter");
return this;
}
public MedicalConfig withMedicationsPerPatient(int medicationsPerPatient) {
this.medicationsPerPatient = requirePositive(medicationsPerPatient, "medicationsPerPatient");
return this;
}
public MedicalConfig withObservationsPerEncounter(int observationsPerEncounter) {
this.observationsPerEncounter = requirePositive(observationsPerEncounter, "observationsPerEncounter");
return this;
}
public MedicalConfig withPractitionerCount(int practitionerCount) {
this.practitionerCount = requirePositive(practitionerCount, "practitionerCount");
return this;
}
public MedicalConfig withSeed(long seed) {
this.seed = seed;
return this;
}
private void validate() {
requirePositive(patientCount, "patientCount");
requirePositive(encountersPerPatient, "encountersPerPatient");
requirePositive(conditionsPerEncounter, "conditionsPerEncounter");
requirePositive(medicationsPerPatient, "medicationsPerPatient");
requirePositive(observationsPerEncounter, "observationsPerEncounter");
requirePositive(practitionerCount, "practitionerCount");
}
}
public static final class SocialMediaConfig {
private int userCount = 20000;
private int postsPerUser = 15;
private int commentsPerPost = 5;
private int likesPerPost = 5;
private int followsPerUser = 9;
private int tagsPerPost = 4;
private int tagCount = 50;
private int[] cliqueSizes = new int[] { 3, 4, 5, 6 };
private long seed = 42L;
public SocialMediaConfig withUserCount(int userCount) {
this.userCount = requirePositive(userCount, "userCount");
return this;
}
public SocialMediaConfig withPostsPerUser(int postsPerUser) {
this.postsPerUser = requirePositive(postsPerUser, "postsPerUser");
return this;
}
public SocialMediaConfig withCommentsPerPost(int commentsPerPost) {
this.commentsPerPost = requirePositive(commentsPerPost, "commentsPerPost");
return this;
}
public SocialMediaConfig withLikesPerPost(int likesPerPost) {
this.likesPerPost = requirePositive(likesPerPost, "likesPerPost");
return this;
}
public SocialMediaConfig withFollowsPerUser(int followsPerUser) {
this.followsPerUser = requirePositive(followsPerUser, "followsPerUser");
return this;
}
public SocialMediaConfig withTagsPerPost(int tagsPerPost) {
this.tagsPerPost = requirePositive(tagsPerPost, "tagsPerPost");
return this;
}
public SocialMediaConfig withTagCount(int tagCount) {
this.tagCount = requirePositive(tagCount, "tagCount");
return this;
}
public SocialMediaConfig withCliqueSizes(int... cliqueSizes) {
Objects.requireNonNull(cliqueSizes, "cliqueSizes");
this.cliqueSizes = cliqueSizes.clone();
return this;
}
public SocialMediaConfig withSeed(long seed) {
this.seed = seed;
return this;
}
private void validate() {
requirePositive(userCount, "userCount");
requirePositive(postsPerUser, "postsPerUser");
requirePositive(commentsPerPost, "commentsPerPost");
requirePositive(likesPerPost, "likesPerPost");
requirePositive(followsPerUser, "followsPerUser");
requirePositive(tagsPerPost, "tagsPerPost");
requirePositive(tagCount, "tagCount");
Objects.requireNonNull(cliqueSizes, "cliqueSizes");
int cliqueTotal = 0;
for (int size : cliqueSizes) {
if (size < 2) {
throw new IllegalArgumentException("cliqueSizes entries must be >= 2");
}
cliqueTotal += size;
}
if (cliqueTotal > userCount) {
throw new IllegalArgumentException("cliqueSizes total exceeds userCount");
}
}
}
public static final class LibraryConfig {
private int bookCount = 100000;
private int authorCount = 30000;
private int branchCount = 5;
private int copiesPerBook = 3;
private int authorsPerBook = 2;
private int memberCount = 5000;
private int loansPerMember = 2;
private long seed = 42L;
public LibraryConfig withBookCount(int bookCount) {
this.bookCount = requirePositive(bookCount, "bookCount");
return this;
}
public LibraryConfig withAuthorCount(int authorCount) {
this.authorCount = requirePositive(authorCount, "authorCount");
return this;
}
public LibraryConfig withBranchCount(int branchCount) {
this.branchCount = requirePositive(branchCount, "branchCount");
return this;
}
public LibraryConfig withCopiesPerBook(int copiesPerBook) {
this.copiesPerBook = requirePositive(copiesPerBook, "copiesPerBook");
return this;
}
public LibraryConfig withAuthorsPerBook(int authorsPerBook) {
this.authorsPerBook = requirePositive(authorsPerBook, "authorsPerBook");
return this;
}
public LibraryConfig withMemberCount(int memberCount) {
this.memberCount = requirePositive(memberCount, "memberCount");
return this;
}
public LibraryConfig withLoansPerMember(int loansPerMember) {
this.loansPerMember = requirePositive(loansPerMember, "loansPerMember");
return this;
}
public LibraryConfig withSeed(long seed) {
this.seed = seed;
return this;
}
private void validate() {
requirePositive(bookCount, "bookCount");
requirePositive(authorCount, "authorCount");
requirePositive(branchCount, "branchCount");
requirePositive(copiesPerBook, "copiesPerBook");
requirePositive(authorsPerBook, "authorsPerBook");
requirePositive(memberCount, "memberCount");
requirePositive(loansPerMember, "loansPerMember");
}
}
public static final class EngineeringConfig {
private int componentCount = 120000;
private int assemblyCount = 1500;
private int requirementCount = 400;
private int testsPerRequirement = 3;
private long seed = 42L;
public EngineeringConfig withComponentCount(int componentCount) {
this.componentCount = requirePositive(componentCount, "componentCount");
return this;
}
public EngineeringConfig withAssemblyCount(int assemblyCount) {
this.assemblyCount = requirePositive(assemblyCount, "assemblyCount");
return this;
}
public EngineeringConfig withRequirementCount(int requirementCount) {
this.requirementCount = requirePositive(requirementCount, "requirementCount");
return this;
}
public EngineeringConfig withTestsPerRequirement(int testsPerRequirement) {
this.testsPerRequirement = requirePositive(testsPerRequirement, "testsPerRequirement");
return this;
}
public EngineeringConfig withSeed(long seed) {
this.seed = seed;
return this;
}
private void validate() {
requirePositive(componentCount, "componentCount");
requirePositive(assemblyCount, "assemblyCount");
requirePositive(requirementCount, "requirementCount");
requirePositive(testsPerRequirement, "testsPerRequirement");
}
}
public static final class HighlyConnectedConfig {
private int nodeCount = 30000;
private int hubCount = 10;
private int edgesPerNode = 8;
private double hubBias = 0.6;
private long seed = 42L;
public HighlyConnectedConfig withNodeCount(int nodeCount) {
this.nodeCount = requirePositive(nodeCount, "nodeCount");
return this;
}
public HighlyConnectedConfig withHubCount(int hubCount) {
this.hubCount = requirePositive(hubCount, "hubCount");
return this;
}
public HighlyConnectedConfig withEdgesPerNode(int edgesPerNode) {
this.edgesPerNode = requirePositive(edgesPerNode, "edgesPerNode");
return this;
}
public HighlyConnectedConfig withHubBias(double hubBias) {
if (hubBias < 0.0 || hubBias > 1.0) {
throw new IllegalArgumentException("hubBias must be between 0 and 1");
}
this.hubBias = hubBias;
return this;
}
public HighlyConnectedConfig withSeed(long seed) {
this.seed = seed;
return this;
}
private void validate() {
requirePositive(nodeCount, "nodeCount");
requirePositive(hubCount, "hubCount");
requirePositive(edgesPerNode, "edgesPerNode");
if (hubBias < 0.0 || hubBias > 1.0) {
throw new IllegalArgumentException("hubBias must be between 0 and 1");
}
}
}
public static final class TrainConfig {
private int stationCount = 40000;
private int routeCount = 6000;
private int stopsPerRoute = 8;
private int trainCount = 12000;
private int tripsPerTrain = 3;
private long seed = 42L;
public TrainConfig withStationCount(int stationCount) {
this.stationCount = requirePositive(stationCount, "stationCount");
return this;
}
public TrainConfig withRouteCount(int routeCount) {
this.routeCount = requirePositive(routeCount, "routeCount");
return this;
}
public TrainConfig withStopsPerRoute(int stopsPerRoute) {
this.stopsPerRoute = requirePositive(stopsPerRoute, "stopsPerRoute");
return this;
}
public TrainConfig withTrainCount(int trainCount) {
this.trainCount = requirePositive(trainCount, "trainCount");
return this;
}
public TrainConfig withTripsPerTrain(int tripsPerTrain) {
this.tripsPerTrain = requirePositive(tripsPerTrain, "tripsPerTrain");
return this;
}
public TrainConfig withSeed(long seed) {
this.seed = seed;
return this;
}
private void validate() {
requirePositive(stationCount, "stationCount");
requirePositive(routeCount, "routeCount");
requirePositive(stopsPerRoute, "stopsPerRoute");
requirePositive(trainCount, "trainCount");
requirePositive(tripsPerTrain, "tripsPerTrain");
}
}
public static final class ElectricalGridConfig {
private int substationCount = 12000;
private int transformersPerSubstation = 3;
private int linesPerSubstation = 2;
private int metersPerTransformer = 4;
private long seed = 42L;
public ElectricalGridConfig withSubstationCount(int substationCount) {
this.substationCount = requirePositive(substationCount, "substationCount");
return this;
}
public ElectricalGridConfig withTransformersPerSubstation(int transformersPerSubstation) {
this.transformersPerSubstation = requirePositive(transformersPerSubstation, "transformersPerSubstation");
return this;
}
public ElectricalGridConfig withLinesPerSubstation(int linesPerSubstation) {
this.linesPerSubstation = requirePositive(linesPerSubstation, "linesPerSubstation");
return this;
}
public ElectricalGridConfig withMetersPerTransformer(int metersPerTransformer) {
this.metersPerTransformer = requirePositive(metersPerTransformer, "metersPerTransformer");
return this;
}
public ElectricalGridConfig withSeed(long seed) {
this.seed = seed;
return this;
}
private void validate() {
requirePositive(substationCount, "substationCount");
requirePositive(transformersPerSubstation, "transformersPerSubstation");
requirePositive(linesPerSubstation, "linesPerSubstation");
requirePositive(metersPerTransformer, "metersPerTransformer");
}
}
public static final class PharmaConfig {
private int drugCount = 5000;
private int moleculeCount = 7500;
private int chemicalClassCount = 200;
private int targetCount = 600;
private int pathwayCount = 150;
private int diseaseCount = 400;
private int trialCount = 1200;
private int armsPerTrial = 3;
private int sideEffectCount = 250;
private int sideEffectsPerDrug = 2;
private int biomarkerCount = 150;
private int combinationCount = 600;
private int moleculesPerDrug = 2;
private int targetsPerDrug = 2;
private int targetsPerMolecule = 2;
private int indicationsPerDrug = 2;
private int drugsPerCombination = 2;
private int comparatorCount = 12;
private long seed = 42L;
public PharmaConfig withDrugCount(int drugCount) {
this.drugCount = requirePositive(drugCount, "drugCount");
return this;
}
public PharmaConfig withMoleculeCount(int moleculeCount) {
this.moleculeCount = requirePositive(moleculeCount, "moleculeCount");
return this;
}
public PharmaConfig withChemicalClassCount(int chemicalClassCount) {
this.chemicalClassCount = requirePositive(chemicalClassCount, "chemicalClassCount");
return this;
}
public PharmaConfig withTargetCount(int targetCount) {
this.targetCount = requirePositive(targetCount, "targetCount");
return this;
}
public PharmaConfig withPathwayCount(int pathwayCount) {
this.pathwayCount = requirePositive(pathwayCount, "pathwayCount");
return this;
}
public PharmaConfig withDiseaseCount(int diseaseCount) {
this.diseaseCount = requirePositive(diseaseCount, "diseaseCount");
return this;
}
public PharmaConfig withTrialCount(int trialCount) {
this.trialCount = requirePositive(trialCount, "trialCount");
return this;
}
public PharmaConfig withArmsPerTrial(int armsPerTrial) {
this.armsPerTrial = requirePositive(armsPerTrial, "armsPerTrial");
return this;
}
public PharmaConfig withSideEffectCount(int sideEffectCount) {
this.sideEffectCount = requirePositive(sideEffectCount, "sideEffectCount");
return this;
}
public PharmaConfig withSideEffectsPerDrug(int sideEffectsPerDrug) {
this.sideEffectsPerDrug = requirePositive(sideEffectsPerDrug, "sideEffectsPerDrug");
return this;
}
public PharmaConfig withBiomarkerCount(int biomarkerCount) {
this.biomarkerCount = requirePositive(biomarkerCount, "biomarkerCount");
return this;
}
public PharmaConfig withCombinationCount(int combinationCount) {
this.combinationCount = requirePositive(combinationCount, "combinationCount");
return this;
}
public PharmaConfig withMoleculesPerDrug(int moleculesPerDrug) {
this.moleculesPerDrug = requirePositive(moleculesPerDrug, "moleculesPerDrug");
return this;
}
public PharmaConfig withTargetsPerDrug(int targetsPerDrug) {
this.targetsPerDrug = requirePositive(targetsPerDrug, "targetsPerDrug");
return this;
}
public PharmaConfig withTargetsPerMolecule(int targetsPerMolecule) {
this.targetsPerMolecule = requirePositive(targetsPerMolecule, "targetsPerMolecule");
return this;
}
public PharmaConfig withIndicationsPerDrug(int indicationsPerDrug) {
this.indicationsPerDrug = requirePositive(indicationsPerDrug, "indicationsPerDrug");
return this;
}
public PharmaConfig withDrugsPerCombination(int drugsPerCombination) {
this.drugsPerCombination = requirePositive(drugsPerCombination, "drugsPerCombination");
return this;
}
public PharmaConfig withComparatorCount(int comparatorCount) {
this.comparatorCount = requirePositive(comparatorCount, "comparatorCount");
return this;
}
public PharmaConfig withSeed(long seed) {
this.seed = seed;
return this;
}
private void validate() {
requirePositive(drugCount, "drugCount");
requirePositive(moleculeCount, "moleculeCount");
requirePositive(chemicalClassCount, "chemicalClassCount");
requirePositive(targetCount, "targetCount");
requirePositive(pathwayCount, "pathwayCount");
requirePositive(diseaseCount, "diseaseCount");
requirePositive(trialCount, "trialCount");
requirePositive(armsPerTrial, "armsPerTrial");
requirePositive(sideEffectCount, "sideEffectCount");
requirePositive(sideEffectsPerDrug, "sideEffectsPerDrug");
requirePositive(biomarkerCount, "biomarkerCount");
requirePositive(combinationCount, "combinationCount");
requirePositive(moleculesPerDrug, "moleculesPerDrug");
requirePositive(targetsPerDrug, "targetsPerDrug");
requirePositive(targetsPerMolecule, "targetsPerMolecule");
requirePositive(indicationsPerDrug, "indicationsPerDrug");
requirePositive(drugsPerCombination, "drugsPerCombination");
requirePositive(comparatorCount, "comparatorCount");
}
}
private static int requirePositive(int value, String name) {
if (value <= 0) {
throw new IllegalArgumentException(name + " must be > 0");
}
return value;
}
}