
xf.xfvrp.opt.init.precheck.vrp.VRPPreCheckService Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of xfvrp Show documentation
Show all versions of xfvrp Show documentation
Solver for realistic vehicle routing problems
package xf.xfvrp.opt.init.precheck.vrp;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import xf.xfvrp.base.InvalidReason;
import xf.xfvrp.base.Node;
import xf.xfvrp.base.SiteType;
import xf.xfvrp.base.Vehicle;
import xf.xfvrp.base.preset.BlockNameConverter;
import xf.xfvrp.opt.init.precheck.PreCheckException;
/**
* Copyright (c) 2012-present Holger Schneider
* All rights reserved.
*
* This source code is licensed under the MIT License (MIT) found in the
* LICENSE file in the root directory of this source tree.
*
*
* This is the standard initialization of the giant tour
* out of the read data. The first thing of an optimization
* process is the creation of such a giant tour. Hereby all
* orders/customers will be arranged in a way, that each
* order/customer is visited by its own tour.
*
* If multiple depots are available, each single route has
* an alternating depot.
*
* Some construction optimization methods ignore the giant tours
* and rebuild their own. But for reasons of convenience in
* all cases a giant tour is initialized by this class.
*
* If orders/customers can not be served in a valid way with the
* given restrictions, they are excluded in an invalid list. These
* orders/customers are reinserted in a later step of optimization.
*
* @author hschneid
*
*/
public class VRPPreCheckService {
/**
* Structural checks of the nodes without model
*/
public Node[] precheck(Node[] nodes, Vehicle vehicle) throws PreCheckException {
checkFeasibility(nodes);
// Fetch block informations
Map> blocks = getBlocks(nodes);
List plannedNodes = getPlannedNodes(nodes);
// Check if customer is allowed for this vehicle type
checkVehicleType(nodes, vehicle, blocks, plannedNodes);
// TODO: PDP shipments
return plannedNodes.toArray(new Node[0]);
}
private void checkFeasibility(Node[] nodes) throws PreCheckException {
if(nodes.length == 0) {
throw new PreCheckException("No nodes found.");
}
}
private void checkVehicleType(Node[] nodes, Vehicle vehicle, Map> blocks, List plannedNodes) {
for (Node node : nodes) {
if(node.getSiteType() == SiteType.CUSTOMER) {
if(!node.getPresetBlockVehicleList().isEmpty() && !node.getPresetBlockVehicleList().contains(vehicle.idx)) {
// Remove invalid customer from nodes list
removeNode(plannedNodes, node, InvalidReason.WRONG_VEHICLE_TYPE);
// Remove all customers from block of invalid customer
removeCustomersOfBlock(blocks, plannedNodes, node);
}
}
}
}
private void removeCustomersOfBlock(Map> blocks, List plannedNodes, Node node) {
if(blocks.containsKey(node.getPresetBlockIdx())) {
blocks.get(node.getPresetBlockIdx())
.forEach(n -> removeNode(plannedNodes, n, InvalidReason.WRONG_VEHICLE_TYPE));
}
}
private void removeNode(List plannedNodes, Node node, InvalidReason invalidReason) {
node.setInvalidReason(invalidReason);
plannedNodes.remove(node);
}
private Map> getBlocks(Node[] nodes) {
return Arrays.stream(nodes)
.filter(n -> n.getSiteType() == SiteType.CUSTOMER)
.filter(n-> n.getPresetBlockIdx() != BlockNameConverter.DEFAULT_BLOCK_IDX)
.collect(Collectors.groupingBy(Node::getPresetBlockIdx));
}
private List getPlannedNodes(Node[] nodes) {
// Already planned customers (true = planned, false = unplanned, DEPOTS/REPLENISH always false)
return Arrays.asList(nodes);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy