-
Notifications
You must be signed in to change notification settings - Fork 459
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3602 from kt86/kmt_mergeLogisticsProjectIntoMATSim2
Merge Logistics (LSP) into freight contrib
- Loading branch information
Showing
221 changed files
with
36,109 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,25 @@ | ||
|
||
# Freight | ||
|
||
Package that plugs freight algorithms (programmed in external package jsprit) into matsim. | ||
This contrib contains the following packages: | ||
|
||
## Carriers | ||
(This is formally knows as 'freight contrib') | ||
|
||
Package that plugs vehicle routing problem algorithms (programmed in external package jsprit) into MATSim. | ||
|
||
A good starting point for jsprit is [ https://github.com/graphhopper/jsprit](https://github.com/graphhopper/jsprit). | ||
|
||
For runnable code see, e.g., the packages org.matsim.contrib.freight.usecases.* above . | ||
For runnable code see, e.g., the packages org.matsim.contrib.freight.carriers.usecases.* above . | ||
|
||
## Logistics | ||
(This code comes from [https://github.com/matsim-vsp/logistics/](https://github.com/matsim-vsp/logistics/) ) | ||
|
||
This code deals with creating logistics chains for freight transport. | ||
|
||
Here the decision agent is the logistics service provider (LSP) who decides on the logistics chain to be used for a given freight transport request. | ||
Therefore, it can use carriers (see above) and hubs. | ||
|
||
This package bases on work in the dfg-freight project. | ||
|
||
|
229 changes: 229 additions & 0 deletions
229
contribs/freight/scenarios/2regions/2regions-network.xml
Large diffs are not rendered by default.
Oops, something went wrong.
189 changes: 189 additions & 0 deletions
189
...freight/src/main/java/org/matsim/freight/logistics/ForwardLogisticChainSchedulerImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
/* | ||
* *********************************************************************** * | ||
* * project: org.matsim.* | ||
* * *********************************************************************** * | ||
* * * | ||
* * copyright : (C) 2022 by the members listed in the COPYING, * | ||
* * LICENSE and WARRANTY file. * | ||
* * email : info at matsim dot org * | ||
* * * | ||
* * *********************************************************************** * | ||
* * * | ||
* * This program is free software; you can redistribute it and/or modify * | ||
* * it under the terms of the GNU General Public License as published by * | ||
* * the Free Software Foundation; either version 2 of the License, or * | ||
* * (at your option) any later version. * | ||
* * See also COPYING, LICENSE and WARRANTY file * | ||
* * * | ||
* * *********************************************************************** | ||
*/ | ||
|
||
package org.matsim.freight.logistics; | ||
|
||
import java.util.ArrayList; | ||
import org.matsim.api.core.v01.Id; | ||
import org.matsim.freight.logistics.shipment.LspShipment; | ||
|
||
/** | ||
* .... Macht 3 Schritte: 1.) the LSPShipments are handed over to the first {@link | ||
* LogisticChainElement} of their {@link LogisticChain} 2.) the neighbors, i.e. the predecessors and | ||
* successors of all {@link LSPResource}s are determined 3.) the Resources are brought into the | ||
* right sequence according to the algorithm. | ||
* | ||
* <p>When traversing this list of {@link LSPResource}s, the operations in each {@link LSPResource} | ||
* are scheduled individually by calling their {@link LSPResourceScheduler}. | ||
*/ | ||
/* package-private */ class ForwardLogisticChainSchedulerImpl implements LogisticChainScheduler { | ||
|
||
/** | ||
* The Resources are brought into the right sequence according to the algorithm. The result of | ||
* this algorithm is a list of Resources that is later traversed from the front to the back, i.e. | ||
* starting with the entry at index 0. In the algorithm, this list is called sortedResourceList. | ||
*/ | ||
private final ArrayList<LSPResource> sortedResourceList; | ||
|
||
/** | ||
* The determination of the neighborhood structure among the Resources resulted in the | ||
* neighborList. | ||
*/ | ||
private final ArrayList<ResourceNeighbours> neighbourList; | ||
|
||
private LSP lsp; | ||
private int bufferTime; | ||
|
||
ForwardLogisticChainSchedulerImpl() { | ||
this.sortedResourceList = new ArrayList<>(); | ||
this.neighbourList = new ArrayList<>(); | ||
} | ||
|
||
@Override | ||
public void scheduleLogisticChain() { | ||
insertShipmentsAtBeginning(); | ||
setResourceNeighbours(); | ||
sortResources(); | ||
for (LSPResource resource : sortedResourceList) { | ||
resource.schedule(bufferTime, lsp.getSelectedPlan()); | ||
} | ||
} | ||
|
||
@Override | ||
public void setEmbeddingContainer(LSP lsp) { | ||
this.lsp = lsp; | ||
} | ||
|
||
private void setResourceNeighbours() { | ||
// internal data structure, try to ignore when looking from outside. kai/kai, jan'22 | ||
neighbourList.clear(); | ||
for (LSPResource resource : lsp.getResources()) { | ||
ResourceNeighbours neighbours = new ResourceNeighbours(resource); | ||
for (LogisticChainElement element : resource.getClientElements()) { | ||
LogisticChainElement predecessor = element.getPreviousElement(); | ||
LSPResource previousResource = predecessor.getResource(); | ||
neighbours.addPredecessor(previousResource); | ||
LogisticChainElement successor = element.getNextElement(); | ||
LSPResource nextResource = successor.getResource(); | ||
neighbours.addSuccessor(nextResource); | ||
} | ||
neighbourList.add(neighbours); | ||
} | ||
} | ||
|
||
private void sortResources() { | ||
sortedResourceList.clear(); | ||
while (!neighbourList.isEmpty()) { | ||
for (ResourceNeighbours neighbours : neighbourList) { | ||
if (allPredecessorsAlreadyScheduled(neighbours) | ||
&& noSuccessorAlreadyScheduled(neighbours)) { | ||
sortedResourceList.add(neighbours.resource); | ||
neighbourList.remove(neighbours); | ||
} | ||
} | ||
} | ||
} | ||
|
||
private boolean allPredecessorsAlreadyScheduled(ResourceNeighbours neighbours) { | ||
if (neighbours.predecessors.isEmpty()) { | ||
return true; | ||
} | ||
|
||
for (LSPResource predecessor : neighbours.predecessors) { | ||
if (!sortedResourceList.contains(predecessor)) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
private boolean noSuccessorAlreadyScheduled(ResourceNeighbours neighbours) { | ||
if (neighbours.successors.isEmpty()) { | ||
return true; | ||
} | ||
|
||
for (LSPResource successor : neighbours.successors) { | ||
if (!sortedResourceList.contains(successor)) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
private void insertShipmentsAtBeginning() { | ||
for (LogisticChain solution : lsp.getSelectedPlan().getLogisticChains()) { | ||
LogisticChainElement firstElement = getFirstElement(solution); | ||
assert firstElement != null; | ||
for (Id<LspShipment> lspShipmentId : solution.getLspShipmentIds()) { | ||
var shipment = LSPUtils.findLspShipment(lsp, lspShipmentId); | ||
assert shipment != null; | ||
firstElement | ||
.getIncomingShipments() | ||
.addShipment(shipment.getPickupTimeWindow().getStart(), shipment); | ||
} | ||
} | ||
} | ||
|
||
private LogisticChainElement getFirstElement(LogisticChain solution) { | ||
for (LogisticChainElement element : solution.getLogisticChainElements()) { | ||
if (element.getPreviousElement() == null) { | ||
return element; | ||
} | ||
} | ||
return null; | ||
} | ||
|
||
@Override | ||
public void setBufferTime(int bufferTime) { | ||
this.bufferTime = bufferTime; | ||
} | ||
|
||
/** | ||
* The relationship between different {@link LSPResource}s allows to handle various supply | ||
* structures that the {@link LSP} might decide to maintain. Thus, a {@link LSPResource} can have | ||
* several successors or predecessors or can be used by several different {@link LogisticChain}s. | ||
* The neighborhood structure among the {@link LSPResource}s is stored in instances of the class | ||
* {@link ResourceNeighbours} which contain references on the considered {@link LSPResource} and | ||
* on the set of immediate successors respective predecessors. As the result of this step, a | ||
* collection of {@link ResourceNeighbours} called neighborList is created that contains the | ||
* neighbors of all {@link LSPResource}s in the plan of the considered {@link LSP}. | ||
*/ | ||
private static class ResourceNeighbours { | ||
// internal data structure, try to ignore when looking from outside. kai/kai, jan'22 | ||
|
||
private final ArrayList<LSPResource> predecessors; | ||
private final ArrayList<LSPResource> successors; | ||
private final LSPResource resource; | ||
|
||
private ResourceNeighbours(LSPResource resource) { | ||
this.resource = resource; | ||
this.predecessors = new ArrayList<>(); | ||
this.successors = new ArrayList<>(); | ||
} | ||
|
||
private void addPredecessor(LSPResource resource) { | ||
this.predecessors.add(resource); | ||
} | ||
|
||
private void addSuccessor(LSPResource resource) { | ||
this.successors.add(resource); | ||
} | ||
} | ||
} |
143 changes: 143 additions & 0 deletions
143
contribs/freight/src/main/java/org/matsim/freight/logistics/FreightLogisticsConfigGroup.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
/* | ||
*********************************************************************** * | ||
* project: org.matsim.* | ||
* * | ||
* *********************************************************************** * | ||
* * | ||
* copyright : (C) 2024 by the members listed in the COPYING, * | ||
* LICENSE and WARRANTY file. * | ||
* email : info at matsim dot org * | ||
* * | ||
* *********************************************************************** * | ||
* * | ||
* This program is free software; you can redistribute it and/or modify * | ||
* it under the terms of the GNU General Public License as published by * | ||
* the Free Software Foundation; either version 2 of the License, or * | ||
* (at your option) any later version. * | ||
* See also COPYING, LICENSE and WARRANTY file * | ||
* * | ||
* *********************************************************************** | ||
*/ | ||
|
||
package org.matsim.freight.logistics; | ||
|
||
import java.net.URL; | ||
import java.util.Arrays; | ||
import java.util.Map; | ||
import org.matsim.core.config.ConfigGroup; | ||
import org.matsim.core.config.ReflectiveConfigGroup; | ||
|
||
public class FreightLogisticsConfigGroup extends ReflectiveConfigGroup { | ||
|
||
public static final String GROUPNAME="freightLogistics" ; | ||
|
||
private String lspsFile; | ||
static final String LSPS_FILE = "lspsFile"; | ||
private static final String LSPS_FILE_DESC = "Freight LogisticsServiceProviders (LSP)s File, according to MATSim logistics extension as part of MATSim's freight contrib."; | ||
|
||
public FreightLogisticsConfigGroup() { | ||
super(GROUPNAME); | ||
} | ||
|
||
//### CarriersFile ### | ||
/** | ||
* @return -- {@value #LSPS_FILE_DESC} | ||
*/ | ||
@StringGetter(LSPS_FILE) | ||
public String getLspsFile() { | ||
return lspsFile; | ||
} | ||
|
||
URL getLspsFileUrl(URL context) { | ||
return ConfigGroup.getInputFileURL(context, this.lspsFile); | ||
} | ||
|
||
/** | ||
* @param -- {@value #LSPS_FILE_DESC} | ||
*/ | ||
@StringSetter(LSPS_FILE) | ||
public void setLspsFile(String lspsFile) { | ||
this.lspsFile = lspsFile; | ||
} | ||
|
||
|
||
|
||
//--- | ||
// Commenting this out, because in a frist step I think it is better/ more streight forward to have the VRP logic in the carriers as an attribute. | ||
// please see {@link CarrierSchedulerUtils#setVrpLogic(carrier, VRPLogic)} and {@link CarrierSchedulerUtils#getVrpLogic(carrier)} | ||
//--- | ||
|
||
// static final String VRP_LOGIC_OF_DISTRIBUTION_CARRIER = "vrpLogicOfDistributionCarrier"; | ||
// private LSPUtils.LogicOfVrp vrpLogicOfDistributionCarrier = LSPUtils.LogicOfVrp.serviceBased; | ||
// private static final String VRP_LOGIC_OF_DISTRIBUTION_CARRIER_DESC = "Define, on which type of jobs the VRP of the **distribution** carrier will base on:" + Arrays.toString(LSPUtils.LogicOfVrp.values()); | ||
// | ||
// static final String VRP_LOGIC_OF_MAINRUN_CARRIER = "vrpLogicOfMainRunCarrier"; | ||
// private LSPUtils.LogicOfVrp vrpLogicOfMainRunCarrier = LSPUtils.LogicOfVrp.serviceBased; | ||
// private static final String VRP_LOGIC_OF_MAINRUN_CARRIER_DESC = "Define, on which type of jobs the VRP of the **MainRun** carrier will base on:" + Arrays.toString(LSPUtils.LogicOfVrp.values()); | ||
// | ||
// static final String VRP_LOGIC_OF_COLLECTION_CARRIER = "vrpLogicOfCollectionCarrier"; | ||
// private LSPUtils.LogicOfVrp vrpLogicOfCollectionCarrier = LSPUtils.LogicOfVrp.serviceBased; | ||
// private static final String VRP_LOGIC_OF_COLLECTION_CARRIER_DESC = "Define, on which type of jobs the VRP of the **Collection** carrier will base on:" + Arrays.toString(LSPUtils.LogicOfVrp.values()); | ||
// | ||
// /** | ||
// * | ||
// * @return The internal type of jobs, on which the VRPs of the distribution carrier bases on. | ||
// */ | ||
// @StringGetter(VRP_LOGIC_OF_DISTRIBUTION_CARRIER) | ||
// public LSPUtils.LogicOfVrp getVrpLogicOfDistributionCarrier() { | ||
// return vrpLogicOfDistributionCarrier; | ||
// } | ||
// | ||
// /** | ||
// * @param vrpLogicOfDistributionCarrier {@value #VRP_LOGIC_OF_DISTRIBUTION_CARRIER} | ||
// */ | ||
// @StringSetter(VRP_LOGIC_OF_DISTRIBUTION_CARRIER) | ||
// public void setVrpLogicOfDistributionCarrier(LSPUtils.LogicOfVrp vrpLogicOfDistributionCarrier) { | ||
// this.vrpLogicOfDistributionCarrier = vrpLogicOfDistributionCarrier; | ||
// } | ||
// | ||
// /** | ||
// * @return The internal type of jobs, on which the VRPs of the main run carrier bases on. | ||
// */ | ||
// @StringGetter(FreightLogisticsConfigGroup.VRP_LOGIC_OF_MAINRUN_CARRIER) | ||
// public LSPUtils.LogicOfVrp getVrpLogicOfMainRunCarrier() { | ||
// return vrpLogicOfMainRunCarrier; | ||
// } | ||
// | ||
// /** | ||
// * @param vrpLogicOfMainRunCarrier {@value #VRP_LOGIC_OF_MAINRUN_CARRIER} | ||
// */ | ||
// @StringSetter(FreightLogisticsConfigGroup.VRP_LOGIC_OF_MAINRUN_CARRIER) | ||
// public void setVrpLogicOfMainRunCarrier(LSPUtils.LogicOfVrp vrpLogicOfMainRunCarrier) { | ||
// this.vrpLogicOfMainRunCarrier = vrpLogicOfMainRunCarrier; | ||
// } | ||
// | ||
// /** | ||
// * @return The internal type of jobs, on which the VRPs of the collection carrier bases on. | ||
// */ | ||
// @StringGetter(FreightLogisticsConfigGroup.VRP_LOGIC_OF_COLLECTION_CARRIER) | ||
// public LSPUtils.LogicOfVrp getVrpLogicOfCollectionCarrier() { | ||
// return vrpLogicOfCollectionCarrier; | ||
// } | ||
// | ||
// /** | ||
// * @param vrpLogicOfCollectionCarrier {@value #VRP_LOGIC_OF_COLLECTION_CARRIER} | ||
// */ | ||
// @StringSetter(FreightLogisticsConfigGroup.VRP_LOGIC_OF_COLLECTION_CARRIER) | ||
// public void setVrpLogicOfCollectionCarrier(LSPUtils.LogicOfVrp vrpLogicOfCollectionCarrier) { | ||
// this.vrpLogicOfCollectionCarrier = vrpLogicOfCollectionCarrier; | ||
// } | ||
|
||
//--- | ||
//--- | ||
@Override | ||
public Map<String, String> getComments() { | ||
Map<String, String> map = super.getComments(); | ||
map.put(LSPS_FILE, LSPS_FILE_DESC); | ||
// map.put(VRP_LOGIC_OF_DISTRIBUTION_CARRIER, VRP_LOGIC_OF_DISTRIBUTION_CARRIER_DESC); | ||
// map.put(VRP_LOGIC_OF_MAINRUN_CARRIER, VRP_LOGIC_OF_MAINRUN_CARRIER_DESC); | ||
// map.put(VRP_LOGIC_OF_COLLECTION_CARRIER, VRP_LOGIC_OF_COLLECTION_CARRIER_DESC); | ||
return map; | ||
} | ||
|
||
} |
12 changes: 12 additions & 0 deletions
12
contribs/freight/src/main/java/org/matsim/freight/logistics/HasBackpointer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package org.matsim.freight.logistics; | ||
|
||
@SuppressWarnings("InterfaceMayBeAnnotatedFunctional") | ||
public interface HasBackpointer<T> { | ||
// In general, we set backpointers when we add to the container. | ||
|
||
// yy maybe also have interface HasSettableBackpointer? | ||
void setEmbeddingContainer(T pointer); | ||
|
||
// T getEmbeddingContainer(); | ||
|
||
} |
Oops, something went wrong.