Overview
The Graphs module provides graph-based algorithms and data structures for:- Cycle detection in resource dependencies
- Batch reservation with conflict resolution
- Influence zone analysis
- Process scheduling with dependencies
- User journey modeling
- Concurrency analysis
Module Structure
Graph Math Foundation
Core graph data structures:Graph
Graph Class
public class Graph<T, P> {
private final Map<Node<T>, List<Edge<T, P>>> adjacencyMatrix;
public Graph<T, P> addEdge(Edge<T, P> edge);
public Optional<Path<T, P>> findFirstCycle();
public boolean hasEdge(Node<T> from, Node<T> to);
public <P2> Graph<T, P> intersection(Graph<T, P2> other);
public void removeEdge(Edge<T, P> edge);
}
Node, Edge, Path
Graph Elements
public record Node<T>(T value) {
public static <T> Node<T> of(T value) {
return new Node<>(value);
}
}
public record Edge<T, P>(
Node<T> from,
Node<T> to,
P properties
) {
public static <T, P> Edge<T, P> between(
Node<T> from,
Node<T> to,
P properties
) {
return new Edge<>(from, to, properties);
}
}
public record Path<T, P>(
List<Edge<T, P>> edges
) {
public List<Node<T>> nodes() {
if (edges.isEmpty()) {
return List.of();
}
List<Node<T>> result = new ArrayList<>();
result.add(edges.get(0).from());
edges.forEach(edge -> result.add(edge.to()));
return result;
}
}
The Graph implementation is currently AI-generated and marked TODO for replacement with a proper graph library.
Cycles: Resource Reservation
Detect and resolve circular dependencies in resource reservations.Slot and Reservation
Slot
public class Slot {
private final SlotId id;
private final LocalDateTime start;
private final LocalDateTime end;
private final Set<Eligibility> eligibilities;
private Optional<OwnerId> currentOwner;
public boolean isAvailableFor(OwnerId owner) {
if (currentOwner.isPresent()) {
return false;
}
return eligibilities.stream()
.anyMatch(e -> e.allows(owner));
}
public Result<String, Void> reserve(OwnerId owner) {
if (!isAvailableFor(owner)) {
return Result.failure("Slot not available");
}
currentOwner = Optional.of(owner);
return Result.success(null);
}
}
public record Eligibility(
Set<OwnerId> allowedOwners
) {
public boolean allows(OwnerId owner) {
return allowedOwners.isEmpty()
|| allowedOwners.contains(owner);
}
}
Batch Reservation
Reserve multiple slots while detecting circular dependencies:BatchReservationUseCase
public class BatchReservationUseCase {
private final SlotRepository slotRepository;
public BatchReservationResult execute(
List<ReservationChangeRequest> requests
) {
// 1. Build dependency graph
Graph<SlotId, ReservationChangeRequest> graph =
buildDependencyGraph(requests);
// 2. Check for cycles
Optional<Path<SlotId, ReservationChangeRequest>> cycle =
graph.findFirstCycle();
if (cycle.isPresent()) {
return BatchReservationResult.failure(
"Circular dependency detected: " +
formatCycle(cycle.get())
);
}
// 3. Process reservations in topological order
List<SlotId> processed = new ArrayList<>();
for (ReservationChangeRequest request : requests) {
Result<String, Void> result =
processRequest(request);
if (result.failure()) {
// Rollback
rollback(processed);
return BatchReservationResult.failure(
result.getFailure()
);
}
processed.add(request.slotId());
}
return BatchReservationResult.success(processed);
}
}
// Reservation request
public record ReservationChangeRequest(
SlotId slotId,
OwnerId newOwner,
Optional<OwnerId> previousOwner
) {}
// Result
public record BatchReservationResult(
boolean success,
List<SlotId> processedSlots,
Optional<String> error
) {
static BatchReservationResult success(List<SlotId> slots);
static BatchReservationResult failure(String error);
}
Usage Example
Batch Reservation
// Create slots
Slot slot1 = new Slot(
SlotId.of("SLOT-1"),
LocalDateTime.of(2024, 3, 15, 10, 0),
LocalDateTime.of(2024, 3, 15, 11, 0),
Set.of(Eligibility.allowAll())
);
Slot slot2 = new Slot(
SlotId.of("SLOT-2"),
LocalDateTime.of(2024, 3, 15, 11, 0),
LocalDateTime.of(2024, 3, 15, 12, 0),
Set.of(Eligibility.allowAll())
);
// Attempt batch reservation
List<ReservationChangeRequest> requests = List.of(
new ReservationChangeRequest(
SlotId.of("SLOT-1"),
OwnerId.of("USER-A"),
Optional.empty()
),
new ReservationChangeRequest(
SlotId.of("SLOT-2"),
OwnerId.of("USER-A"),
Optional.empty()
)
);
BatchReservationResult result =
batchReservationUseCase.execute(requests);
if (result.success()) {
// All slots reserved
} else {
// Conflict or cycle detected
System.out.println(result.error().get());
}
Influence: Zone Analysis
Model influence zones and their interactions in physical/logical spaces.Influence Concepts
Influence Zone
public class InfluenceZone {
private final InfluenceUnit source;
private final Set<InfluenceUnit> affected;
private final double radius;
public boolean affects(InfluenceUnit unit) {
return affected.contains(unit);
}
public Set<InfluenceUnit> getAffectedUnits() {
return Set.copyOf(affected);
}
}
public interface InfluenceUnit {
String id();
Position position();
}
// Example: Laboratory equipment
public record Laboratory(
String id,
Position position,
EquipmentType type
) implements InfluenceUnit {}
Influence Map
InfluenceMap
public class InfluenceMap {
private final Map<InfluenceUnit, InfluenceZone> zones;
public void addZone(InfluenceZone zone) {
zones.put(zone.source(), zone);
}
public Set<InfluenceUnit> findConflicts(
InfluenceUnit unit
) {
return zones.values().stream()
.filter(zone -> zone.affects(unit))
.map(InfluenceZone::source)
.collect(Collectors.toSet());
}
public Set<Reservation> findBridgingReservations(
Reservation newReservation
) {
// Find reservations that would create
// influence conflicts
return existingReservations.stream()
.filter(existing ->
wouldConflict(existing, newReservation))
.collect(Collectors.toSet());
}
}
Physics and Infrastructure Influence
Influence Types
// Physics-based influence
public class PhysicsInfluence implements InfluenceZone {
private final PhysicsProcess process;
private final double temperature;
private final double vibrationLevel;
public boolean interferesWith(PhysicsProcess other) {
// Check if processes interfere
return temperature > other.maxTemperature()
|| vibrationLevel > other.maxVibration();
}
}
// Infrastructure influence
public class InfrastructureInfluence implements InfluenceZone {
private final Set<Laboratory> laboratories;
private final LaboratoryAdjacency adjacency;
public boolean canCoexist(Laboratory lab) {
return laboratories.stream()
.noneMatch(existing ->
adjacency.forbids(existing, lab));
}
}
Influence Analyzer
InfluenceAnalyzer
public class InfluanceAnalyzer {
public AnalysisResult analyze(
InfluenceMap map,
List<Reservation> plannedReservations
) {
List<Conflict> conflicts = new ArrayList<>();
for (Reservation reservation : plannedReservations) {
Set<InfluenceUnit> conflicting =
map.findConflicts(reservation.unit());
if (!conflicting.isEmpty()) {
conflicts.add(new Conflict(
reservation,
conflicting
));
}
}
return new AnalysisResult(conflicts);
}
}
Scheduling: Process Dependencies
Schedule processes with dependencies and concurrency constraints.Process and Steps
Process Structure
public class Process {
private final ProcessId id;
private final List<ProcessStep> steps;
private final Map<ProcessStep, Set<ProcessStep>> dependencies;
public List<ProcessStep> getReadySteps(
Set<ProcessStep> completed
) {
return steps.stream()
.filter(step -> !completed.contains(step))
.filter(step -> {
Set<ProcessStep> deps =
dependencies.getOrDefault(step, Set.of());
return completed.containsAll(deps);
})
.toList();
}
}
public record ProcessStep(
String id,
Duration estimatedDuration,
Set<ResourceRequirement> requiredResources
) {}
public enum DependencyType {
FINISH_TO_START, // B starts after A finishes
START_TO_START, // B starts when A starts
FINISH_TO_FINISH, // B finishes when A finishes
START_TO_FINISH // B finishes when A starts
}
Schedule
Schedule
public class Schedule {
private final Map<ProcessStep, Instant> startTimes;
private final Map<ProcessStep, Instant> endTimes;
public void scheduleStep(
ProcessStep step,
Instant start
) {
startTimes.put(step, start);
endTimes.put(
step,
start.plus(step.estimatedDuration())
);
}
public boolean hasOverlap(
ProcessStep step1,
ProcessStep step2
) {
Instant start1 = startTimes.get(step1);
Instant end1 = endTimes.get(step1);
Instant start2 = startTimes.get(step2);
Instant end2 = endTimes.get(step2);
return start1.isBefore(end2) && start2.isBefore(end1);
}
public Duration totalDuration() {
if (endTimes.isEmpty()) {
return Duration.ZERO;
}
Instant earliest = startTimes.values().stream()
.min(Instant::compareTo)
.orElseThrow();
Instant latest = endTimes.values().stream()
.max(Instant::compareTo)
.orElseThrow();
return Duration.between(earliest, latest);
}
}
Concurrency Analysis
Concurrency
public class Concurrency {
public static int maxConcurrentSteps(
Schedule schedule
) {
// Find maximum number of overlapping steps
List<Instant> events = new ArrayList<>();
schedule.startTimes().forEach((step, time) -> {
events.add(time); // +1
});
schedule.endTimes().forEach((step, time) -> {
events.add(time); // -1
});
events.sort(Instant::compareTo);
int max = 0;
int current = 0;
for (Instant event : events) {
if (isStart(event, schedule)) {
current++;
max = Math.max(max, current);
} else {
current--;
}
}
return max;
}
}
// Execution environments
public record ExecutionEnvironments(
Map<String, Integer> capacities
) {
public boolean canHandle(
int concurrentProcesses,
String environmentType
) {
return capacities.getOrDefault(environmentType, 0)
>= concurrentProcesses;
}
}
User Journey
Model user flows and state transitions.Condition-based Flow
User Journey
public class UserJourney {
private final Map<State, List<Transition>> transitions;
public record State(String id, String description) {}
public record Transition(
State from,
State to,
Condition condition,
Action action
) {}
public interface Condition {
boolean isMet(UserContext context);
}
public interface Action {
void execute(UserContext context);
}
public List<State> possibleNextStates(
State current,
UserContext context
) {
return transitions.getOrDefault(current, List.of())
.stream()
.filter(t -> t.condition().isMet(context))
.map(Transition::to)
.toList();
}
}
Example: Checkout Flow
Checkout Journey
UserJourney checkout = new UserJourney();
State cart = new State("cart", "Shopping Cart");
State shipping = new State("shipping", "Shipping Info");
State payment = new State("payment", "Payment");
State confirmation = new State("confirmation", "Order Confirmed");
// Cart -> Shipping (if items in cart)
checkout.addTransition(new Transition(
cart,
shipping,
ctx -> !ctx.cart().isEmpty(),
ctx -> ctx.saveCart()
));
// Shipping -> Payment (if address valid)
checkout.addTransition(new Transition(
shipping,
payment,
ctx -> ctx.shippingAddress().isValid(),
ctx -> ctx.calculateShipping()
));
// Payment -> Confirmation (if payment successful)
checkout.addTransition(new Transition(
payment,
confirmation,
ctx -> ctx.payment().isSuccessful(),
ctx -> ctx.createOrder()
));
Real-World Example: Laboratory Scheduling
Laboratory Scheduling
// 1. Define laboratories with positions
Laboratory cleanRoom = new Laboratory(
"LAB-CLEAN-01",
Position.of(0, 0),
EquipmentType.CLEAN_ROOM
);
Laboratory chemLab = new Laboratory(
"LAB-CHEM-01",
Position.of(0, 10), // 10 meters away
EquipmentType.CHEMISTRY
);
// 2. Define influence zones
InfluenceZone cleanRoomZone = new InfluenceZone(
cleanRoom,
Set.of(chemLab), // Chemistry lab affects clean room
20.0 // 20 meter radius
);
InfluenceMap map = new InfluenceMap();
map.addZone(cleanRoomZone);
// 3. Plan reservations
Reservation cleanRoomReservation = new Reservation(
cleanRoom,
LocalDateTime.of(2024, 3, 15, 10, 0),
LocalDateTime.of(2024, 3, 15, 12, 0),
OwnerId.of("RESEARCHER-A")
);
Reservation chemLabReservation = new Reservation(
chemLab,
LocalDateTime.of(2024, 3, 15, 10, 30),
LocalDateTime.of(2024, 3, 15, 11, 30),
OwnerId.of("RESEARCHER-B")
);
// 4. Check for conflicts
Set<Reservation> conflicts =
map.findBridgingReservations(chemLabReservation);
if (!conflicts.isEmpty()) {
// Reschedule chemistry lab work
chemLabReservation = chemLabReservation.reschedule(
LocalDateTime.of(2024, 3, 15, 13, 0),
LocalDateTime.of(2024, 3, 15, 14, 0)
);
}
Best Practices
Detect Cycles
Always check for circular dependencies before committing
Topological Sort
Process dependencies in correct order
Rollback Ready
Design operations to be reversible
Test Concurrency
Verify concurrent execution limits
