-
Notifications
You must be signed in to change notification settings - Fork 452
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(dvrp): generic loads and changeable capacities #3627
Open
tkchouaki
wants to merge
14
commits into
matsim-org:master
Choose a base branch
from
tkchouaki:master_dvrp_generic_loads
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Conversation
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
feat(dvrp): generic loads and changeable capacities See merge request matsim/matsim-libs!95
# Conflicts: # contribs/drt/src/test/java/org/matsim/contrib/drt/prebooking/PrebookingTestEnvironment.java
…leWithChangingCapacitiesTest
…rs in CapacityChangeTask
…generic_loads' Fix: Preventing DefaultRequestInsertionScheduler from adding passengers in CapacityChangeTask See merge request matsim/matsim-libs!109
LGTM! |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Generic DvrpLoad representation of DVRP vehicle capacities and occupancies
This PR, co-prepared with @sebhoerl, proposes a more generic and extensible definition of DVRP vehicle capacities and occupancies with two main goals in mind:
To achieve this, several features were implemented between the DVRP and DRT modules. Below we first present the implementation in detail, then we show how to use this functionality to build your own simulations with complex capacities and occupancies and changing capacities.
Implementation details
The DvrpLoad interface
Instead of the systematic use of integers to represent the capacities of
DvrpVehicle
and their occupancies, we hide these behind a new interface,DvrpLoad
. All already existing operations on vehicle loads and occupancies were hidden behind one of the interface's methods:DvrpLoad::fitsIn
method. The general meaning behind it is whether the currentDvrpLoad
can be put in a vehicle that has the given load as a capacity. It must supportDvrpLoad
objects of different implementations and return false if they are not compatible.DvrpLoad::addTo
andDvrpLoad::subtract
methods. Implementations must support null parameters, and return the current load in those cases. Moreover, negative values must be supported.DvrpLoad::isEmpty
method.For serialization purposes (reading and writing
DvrpLoad
objects from/to files), we also assume that aDvrpLoad
is comprised of N-slots and that the value of each can be represented as aNumber
.Moreover, for factoring purposes, we also define a
DvrpLoadType
interface that handles type-level logics, such as building new instances (representing an empty quantity using theDvrpLoadType::getEmptyLoad
or from an array of numbers using theDvrpLoadType::fromArray
method). The link between theDvrpLoad
andDvrpLoadType
is made with theDvrpLoad::getType
method.A default
IntegerLoad
that behaves the same way as the previous integer representation is proposed. As theIntegerLoad::fitsIn
,IntegerLoad::addTo
andIntegerLoad::subtract
methods check if the type (anIntegerLoadType
instance) is the same, one can build new mutually exclusive capacities and occupancies simply by extending theIntegerLoadType
class.Additionally, a
MultipleIndependentSlotsLoad
(with aMultipleIndependentSlotsLoadType
) is proposed to allow defining capacities that consists of N-slots that have independent maximum occupancies.The DvrpLoadSerializer interface
To allow reading and writing the generic DvrpLoad objects from input and to output files, we need to be able to convert DvrpLoad objects to and from strings. This is encapsulated behind a
DvrpLoadSerializer
interface. Note that by default, the serilized string representation of aDvrpLoad
does not necessarily indicate its type. This is why theDvrpLoadSerializer::deSerialize
takes the string representation and theDvrpLoadType
id.The
DefaultDvrpLoadSerilizer
implementation follows aslotName=value
representation. However if the load type only has one slot, only a number is printed.Changing DvrpVehicle capacities
The
Dvrpvehicle
interface is extended with aDvrpVehicle::setCapacity
method. Furthermore, aCapacityChangeTask
interface is added, that can be then present in aDvrpVehicle
's schedule. Such a task lead to aVehicleCapacityChangeActivity
where the capacity is actually changed.This impacts the
InsertionGenerator
that can no longer assume that the vehicle's capacity remains constant. The current capacity during the day is then tracked and changes detected through the presence ofCapacityChangeTask
instances in the schedule. This is also reflected inVehicleDataEntryFactoryImpl
.To provide some basic capability of planning
DvrpVehicle
capacity changes at the beginning of the simulation, theorg.matsim.contrib.drt.taas.capacities.CapacityChangeSchedulerEngine
allows to do so through an implementation of theCapacityReconfigurationLogic
interface. These allow to modify the capacities of vehicles either at the beginning of the iteration, without having to insertCapacityChangeTask
, or during the day by schedulling such a task.A use case illustrating a simulation where vehicle capacities are changed during the day is present in the unit tests (Namely
RunDrtExampleWithChangingCapacitiesTest
) with two variations. One basic implementation that sets all vehicles to change capacities at the middle of the day, and another one that attempts to distribute vehicle capacities during the day according to the demand (implemented in theorg.matsim.contrib.drt.taas.capacities.DefaultCapacityReconfigurationLogic
).Integration in the Dvrp module
The capacity of
DvrpVehicle
objects comes from the one in the underlyingDvrpVehicleSpecification
. TheFleetModule
handles the two ways of constructing DVRP fleets: from dvrp fleet files or from regular MATSim vehicles file. In the former, the capacity XML attribute is used while in the latter, the number of seats in the vehicle's type is used. To allow buildingDvrpLoad
instances from those two sources, we implement two interfaces:DvrpLoadFromFleet
andDvrpLoadFromVehicle
. The implementation ofDvrpLoadFromFleet
that is binded in the current Dvrp mode is passed to theFleetReader
while the implementation ofDvrpLoadFromVehicle
is passed toDvrpVehicleSpecificationWithMatsimVehicle::createFleetSpecificationFromMatsimVehicles
The default implementation of
DvrpLoadFromFleet
(defined anonymously in theFleetModule
behaves the previous implementation, interpreting the integer capacity attribute of the XML file with theIntegerLoadType
that is bound in the current Dvrp mode. To avoid having to change thedvrp_vehicles_v1.dtd
, this default implementation does not directly allow to buildDvrpLoad
s that are not from oneIntegerLoadType
. It is up to the developper to implement a customDvrpLoadFromFleet
that does this.The default implementation of
DvrpLoadFromVehicle
(calledDefaultDvrpLoadFromVehicle
) considers the presence ofdvrp:capacityType
anddvrp:capacityValue
attributes in the vehicles (or in the vehicle type) and uses aDvrpLoadSerializer
to convert them into aDvrpLoad
. If those attributes are not available, a fallbackIntegerLoadType
is used to interpret the vehicle type's number of seats, thus keeping the same behaviour as the previous implementation.A
DvrpLoadModule
is added that performs the default bindings for theIntegerLoadType
and theDvrpLoadSerializer
. Currently this module is installed by theFleetModule
.To keep track of changing capacities, the new event type
DvrpVehicleCapacityChanged
is added (implemented by theVehicleCapacityChangedEvent
class). It is fired every time the capacity of aDvrpVehicle
is changed and also at the start of the first task of the vehicle's schedule. Below an XML example generated with this event.Integration in the DRT module
The only point that needed adaptation in the DRT module concerns building the
DvrpLoad
representing the occupancy generated by a DRT request. While before it was just the number of passengers, here we propose an interface that encapsulates this:DvrpLoadFromDrtPassengers
.The default implementation of this interface,
DefaultDvrpLoadFromDrtPassengers
works on the person level, determining the load of each person and summing them to retrieve the overallDvrpLoad
of a request (Attempting to sum incompatible loads will throw an exception). To determine the load/occupancy of a person, the following process is followed:drt:loadType
anddrt:loadValue
are looked for in the person's attribute.DvrpLoadSerializer
is used to interpret the attributes into a load objectdrt:loadType
attribute is found, the string1
is deserialized using that type.drt:loadValue
is provided, the fallbackIntegerLoadType
(usually the one that is bound for that Drt mode) is used.IntegerLoadType
is used to build the DvrpLoad from the integer1
.This allows, for instance, to simulate a service where different passengers of the same grouped request do not have the same occupancy. E.g, one passenger with one suitcase and another passenger with 2 suitcases will generate an overall
DvrpLoad
of 2 passengers and 3 suitcases.This
DvrpLoad
is now a separate attribute of aDrtRequest
. To track the load of each request, thePassengerRequestSubmittedEvent
event is extended with two new XML attributes:load
andloadType
. Below an XML exampleAnalysis
Analysis for capacities and loads can be activated by setting
capacityLoadAnalysisInterval
in the modal DRT config group to a non-zero value. In that case, two files will be created in each iteration directory:dvrp_capacities_[mode].csv
anddvrp_loads_[mode].csv
. The first file contains all intervals in which vehicles have specific capacity in the formatvehicle_id;start_time;end_time;type;slot;capacity
where the first columns help identify the vehicle and the time slot at which certain capacities are active,
type
andslot
indicate the capacity type and capacity slot inside the activty type, andcapacity
the available amount. These information allow, for instance, to plot the available capacities in the fleet by hour. The second file tracks all requests and their loads by providing:vehicle_id;request_id;pickup_time;dropoff_time;type;slot;load
The file allows, for instance, to plot the transported load for each capacity type throghout the day.
How to use ?
We describe below the steps to follow to implement two example tests. If you want to look at code examples, they are present in
RunDrtExampleWithChangingCapacitiesTest
Simulating a fleet with fixed heterogeneous capacities and its related demand
Let's say the goal is to simulate a service where some vehicles can serve persons and the others can serve goods, both being able to be represented with an integer. The steps below can be followed to achieve that:
IntegerLoadType
:PersonsLoadType
andGoodsLoadType
that both buildIntegerLoad
instances with the given type.DvrpLoadFromFleet
that sets the vehicle's capacity to persons or goods according to its ID. (b) If the vehicles come from a vehicles file: You can add the attributesdvrp:capacityType
anddvrp:capacityValue
in the vehicles or factor in different vehicle types.DvrpLoadFromDrtPassengers
the determines whether a request is a persons or a goods one. (b) Alternatively, modify your plans.xml to add the person attributedrt:loadType
with the name of the appropriate load type.DvrpLoadType
s that are used in the simulation, theDefaultDvrpLoadSerializer
can be built by passing them to the constructor.Simulating a fleet with changing heterogeneous capacities and its related demand
Now let's say that vehicle capacities are to be re-configured during the day, the process above can be adapted as follows:
IntegerLoadType
to the desired one. Otherwise, follow step 2.a or 2.b from above.DefaultCapacityReconfigurationLogic
or bind your ownCapacityReconfigurationLogic
implementation, an example is shown inRunDrtExampleWithChangingCapacitiesTest.SimpleCapacityConfiguration
that configures all vehicles to switch capacities at 12pm.CapacityChangeSchedulerEngine
by passing the boundCapacityReconfigurationLogic
.