org.optaplanner.examples.machinereassignment.persistence.MachineReassignmentImporter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of optaplanner-examples Show documentation
Show all versions of optaplanner-examples Show documentation
OptaPlanner solves planning problems.
This lightweight, embeddable planning engine implements powerful and scalable algorithms
to optimize business resource scheduling and planning.
This module contains the examples which demonstrate how to use it in a normal Java application.
package org.optaplanner.examples.machinereassignment.persistence;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.optaplanner.examples.common.persistence.AbstractTxtSolutionImporter;
import org.optaplanner.examples.common.persistence.SolutionConverter;
import org.optaplanner.examples.machinereassignment.app.MachineReassignmentApp;
import org.optaplanner.examples.machinereassignment.domain.MachineReassignment;
import org.optaplanner.examples.machinereassignment.domain.MrBalancePenalty;
import org.optaplanner.examples.machinereassignment.domain.MrGlobalPenaltyInfo;
import org.optaplanner.examples.machinereassignment.domain.MrLocation;
import org.optaplanner.examples.machinereassignment.domain.MrMachine;
import org.optaplanner.examples.machinereassignment.domain.MrMachineCapacity;
import org.optaplanner.examples.machinereassignment.domain.MrNeighborhood;
import org.optaplanner.examples.machinereassignment.domain.MrProcess;
import org.optaplanner.examples.machinereassignment.domain.MrProcessAssignment;
import org.optaplanner.examples.machinereassignment.domain.MrProcessRequirement;
import org.optaplanner.examples.machinereassignment.domain.MrResource;
import org.optaplanner.examples.machinereassignment.domain.MrService;
public class MachineReassignmentImporter extends AbstractTxtSolutionImporter {
public static void main(String[] args) {
SolutionConverter converter =
SolutionConverter.createImportConverter(MachineReassignmentApp.DATA_DIR_NAME, new MachineReassignmentImporter(),
new MachineReassignmentSolutionFileIO());
converter.convert("model_a1_1.txt");
converter.convert("model_a1_2.txt");
converter.convert("model_a1_3.txt");
converter.convert("model_a1_4.txt");
converter.convert("model_a1_5.txt");
converter.convert("model_a2_1.txt");
converter.convert("model_a2_2.txt");
converter.convert("model_a2_3.txt");
converter.convert("model_a2_4.txt");
converter.convert("model_a2_5.txt");
// model_b's are too big to write as XML
}
@Override
public String getInputFileSuffix() {
return "txt";
}
@Override
public TxtInputBuilder createTxtInputBuilder() {
return new MachineReassignmentInputBuilder();
}
public static class MachineReassignmentInputBuilder extends TxtInputBuilder {
private MachineReassignment machineReassignment;
private int resourceListSize;
private List resourceList;
private List serviceList;
private List machineList;
private int processListSize;
private List processList;
@Override
public MachineReassignment readSolution() throws IOException {
machineReassignment = new MachineReassignment(0L);
readResourceList();
readMachineList();
readServiceList();
readProcessList();
readBalancePenaltyList();
readGlobalPenaltyInfo();
readProcessAssignmentList();
BigInteger possibleSolutionSize = BigInteger.valueOf(machineReassignment.getMachineList().size()).pow(
machineReassignment.getProcessList().size());
logger.info("MachineReassignment {} has {} resources, {} neighborhoods, {} locations, {} machines," +
" {} services, {} processes and {} balancePenalties with a search space of {}.",
getInputId(),
machineReassignment.getResourceList().size(),
machineReassignment.getNeighborhoodList().size(),
machineReassignment.getLocationList().size(),
machineReassignment.getMachineList().size(),
machineReassignment.getServiceList().size(),
machineReassignment.getProcessList().size(),
machineReassignment.getBalancePenaltyList().size(),
getFlooredPossibleSolutionSize(possibleSolutionSize));
return machineReassignment;
}
private void readResourceList() throws IOException {
resourceListSize = readIntegerValue();
resourceList = new ArrayList<>(resourceListSize);
long resourceId = 0L;
for (int i = 0; i < resourceListSize; i++) {
String line = readStringValue();
String[] lineTokens = splitBySpace(line, 2);
boolean transientlyConsumed = parseBooleanFromNumber(lineTokens[0]);
int loadCostWeight = Integer.parseInt(lineTokens[1]);
MrResource resource = new MrResource(resourceId, i, transientlyConsumed, loadCostWeight);
resourceList.add(resource);
resourceId++;
}
machineReassignment.setResourceList(resourceList);
}
private void readMachineList() throws IOException {
int machineListSize = readIntegerValue();
List neighborhoodList = new ArrayList<>(machineListSize);
Map idToNeighborhoodMap = new LinkedHashMap<>(machineListSize);
List locationList = new ArrayList<>(machineListSize);
Map idToLocationMap = new LinkedHashMap<>(machineListSize);
machineList = new ArrayList<>(machineListSize);
long machineId = 0L;
List machineCapacityList = new ArrayList<>(machineListSize * resourceListSize);
long machineCapacityId = 0L;
// 2 phases because service dependencies are not in low to high order
for (int i = 0; i < machineListSize; i++) {
MrMachine machine = new MrMachine(machineId);
machineList.add(machine);
machineId++;
}
for (int i = 0; i < machineListSize; i++) {
MrMachine machine = machineList.get(i);
String line = readStringValue();
int moveCostOffset = 2 + (resourceListSize * 2);
String[] lineTokens = splitBySpace(line, moveCostOffset + machineListSize);
long neighborhoodId = Long.parseLong(lineTokens[0]);
MrNeighborhood neighborhood = idToNeighborhoodMap.get(neighborhoodId);
if (neighborhood == null) {
neighborhood = new MrNeighborhood(neighborhoodId);
neighborhoodList.add(neighborhood);
idToNeighborhoodMap.put(neighborhoodId, neighborhood);
}
machine.setNeighborhood(neighborhood);
long locationId = Long.parseLong(lineTokens[1]);
MrLocation location = idToLocationMap.get(locationId);
if (location == null) {
location = new MrLocation(locationId);
locationList.add(location);
idToLocationMap.put(locationId, location);
}
machine.setLocation(location);
List machineCapacityListOfMachine = new ArrayList<>(resourceListSize);
for (int j = 0; j < resourceListSize; j++) {
long maximumCapacity = Long.parseLong(lineTokens[2 + j]);
long safetyCapacity = Long.parseLong(lineTokens[2 + resourceListSize + j]);
MrMachineCapacity machineCapacity = new MrMachineCapacity(machineCapacityId, machine,
resourceList.get(j), maximumCapacity, safetyCapacity);
machineCapacityList.add(machineCapacity);
machineCapacityListOfMachine.add(machineCapacity);
machineCapacityId++;
}
machine.setMachineCapacityList(machineCapacityListOfMachine);
Map machineMoveCostMap = new LinkedHashMap<>(machineListSize);
for (int j = 0; j < machineListSize; j++) {
MrMachine toMachine = machineList.get(j);
int moveCost = Integer.parseInt(lineTokens[moveCostOffset + j]);
machineMoveCostMap.put(toMachine, moveCost);
}
machine.setMachineMoveCostMap(machineMoveCostMap);
}
machineReassignment.setNeighborhoodList(neighborhoodList);
machineReassignment.setLocationList(locationList);
machineReassignment.setMachineList(machineList);
machineReassignment.setMachineCapacityList(machineCapacityList);
}
private void readServiceList() throws IOException {
int serviceListSize = readIntegerValue();
serviceList = new ArrayList<>(serviceListSize);
long serviceId = 0L;
// 2 phases because service dependencies are not in low to high order
for (int i = 0; i < serviceListSize; i++) {
MrService service = new MrService(serviceId);
service.setFromDependencyServiceList(new ArrayList<>(5));
serviceList.add(service);
serviceId++;
}
for (int i = 0; i < serviceListSize; i++) {
MrService service = serviceList.get(i);
String line = readStringValue();
String[] lineTokens = splitBySpace(line);
service.setLocationSpread(Integer.parseInt(lineTokens[0]));
int serviceDependencyListSize = Integer.parseInt(lineTokens[1]);
List toDependencyServiceList = new ArrayList<>(serviceDependencyListSize);
for (int j = 0; j < serviceDependencyListSize; j++) {
int toServiceIndex = Integer.parseInt(lineTokens[2 + j]);
if (toServiceIndex >= serviceList.size()) {
throw new IllegalArgumentException("Service with id (" + serviceId
+ ") has a non existing toServiceIndex (" + toServiceIndex + ").");
}
MrService toService = serviceList.get(toServiceIndex);
if (toService.equals(service)) {
throw new IllegalStateException("The toService (" + toService
+ ") cannot be equal to the service (" + service + ").");
}
toDependencyServiceList.add(toService);
toService.getFromDependencyServiceList().add(service);
}
service.setToDependencyServiceList(toDependencyServiceList);
int numberOfTokens = 2 + serviceDependencyListSize;
if (lineTokens.length != numberOfTokens) {
throw new IllegalArgumentException("Read line (" + line + ") has " + lineTokens.length
+ " tokens but is expected to contain " + numberOfTokens + " tokens separated by space.");
}
}
machineReassignment.setServiceList(serviceList);
}
private void readProcessList() throws IOException {
processListSize = readIntegerValue();
processList = new ArrayList<>(processListSize);
long processId = 0L;
long processRequirementId = 0L;
for (int i = 0; i < processListSize; i++) {
String line = readStringValue();
String[] lineTokens = splitBySpace(line, 2 + resourceListSize);
int serviceIndex = Integer.parseInt(lineTokens[0]);
if (serviceIndex >= serviceList.size()) {
throw new IllegalArgumentException("Process with id (" + processId
+ ") has a non existing serviceIndex (" + serviceIndex + ").");
}
MrService service = serviceList.get(serviceIndex);
int moveCost = Integer.parseInt(lineTokens[1 + resourceListSize]);
MrProcess process = new MrProcess(processId, service, moveCost);
List processRequirementList = new ArrayList<>(resourceListSize);
for (int j = 0; j < resourceListSize; j++) {
MrResource resource = resourceList.get(j);
int usage = Integer.parseInt(lineTokens[1 + j]);
MrProcessRequirement processRequirement = new MrProcessRequirement(processRequirementId, process,
resource, usage);
processRequirementList.add(processRequirement);
processRequirementId++;
}
process.setProcessRequirementList(processRequirementList);
processList.add(process);
processId++;
}
machineReassignment.setProcessList(processList);
}
private void readBalancePenaltyList() throws IOException {
int balancePenaltyListSize = readIntegerValue();
List balancePenaltyList = new ArrayList<>(balancePenaltyListSize);
long balancePenaltyId = 0L;
for (int i = 0; i < balancePenaltyListSize; i++) {
String line = readStringValue();
String[] lineTokens = splitBySpace(line, 3);
int originResourceIndex = Integer.parseInt(lineTokens[0]);
if (originResourceIndex >= resourceListSize) {
throw new IllegalArgumentException("BalancePenalty with id (" + balancePenaltyId
+ ") has a non existing originResourceIndex (" + originResourceIndex + ").");
}
MrResource originResource = resourceList.get(originResourceIndex);
int targetResourceIndex = Integer.parseInt(lineTokens[1]);
if (targetResourceIndex >= resourceListSize) {
throw new IllegalArgumentException("BalancePenalty with id (" + balancePenaltyId
+ ") has a non existing targetResourceIndex (" + targetResourceIndex + ").");
}
MrResource targetResource = resourceList.get(targetResourceIndex);
int multiplicand = Integer.parseInt(lineTokens[2]);
// Read a new line (weird in the input definition)
int weight = readIntegerValue();
MrBalancePenalty balancePenalty = new MrBalancePenalty(balancePenaltyId, originResource, targetResource,
multiplicand, weight);
balancePenaltyList.add(balancePenalty);
balancePenaltyId++;
}
machineReassignment.setBalancePenaltyList(balancePenaltyList);
}
private void readGlobalPenaltyInfo() throws IOException {
String line = readStringValue();
String[] lineTokens = splitBySpace(line, 3);
int processMoveCostWeight = Integer.parseInt(lineTokens[0]);
int serviceMoveCostWeight = Integer.parseInt(lineTokens[1]);
int machineMoveCostWeight = Integer.parseInt(lineTokens[2]);
MrGlobalPenaltyInfo globalPenaltyInfo = new MrGlobalPenaltyInfo(0L, processMoveCostWeight,
serviceMoveCostWeight, machineMoveCostWeight);
machineReassignment.setGlobalPenaltyInfo(globalPenaltyInfo);
}
private void readProcessAssignmentList() {
String line = readOriginalProcessAssignmentLine();
String[] lineTokens = splitBySpace(line, processListSize);
List processAssignmentList = new ArrayList<>(processListSize);
long processAssignmentId = 0L;
for (int i = 0; i < processListSize; i++) {
int machineIndex = Integer.parseInt(lineTokens[i]);
if (machineIndex >= machineList.size()) {
throw new IllegalArgumentException("ProcessAssignment with id (" + processAssignmentId
+ ") has a non existing machineIndex (" + machineIndex + ").");
}
MrProcessAssignment processAssignment = MrProcessAssignment.withOriginalMachine(processAssignmentId,
processList.get(i), machineList.get(machineIndex));
processAssignmentList.add(processAssignment);
processAssignmentId++;
}
machineReassignment.setProcessAssignmentList(processAssignmentList);
}
private String readOriginalProcessAssignmentLine() {
String inputFileName = inputFile.getName();
String inputFilePrefix = "model_";
if (!inputFileName.startsWith(inputFilePrefix)) {
throw new IllegalArgumentException("The inputFile (" + inputFile
+ ") is expected to start with \"" + inputFilePrefix + "\".");
}
File assignmentInputFile = new File(inputFile.getParent(),
inputFileName.replaceFirst(inputFilePrefix, "assignment_").replaceAll("\\.txt$", ".sol"));
try (BufferedReader assignmentBufferedReader = new BufferedReader(new InputStreamReader(
new FileInputStream(assignmentInputFile), StandardCharsets.UTF_8))) {
return assignmentBufferedReader.readLine();
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException("Exception in assignmentInputFile ("
+ assignmentInputFile + ")", e);
} catch (IllegalStateException e) {
throw new IllegalStateException("Exception in assignmentInputFile ("
+ assignmentInputFile + ")", e);
} catch (IOException e) {
throw new IllegalArgumentException("Could not read the file (" + assignmentInputFile.getName() + ").", e);
}
}
}
}