Input Distributions

In this chapter, the default input distributions are presented. These are automatically seeded when a new database is created. They can be simply overwritten with your use-case specific assumptions.

First, the required modules are imported.

[1]:
import datetime
import itertools

import matplotlib
import matplotlib.pyplot as plt
import numpy as np
from IPython.display import Markdown

import conflowgen

Set a style for matplotlib.

[2]:
plt.style.use("seaborn-v0_8-colorblind")

Next, an in-memory SQLite database is opened. This is a fresh database without any content. While creating the database, it is automatically seeded with the default values.

[3]:
database_chooser = conflowgen.DatabaseChooser()
database_chooser.create_new_sqlite_database(":memory:")

If that was too fast, you can switch on logging to have a look behind the scenes.

[4]:
conflowgen.setup_logger(
    logging_directory="./data/logger",  # use data subdirectory relative to Jupyter Notebook
    format_string="%(message)s",  # only show log messages, no timestamps etc.
)
Creating log file at ./data/logger/2024-04-02--08-35-10.log
[4]:
<Logger conflowgen (DEBUG)>

Now you can see the same output like in the demo scripts.

[5]:
database_chooser.create_new_sqlite_database(":memory:")
Closing current database connection :memory:.
Opening file :memory:
journal_mode: memory
cache_size: -32768
page_size: 4096
foreign_keys: 1
Creating new database at :memory:
Creating all tables...
Seed with default values...
Number entries in table 'DeepSeaVessel': 0
Number entries in table 'Feeder': 0
Number entries in table 'Barge': 0
Number entries in table 'Train': 0
Number entries in table 'Truck': 0
Number entries in table 'Container': 0
Randomly set seed 1712046910807121797 for 'SqliteDatabaseConnection'

Once the database is set up, we can use the different distribution managers to have a look at the distributions which were automatically seeded.

Container Length Distribution

For each container length, the container length distribution determines its frequency among the containers. The numbers have been determined by the following reasoning:

Note

DEFAULT_CONTAINER_LENGTH_FREQUENCIES = {ContainerLength.forty_feet: 0.57, ContainerLength.forty_five_feet: 0.029, ContainerLength.other: 0.001, ContainerLength.twenty_feet: 0.4}

In general, most containerized goods are transported in 20’ and 40’ sea containers. In Germany in August 2021, only 1% of containerized goods (measured in weight) were transported in a container different from these two standard sizes [Statistisches Bundesamt (DESTATIS), 2021]. The same statistics says that approximately 30% of the goods (measured in weight again) are transported in 20’ containers, and 40’ containers make up 67%. For ConFlowGen, however, the fraction in numbers of containers is required instead of the fraction based on weight. In an expert interview it was said that the TEU factor in their case is approximately 1.6 and 45 foot containers made up less than 5%.

The numbers used here are inspired by the reported statistics and the expert interview. They are believed to be a reasonable first assumption if no data is available.

The container length distribution is obtained with the following lines of code:

[6]:
container_length_manager = conflowgen.ContainerLengthDistributionManager()

length_distribution = container_length_manager.get_container_length_distribution()

length_distribution
[6]:
{<ContainerLength.other: -1>: 0.001,
 <ContainerLength.twenty_feet: 20>: 0.4,
 <ContainerLength.forty_feet: 40>: 0.57,
 <ContainerLength.forty_five_feet: 45>: 0.029}

We can see that all the keys are enum values of the enum ContainerLength. For a nicer visualization, we can circumvent that by converting the enum values into strings.

[7]:
length_distribution_with_key_as_str = {
    str(key): value for (key, value) in length_distribution.items()
}

length_distribution_with_key_as_str
[7]:
{'other': 0.001, '20 feet': 0.4, '40 feet': 0.57, '45 feet': 0.029}

Now we can also plot the same information as a pie chart.

[8]:
length_distribution_with_key_as_str_without_zeros = {
    key: value
    for (key, value) in length_distribution_with_key_as_str.items()
    if value > 0
}

plt.title("Frequency of container lengths")
plt.pie(
    list(length_distribution_with_key_as_str_without_zeros.values()),
    labels=list(length_distribution_with_key_as_str_without_zeros.keys()),
    autopct="%1.0f%%",
)
plt.gcf().set_size_inches(5, 5)
plt.show()
../_images/notebooks_input_distributions_19_0.svg

More information on setting and getting the distribution can be found at ContainerLengthDistributionManager.

Container Weight Distribution

The container weight of each container is drawn from a distribution. For each container length, a different weight distribution can be provided.

Note

DEFAULT_CONTAINER_WEIGHT_DISTRIBUTION = {ContainerLength.forty_feet: {2: 0, 4: 2, 6: 5, 8: 6, 10: 9, 12: 11, 14: 11, 16: 9, 18: 4, 20: 3, 22: 3, 24: 3, 26: 1, 28: 1, 30: 1}, ContainerLength.forty_five_feet: {2: 0, 4: 2, 6: 5, 8: 6, 10: 9, 12: 11, 14: 11, 16: 9, 18: 4, 20: 3, 22: 3, 24: 3, 26: 1, 28: 1, 30: 1}, ContainerLength.other: {2: 0, 4: 0, 6: 0, 8: 0, 10: 0, 12: 0, 14: 0, 16: 0, 18: 0, 20: 0, 22: 0, 24: 0, 26: 0, 28: 0, 30: 0}, ContainerLength.twenty_feet: {2: 1, 4: 1, 6: 2, 8: 2.5, 10: 2.5, 12: 3, 14: 3, 16: 3, 18: 2.5, 20: 2.5, 22: 2, 24: 2, 26: 2, 28: 1, 30: 1}}

The initially seeded weight distributions stem from the cargo profile of the brochure [MacGregor, 2016]. The key refers to the weight of the container in metric tonnes. The value describes the relative frequency.

[9]:
container_weight_distribution_manager = conflowgen.ContainerWeightDistributionManager()

weight_distribution = (
    container_weight_distribution_manager.get_container_weight_distribution()
)

weight_distribution
[9]:
{<ContainerLength.twenty_feet: 20>: {2: 0.03225806451612903,
  4: 0.03225806451612903,
  6: 0.06451612903225806,
  8: 0.08064516129032258,
  10: 0.08064516129032258,
  12: 0.0967741935483871,
  14: 0.0967741935483871,
  16: 0.0967741935483871,
  18: 0.08064516129032258,
  20: 0.08064516129032258,
  22: 0.06451612903225806,
  24: 0.06451612903225806,
  26: 0.06451612903225806,
  28: 0.03225806451612903,
  30: 0.03225806451612903},
 <ContainerLength.forty_feet: 40>: {2: 0.0,
  4: 0.028985507246376812,
  6: 0.07246376811594203,
  8: 0.08695652173913043,
  10: 0.13043478260869565,
  12: 0.15942028985507245,
  14: 0.15942028985507245,
  16: 0.13043478260869565,
  18: 0.057971014492753624,
  20: 0.043478260869565216,
  22: 0.043478260869565216,
  24: 0.043478260869565216,
  26: 0.014492753623188406,
  28: 0.014492753623188406,
  30: 0.014492753623188406},
 <ContainerLength.forty_five_feet: 45>: {2: 0.0,
  4: 0.028985507246376812,
  6: 0.07246376811594203,
  8: 0.08695652173913043,
  10: 0.13043478260869565,
  12: 0.15942028985507245,
  14: 0.15942028985507245,
  16: 0.13043478260869565,
  18: 0.057971014492753624,
  20: 0.043478260869565216,
  22: 0.043478260869565216,
  24: 0.043478260869565216,
  26: 0.014492753623188406,
  28: 0.014492753623188406,
  30: 0.014492753623188406},
 <ContainerLength.other: -1>: {2: 0.06666666666666667,
  4: 0.06666666666666667,
  6: 0.06666666666666667,
  8: 0.06666666666666667,
  10: 0.06666666666666667,
  12: 0.06666666666666667,
  14: 0.06666666666666667,
  16: 0.06666666666666667,
  18: 0.06666666666666667,
  20: 0.06666666666666667,
  22: 0.06666666666666667,
  24: 0.06666666666666667,
  26: 0.06666666666666667,
  28: 0.06666666666666667,
  30: 0.06666666666666667}}

By visualizing the previous distribution with matplotlib, it is easier to make sense of it.

[10]:
fig, axes = plt.subplots(nrows=4, sharex=True, sharey=True, figsize=(5, 12))

for ax, container_length in zip(axes, list(conflowgen.ContainerLength)):
    x, y = zip(*weight_distribution[container_length].items())
    ax.title.set_text(str(container_length))
    ax.bar(x, [i * 100 for i in y])
    ax.set_ylabel("Share (in percentage)")

plt.xlabel("Weight (in metric tonnes)")
plt.show()
../_images/notebooks_input_distributions_25_0.svg

The container weight distributions can only be overwritten all at once. The values are automatically normalized by default.

[11]:
container_weight_distribution_manager.set_container_weight_distribution(
    {
        conflowgen.ContainerLength.twenty_feet: {10: 20, 20: 50, 30: 30},
        conflowgen.ContainerLength.forty_feet: {10: 15, 20: 50, 30: 35},
        conflowgen.ContainerLength.forty_five_feet: {10: 10, 20: 5, 30: 85},
        conflowgen.ContainerLength.other: {10: 1, 20: 1, 30: 1},
    }
)
Sum of fractions was not 1 for '20 feet' and was automatically normalized.
Sum of fractions was not 1 for '40 feet' and was automatically normalized.
Sum of fractions was not 1 for '45 feet' and was automatically normalized.
Sum of fractions was not 1 for 'other' and was automatically normalized.

From now on, ConFlowGen uses the new container weight distribution:

[12]:
container_weight_distribution_manager.get_container_weight_distribution()
[12]:
{<ContainerLength.twenty_feet: 20>: {10: 0.2, 20: 0.5, 30: 0.3},
 <ContainerLength.forty_feet: 40>: {10: 0.15, 20: 0.5, 30: 0.35},
 <ContainerLength.forty_five_feet: 45>: {10: 0.1, 20: 0.05, 30: 0.85},
 <ContainerLength.other: -1>: {10: 0.3333333333333333,
  20: 0.3333333333333333,
  30: 0.3333333333333333}}

More information on setting and getting the distribution can be found at ContainerWeightDistributionManager.

Container Storage Requirement Distribution

The storage requirement of each container is drawn from a distribution. For each container length, a different storage requirement distribution can be provided.

Note

DEFAULT_STORAGE_REQUIREMENT_DISTRIBUTION = {ContainerLength.forty_feet: {StorageRequirement.dangerous_goods: 0.08100000000000002, StorageRequirement.empty: 0.12, StorageRequirement.reefer: 0.07, StorageRequirement.standard: 0.7290000000000001}, ContainerLength.forty_five_feet: {StorageRequirement.dangerous_goods: 0.08100000000000002, StorageRequirement.empty: 0.12, StorageRequirement.reefer: 0.07, StorageRequirement.standard: 0.7290000000000001}, ContainerLength.other: {StorageRequirement.dangerous_goods: 0.08100000000000002, StorageRequirement.empty: 0.12, StorageRequirement.reefer: 0.07, StorageRequirement.standard: 0.7290000000000001}, ContainerLength.twenty_feet: {StorageRequirement.dangerous_goods: 0.08100000000000002, StorageRequirement.empty: 0.12, StorageRequirement.reefer: 0.07, StorageRequirement.standard: 0.7290000000000001}}

Containers come with different storage requirements. The given distribution is estimated based on the combination of several sources. Currently, no differentiation between the different container lengths exist.

The container storage requirement distribution is obtained with the following lines of code:

[13]:
storage_manager = conflowgen.StorageRequirementDistributionManager()

storage_requirement_distribution = (
    storage_manager.get_storage_requirement_distribution()
)

storage_requirement_distribution
[13]:
{<ContainerLength.twenty_feet: 20>: {<StorageRequirement.empty: 'empty'>: 0.12,
  <StorageRequirement.standard: 'standard'>: 0.7290000000000001,
  <StorageRequirement.reefer: 'reefer'>: 0.07,
  <StorageRequirement.dangerous_goods: 'dangerous_goods'>: 0.08100000000000002},
 <ContainerLength.forty_feet: 40>: {<StorageRequirement.empty: 'empty'>: 0.12,
  <StorageRequirement.standard: 'standard'>: 0.7290000000000001,
  <StorageRequirement.reefer: 'reefer'>: 0.07,
  <StorageRequirement.dangerous_goods: 'dangerous_goods'>: 0.08100000000000002},
 <ContainerLength.forty_five_feet: 45>: {<StorageRequirement.empty: 'empty'>: 0.12,
  <StorageRequirement.standard: 'standard'>: 0.7290000000000001,
  <StorageRequirement.reefer: 'reefer'>: 0.07,
  <StorageRequirement.dangerous_goods: 'dangerous_goods'>: 0.08100000000000002},
 <ContainerLength.other: -1>: {<StorageRequirement.empty: 'empty'>: 0.12,
  <StorageRequirement.standard: 'standard'>: 0.7290000000000001,
  <StorageRequirement.reefer: 'reefer'>: 0.07,
  <StorageRequirement.dangerous_goods: 'dangerous_goods'>: 0.08100000000000002}}

This can be visualized e.g. with the help of one pie chart for each container length.

[14]:
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(8, 8))

axes = list(itertools.chain(*axes))

for ax, container_length in zip(axes, list(conflowgen.ContainerLength)):
    keys, values = zip(*storage_requirement_distribution[container_length].items())
    labels = list(map(lambda x: str(x).replace("_", "\n"), keys))
    ax.title.set_text(str(container_length))
    ax.pie(
        [i * 100 for i in values],
        labels=labels,
        autopct="%1.0f%%",
        pctdistance=0.7,
        labeldistance=1.18,
        startangle=45,
    )

plt.tight_layout()
plt.show()
../_images/notebooks_input_distributions_37_0.svg

The container storage distributions can only be overwritten all at once. The values are automatically normalized by default.

[15]:
storage_manager.set_storage_requirement_distribution(
    {
        conflowgen.ContainerLength.twenty_feet: {
            conflowgen.StorageRequirement.empty: 0.3,
            conflowgen.StorageRequirement.standard: 0.5,
            conflowgen.StorageRequirement.reefer: 0.1,
            conflowgen.StorageRequirement.dangerous_goods: 0.1,
        },
        conflowgen.ContainerLength.forty_feet: {
            conflowgen.StorageRequirement.empty: 0.2,
            conflowgen.StorageRequirement.standard: 0.45,
            conflowgen.StorageRequirement.reefer: 0.2,
            conflowgen.StorageRequirement.dangerous_goods: 0.15,
        },
        conflowgen.ContainerLength.forty_five_feet: {
            conflowgen.StorageRequirement.empty: 0.2,
            conflowgen.StorageRequirement.standard: 0.7,
            conflowgen.StorageRequirement.reefer: 0.05,
            conflowgen.StorageRequirement.dangerous_goods: 0.05,
        },
        conflowgen.ContainerLength.other: {
            conflowgen.StorageRequirement.empty: 0.25,
            conflowgen.StorageRequirement.standard: 0.4,
            conflowgen.StorageRequirement.reefer: 0.25,
            conflowgen.StorageRequirement.dangerous_goods: 0.1,
        },
    }
)

From now on, ConFlowGen uses the new distribution.

[16]:
storage_manager.get_storage_requirement_distribution()
[16]:
{<ContainerLength.twenty_feet: 20>: {<StorageRequirement.empty: 'empty'>: 0.3,
  <StorageRequirement.standard: 'standard'>: 0.5,
  <StorageRequirement.reefer: 'reefer'>: 0.1,
  <StorageRequirement.dangerous_goods: 'dangerous_goods'>: 0.1},
 <ContainerLength.forty_feet: 40>: {<StorageRequirement.empty: 'empty'>: 0.2,
  <StorageRequirement.standard: 'standard'>: 0.45,
  <StorageRequirement.reefer: 'reefer'>: 0.2,
  <StorageRequirement.dangerous_goods: 'dangerous_goods'>: 0.15},
 <ContainerLength.forty_five_feet: 45>: {<StorageRequirement.empty: 'empty'>: 0.2,
  <StorageRequirement.standard: 'standard'>: 0.7,
  <StorageRequirement.reefer: 'reefer'>: 0.05,
  <StorageRequirement.dangerous_goods: 'dangerous_goods'>: 0.05},
 <ContainerLength.other: -1>: {<StorageRequirement.empty: 'empty'>: 0.25,
  <StorageRequirement.standard: 'standard'>: 0.4,
  <StorageRequirement.reefer: 'reefer'>: 0.25,
  <StorageRequirement.dangerous_goods: 'dangerous_goods'>: 0.1}}

More information on setting and getting the distribution can be found at StorageRequirementDistributionManager.

Mode of Transport Distribution

The mode of transport for each container is drawn from a distribution.

Note

DEFAULT_MODE_OF_TRANSPORT_DISTRIBUTION = {ModeOfTransport.barge: {ModeOfTransport.barge: 0, ModeOfTransport.deep_sea_vessel: 0.8518518518518519, ModeOfTransport.feeder: 0.14814814814814817, ModeOfTransport.train: 0, ModeOfTransport.truck: 0}, ModeOfTransport.deep_sea_vessel: {ModeOfTransport.barge: 0.0019815384615384612, ModeOfTransport.deep_sea_vessel: 0, ModeOfTransport.feeder: 0.29230769230769227, ModeOfTransport.train: 0.3326153846153846, ModeOfTransport.truck: 0.3552615384615384}, ModeOfTransport.feeder: {ModeOfTransport.barge: 0.0008296296296296296, ModeOfTransport.deep_sea_vessel: 0.7037037037037036, ModeOfTransport.feeder: 0, ModeOfTransport.train: 0.13925925925925925, ModeOfTransport.truck: 0.14874074074074073}, ModeOfTransport.train: {ModeOfTransport.barge: 0, ModeOfTransport.deep_sea_vessel: 0.7018518518518518, ModeOfTransport.feeder: 0.29814814814814816, ModeOfTransport.train: 0, ModeOfTransport.truck: 0}, ModeOfTransport.truck: {ModeOfTransport.barge: 0, ModeOfTransport.deep_sea_vessel: 0.7018518518518518, ModeOfTransport.feeder: 0.29814814814814816, ModeOfTransport.train: 0, ModeOfTransport.truck: 0}}

This mode of transport distribution is based on the report [Institut für Seeverkehrswirtschaft und Logistik, 2015]. The exact data for transshipment and hinterland share is taken from page 22, Figure 12 “Containerumschlag des Hafens Hamburg in TEU / Marktsegment 2013”. The modal split of the hinterland is updated based on the figures presented by Hafen Hamburg [2021]. After those adaptions, still there were several imbalances. Thus, some traffic was shifted from deep sea vessels to feeders by adding/subtracting some constants. In summary, this is an educated guess based on several sources.

The mode of transport distribution is obtained by the following code:

[17]:
mode_of_transport = conflowgen.ModeOfTransportDistributionManager()

mode_of_transport_distribution = mode_of_transport.get_mode_of_transport_distribution()

mode_of_transport_distribution
[17]:
{<ModeOfTransport.truck: 'truck'>: {<ModeOfTransport.truck: 'truck'>: 0,
  <ModeOfTransport.train: 'train'>: 0,
  <ModeOfTransport.feeder: 'feeder'>: 0.29814814814814816,
  <ModeOfTransport.deep_sea_vessel: 'deep_sea_vessel'>: 0.7018518518518518,
  <ModeOfTransport.barge: 'barge'>: 0},
 <ModeOfTransport.train: 'train'>: {<ModeOfTransport.truck: 'truck'>: 0,
  <ModeOfTransport.train: 'train'>: 0,
  <ModeOfTransport.feeder: 'feeder'>: 0.29814814814814816,
  <ModeOfTransport.deep_sea_vessel: 'deep_sea_vessel'>: 0.7018518518518518,
  <ModeOfTransport.barge: 'barge'>: 0},
 <ModeOfTransport.feeder: 'feeder'>: {<ModeOfTransport.truck: 'truck'>: 0.14985969311600694,
  <ModeOfTransport.train: 'train'>: 0.14030688399307423,
  <ModeOfTransport.feeder: 'feeder'>: 0,
  <ModeOfTransport.deep_sea_vessel: 'deep_sea_vessel'>: 0.7089975520926622,
  <ModeOfTransport.barge: 'barge'>: 0.0008358707982566125},
 <ModeOfTransport.deep_sea_vessel: 'deep_sea_vessel'>: {<ModeOfTransport.truck: 'truck'>: 0.3617122592448716,
  <ModeOfTransport.train: 'train'>: 0.33865490407388377,
  <ModeOfTransport.feeder: 'feeder'>: 0.2976153181037831,
  <ModeOfTransport.deep_sea_vessel: 'deep_sea_vessel'>: 0,
  <ModeOfTransport.barge: 'barge'>: 0.0020175185774614353},
 <ModeOfTransport.barge: 'barge'>: {<ModeOfTransport.truck: 'truck'>: 0,
  <ModeOfTransport.train: 'train'>: 0,
  <ModeOfTransport.feeder: 'feeder'>: 0.14814814814814817,
  <ModeOfTransport.deep_sea_vessel: 'deep_sea_vessel'>: 0.8518518518518519,
  <ModeOfTransport.barge: 'barge'>: 0}}

The mode of transport distributions can only be overwritten all at once. The values are automatically normalized by default.

[18]:
mode_of_transport.set_mode_of_transport_distribution(
    {
        conflowgen.ModeOfTransport.feeder: {
            conflowgen.ModeOfTransport.train: 0.2,
            conflowgen.ModeOfTransport.truck: 0.1,
            conflowgen.ModeOfTransport.barge: 0.1,
            conflowgen.ModeOfTransport.feeder: 0.4,
            conflowgen.ModeOfTransport.deep_sea_vessel: 0.2,
        },
        conflowgen.ModeOfTransport.truck: {
            conflowgen.ModeOfTransport.train: 0.15,
            conflowgen.ModeOfTransport.truck: 0.45,
            conflowgen.ModeOfTransport.barge: 0.1,
            conflowgen.ModeOfTransport.feeder: 0.2,
            conflowgen.ModeOfTransport.deep_sea_vessel: 0.1,
        },
        conflowgen.ModeOfTransport.barge: {
            conflowgen.ModeOfTransport.train: 0.2,
            conflowgen.ModeOfTransport.truck: 0.15,
            conflowgen.ModeOfTransport.barge: 0.25,
            conflowgen.ModeOfTransport.feeder: 0.1,
            conflowgen.ModeOfTransport.deep_sea_vessel: 0.3,
        },
        conflowgen.ModeOfTransport.deep_sea_vessel: {
            conflowgen.ModeOfTransport.train: 0.25,
            conflowgen.ModeOfTransport.truck: 0.1,
            conflowgen.ModeOfTransport.barge: 0.2,
            conflowgen.ModeOfTransport.feeder: 0.15,
            conflowgen.ModeOfTransport.deep_sea_vessel: 0.3,
        },
        conflowgen.ModeOfTransport.train: {
            conflowgen.ModeOfTransport.train: 0.3,
            conflowgen.ModeOfTransport.truck: 0.1,
            conflowgen.ModeOfTransport.barge: 0.15,
            conflowgen.ModeOfTransport.feeder: 0.2,
            conflowgen.ModeOfTransport.deep_sea_vessel: 0.25,
        },
    }
)

From now on, ConFlowGen uses the new distribution.

[19]:
mode_of_transport.get_mode_of_transport_distribution()
[19]:
{<ModeOfTransport.truck: 'truck'>: {<ModeOfTransport.truck: 'truck'>: 0.45,
  <ModeOfTransport.train: 'train'>: 0.15,
  <ModeOfTransport.feeder: 'feeder'>: 0.2,
  <ModeOfTransport.deep_sea_vessel: 'deep_sea_vessel'>: 0.1,
  <ModeOfTransport.barge: 'barge'>: 0.1},
 <ModeOfTransport.train: 'train'>: {<ModeOfTransport.truck: 'truck'>: 0.1,
  <ModeOfTransport.train: 'train'>: 0.3,
  <ModeOfTransport.feeder: 'feeder'>: 0.2,
  <ModeOfTransport.deep_sea_vessel: 'deep_sea_vessel'>: 0.25,
  <ModeOfTransport.barge: 'barge'>: 0.15},
 <ModeOfTransport.feeder: 'feeder'>: {<ModeOfTransport.truck: 'truck'>: 0.09999999999999998,
  <ModeOfTransport.train: 'train'>: 0.19999999999999996,
  <ModeOfTransport.feeder: 'feeder'>: 0.3999999999999999,
  <ModeOfTransport.deep_sea_vessel: 'deep_sea_vessel'>: 0.19999999999999996,
  <ModeOfTransport.barge: 'barge'>: 0.09999999999999998},
 <ModeOfTransport.deep_sea_vessel: 'deep_sea_vessel'>: {<ModeOfTransport.truck: 'truck'>: 0.1,
  <ModeOfTransport.train: 'train'>: 0.25,
  <ModeOfTransport.feeder: 'feeder'>: 0.15,
  <ModeOfTransport.deep_sea_vessel: 'deep_sea_vessel'>: 0.3,
  <ModeOfTransport.barge: 'barge'>: 0.2},
 <ModeOfTransport.barge: 'barge'>: {<ModeOfTransport.truck: 'truck'>: 0.15,
  <ModeOfTransport.train: 'train'>: 0.2,
  <ModeOfTransport.feeder: 'feeder'>: 0.1,
  <ModeOfTransport.deep_sea_vessel: 'deep_sea_vessel'>: 0.3,
  <ModeOfTransport.barge: 'barge'>: 0.25}}

More information on setting and getting the distribution can be found at ModeOfTransportDistributionManager.

Truck Arrival Distribution Manager

Each truck arrival time is drawn from a distribution.

Note

DEFAULT_TRUCK_ARRIVAL_DISTRIBUTION_WITH_NO_ARRIVAL_MANAGEMENT

This distribution assigns each hour of the week to the fraction of trucks that arrive during this time window. The distribution is based on real data of a project that took place approximately between 2013 and 2017. To ensure confidentiality, the distribution has been slightly distorted.

Truck arrival distribution is obtained by the following code:

[20]:
truck_arrival_distribution_manager = conflowgen.TruckArrivalDistributionManager()

truck_arrival_distribution = (
    truck_arrival_distribution_manager.get_truck_arrival_distribution()
)

truck_arrival_distribution
[20]:
{0.0: 0.0,
 1.0: 0.0,
 2.0: 0.0,
 3.0: 0.0,
 4.0: 0.0,
 5.0: 0.0039591265543534575,
 6.0: 0.008280755354708402,
 7.0: 0.00787052138708076,
 8.0: 0.009048448164603814,
 9.0: 0.010653252222483504,
 10.0: 0.012752141622641803,
 11.0: 0.016642037255734387,
 12.0: 0.014028517880762,
 13.0: 0.014804115031537253,
 14.0: 0.014974413128949352,
 15.0: 0.011139325718994135,
 16.0: 0.013892795598075644,
 17.0: 0.01082340227148447,
 18.0: 0.008328057746798652,
 19.0: 0.006987426702627708,
 20.0: 0.005148702946956847,
 21.0: 0.0030022110241690898,
 22.0: 0.0022556664886468924,
 23.0: 0.002490824815783658,
 24.0: 0.001903829363512033,
 25.0: 0.0021963463393818504,
 26.0: 0.001702371138626582,
 27.0: 0.0021438383478597847,
 28.0: 0.0024202228363111615,
 29.0: 0.006458109051981418,
 30.0: 0.009296920847765565,
 31.0: 0.008129901930327036,
 32.0: 0.009348584294496615,
 33.0: 0.011340930095712323,
 34.0: 0.013698448606867216,
 35.0: 0.01296799663104594,
 36.0: 0.015331193639106963,
 37.0: 0.014188986240397503,
 38.0: 0.014878231656167027,
 39.0: 0.01218616653188358,
 40.0: 0.012107579394020204,
 41.0: 0.010917000115475164,
 42.0: 0.006806732487834122,
 43.0: 0.005802918750649381,
 44.0: 0.005287802279192979,
 45.0: 0.0028202830127811215,
 46.0: 0.0019358005313836828,
 47.0: 0.0024196460473237236,
 48.0: 0.0016307576755443523,
 49.0: 0.0019988666796929904,
 50.0: 0.001446034417884346,
 51.0: 0.0010097489273788896,
 52.0: 0.0022229861377374384,
 53.0: 0.008228976109664983,
 54.0: 0.00916729394725238,
 55.0: 0.008981193048564363,
 56.0: 0.010437595120044508,
 57.0: 0.011883447250428468,
 58.0: 0.013126241314098189,
 59.0: 0.0140232137102564,
 60.0: 0.014067510063763042,
 61.0: 0.017925057408950704,
 62.0: 0.014893617277832918,
 63.0: 0.01301145426124103,
 64.0: 0.012079362990869175,
 65.0: 0.010112961782918234,
 66.0: 0.00893673181616467,
 67.0: 0.006631710275002562,
 68.0: 0.004326674554006004,
 69.0: 0.004305598082248182,
 70.0: 0.0022903162137174965,
 71.0: 0.0024661555911701296,
 72.0: 0.0011415664927662006,
 73.0: 0.0012494109397148158,
 74.0: 0.0009989509275061823,
 75.0: 0.0009419532259761962,
 76.0: 0.002040252335905318,
 77.0: 0.00518431625514197,
 78.0: 0.009913000508486947,
 79.0: 0.010654141394182583,
 80.0: 0.010344655620812727,
 81.0: 0.012472178423578372,
 82.0: 0.015253769000857457,
 83.0: 0.015313545656682602,
 84.0: 0.01971921057376204,
 85.0: 0.016488565599922105,
 86.0: 0.016894274684674377,
 87.0: 0.015499123208186931,
 88.0: 0.01478237177250456,
 89.0: 0.012150479118805851,
 90.0: 0.008135216144988145,
 91.0: 0.006333340451456769,
 92.0: 0.006095849295750999,
 93.0: 0.004708883365054937,
 94.0: 0.003413326087863949,
 95.0: 0.0017118289895981984,
 96.0: 0.0026912758548089605,
 97.0: 0.0021584624941145677,
 98.0: 0.0023228922170533146,
 99.0: 0.001604168692757123,
 100.0: 0.0027305554397402476,
 101.0: 0.0065523938632102915,
 102.0: 0.009520380832912196,
 103.0: 0.010997001773196237,
 104.0: 0.010602136875550094,
 105.0: 0.015899660970804596,
 106.0: 0.018083220148664984,
 107.0: 0.0163816471763427,
 108.0: 0.01629007302430533,
 109.0: 0.019168920074881534,
 110.0: 0.01646589595887871,
 111.0: 0.013656904790633789,
 112.0: 0.012617169136636602,
 113.0: 0.009685606800402495,
 114.0: 0.009069337128450136,
 115.0: 0.004422493262915178,
 116.0: 0.0042658850465993456,
 117.0: 0.0030436628208826318,
 118.0: 0.0016924428501923685,
 119.0: 0.002152265219068244,
 120.0: 0.0028091995053135693,
 121.0: 0.0022128380816916287,
 122.0: 0.0020158483718963533,
 123.0: 0.0010395871009478725,
 124.0: 0.0009474696390102265,
 125.0: 0.0011628071003245448,
 126.0: 0.001418797422137764,
 127.0: 0.0016522620284370162,
 128.0: 0.0015376248047583672,
 129.0: 0.0014253278743416424,
 130.0: 0.0007202777097896012,
 131.0: 0.0005074102872076632,
 132.0: 0.0004608008040356385,
 133.0: 0.0,
 134.0: 0.0,
 135.0: 0.0,
 136.0: 0.0,
 137.0: 0.0,
 138.0: 0.0,
 139.0: 0.0,
 140.0: 0.0,
 141.0: 0.0,
 142.0: 0.0,
 143.0: 0.0,
 144.0: 0.0,
 145.0: 0.0,
 146.0: 0.0,
 147.0: 0.0,
 148.0: 0.0,
 149.0: 0.0,
 150.0: 0.0,
 151.0: 0.0,
 152.0: 0.0,
 153.0: 0.0,
 154.0: 0.0,
 155.0: 0.0,
 156.0: 0.0,
 157.0: 0.0,
 158.0: 0.0,
 159.0: 0.0,
 160.0: 0.0,
 161.0: 0.0,
 162.0: 0.0,
 163.0: 0.0,
 164.0: 0.0,
 165.0: 0.0,
 166.0: 0.0,
 167.0: 0.0}

With a few lines of matplotlib code, the truck arrival pattern is visualized.

[21]:
hour_in_week, fraction = zip(*list(sorted(truck_arrival_distribution.items())))
weekday_in_week = [x / 24 + 1 for x in hour_in_week]
percentage = [x * 100 for x in fraction]

fig, ax = plt.subplots(figsize=(15, 3))
plt.plot(weekday_in_week, percentage)
plt.xlim([1, 7])  # plot from Monday to Sunday
ax.xaxis.grid(True, which="minor", color="lightgray")  # every hour
ax.xaxis.grid(True, which="major", color="k")  # every day
ax.xaxis.set_minor_locator(matplotlib.ticker.MultipleLocator(1 / 24))  # every hour

plt.title("Truck arrival distribution")
ax.set_xticks([i for i in range(1, 8)])  # every day
ax.set_xticklabels(
    ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
)
plt.xlabel("Week day")
plt.ylabel("Share (as percentage overall)")

plt.show()
../_images/notebooks_input_distributions_59_0.svg

A second default distribution exists. You need to provide the corresponding keyword when creating the new SQLite database to use it.

Note

DEFAULT_TRUCK_ARRIVAL_DISTRIBUTION_WITH_SLOT_BOOKING

This distribution assigns each hour of the week to the fraction of trucks that arrive during this time window. The distribution is based on an interview with the operational staff of a container terminal. To ensure confidentiality, the distribution has been slightly distorted.

Thee pattern looks slightly different - the peaks during lunch time are smoothened.

[22]:
database_chooser.close_current_connection()

database_chooser.create_new_sqlite_database(":memory:", assume_tas=True)

truck_arrival_distribution = (
    truck_arrival_distribution_manager.get_truck_arrival_distribution()
)

hour_in_week, fraction = zip(*list(sorted(truck_arrival_distribution.items())))
weekday_in_week = [x / 24 + 1 for x in hour_in_week]
percentage = [x * 100 for x in fraction]

fig, ax = plt.subplots(figsize=(15, 3))
plt.plot(weekday_in_week, percentage)
plt.xlim([1, 7])  # plot from Monday to Sunday
ax.xaxis.grid(True, which="minor", color="lightgray")  # every hour
ax.xaxis.grid(True, which="major", color="k")  # every day
ax.xaxis.set_minor_locator(matplotlib.ticker.MultipleLocator(1 / 24))  # every hour

plt.title("Truck arrival distribution")
ax.set_xticks([i for i in range(1, 8)])  # every day
ax.set_xticklabels(
    ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
)
plt.xlabel("Week day")
plt.ylabel("Share (as percentage overall)")

plt.show()
Closing current database connection :memory:.
Opening file :memory:
journal_mode: memory
cache_size: -32768
page_size: 4096
foreign_keys: 1
Creating new database at :memory:
Creating all tables...
Seed with default values...
Number entries in table 'DeepSeaVessel': 0
Number entries in table 'Feeder': 0
Number entries in table 'Barge': 0
Number entries in table 'Train': 0
Number entries in table 'Truck': 0
Number entries in table 'Container': 0
Randomly set seed 1712046915144593615 for 'SqliteDatabaseConnection'
../_images/notebooks_input_distributions_63_16.svg

The truck arrival distributions can only be overwritten for the whole week at once. Each key represents the hour in the week and each value represents the probability of a truck to arrive between that hour and the start of the next time slot.

[23]:
truck_arrival_distribution_manager.set_truck_arrival_distribution(
    {
        0: 0.006944444444444444,
        1: 0.006944444444444444,
        2: 0.006944444444444444,
        3: 0.006944444444444444,
        4: 0.006944444444444444,
        5: 0.006944444444444444,
        6: 0.006944444444444444,
        7: 0.006944444444444444,
        8: 0.006944444444444444,
        9: 0.006944444444444444,
        10: 0.006944444444444444,
        11: 0.006944444444444444,
        12: 0.006944444444444444,
        13: 0.006944444444444444,
        14: 0.006944444444444444,
        15: 0.006944444444444444,
        16: 0.006944444444444444,
        17: 0.006944444444444444,
        18: 0.006944444444444444,
        19: 0.006944444444444444,
        20: 0.006944444444444444,
        21: 0.006944444444444444,
        22: 0.006944444444444444,
        23: 0.006944444444444444,
        24: 0.006944444444444444,
        25: 0.006944444444444444,
        26: 0.006944444444444444,
        27: 0.006944444444444444,
        28: 0.006944444444444444,
        29: 0.006944444444444444,
        30: 0.006944444444444444,
        31: 0.006944444444444444,
        32: 0.006944444444444444,
        33: 0.006944444444444444,
        34: 0.006944444444444444,
        35: 0.006944444444444444,
        36: 0.006944444444444444,
        37: 0.006944444444444444,
        38: 0.006944444444444444,
        39: 0.006944444444444444,
        40: 0.006944444444444444,
        41: 0.006944444444444444,
        42: 0.006944444444444444,
        43: 0.006944444444444444,
        44: 0.006944444444444444,
        45: 0.006944444444444444,
        46: 0.006944444444444444,
        47: 0.006944444444444444,
        48: 0.006944444444444444,
        49: 0.006944444444444444,
        50: 0.006944444444444444,
        51: 0.006944444444444444,
        52: 0.006944444444444444,
        53: 0.006944444444444444,
        54: 0.006944444444444444,
        55: 0.006944444444444444,
        56: 0.006944444444444444,
        57: 0.006944444444444444,
        58: 0.006944444444444444,
        59: 0.006944444444444444,
        60: 0.006944444444444444,
        61: 0.006944444444444444,
        62: 0.006944444444444444,
        63: 0.006944444444444444,
        64: 0.006944444444444444,
        65: 0.006944444444444444,
        66: 0.006944444444444444,
        67: 0.006944444444444444,
        68: 0.006944444444444444,
        69: 0.006944444444444444,
        70: 0.006944444444444444,
        71: 0.006944444444444444,
        72: 0.006944444444444444,
        73: 0.006944444444444444,
        74: 0.006944444444444444,
        75: 0.006944444444444444,
        76: 0.006944444444444444,
        77: 0.006944444444444444,
        78: 0.006944444444444444,
        79: 0.006944444444444444,
        80: 0.006944444444444444,
        81: 0.006944444444444444,
        82: 0.006944444444444444,
        83: 0.006944444444444444,
        84: 0.006944444444444444,
        85: 0.006944444444444444,
        86: 0.006944444444444444,
        87: 0.006944444444444444,
        88: 0.006944444444444444,
        89: 0.006944444444444444,
        90: 0.006944444444444444,
        91: 0.006944444444444444,
        92: 0.006944444444444444,
        93: 0.006944444444444444,
        94: 0.006944444444444444,
        95: 0.006944444444444444,
        96: 0.006944444444444444,
        97: 0.006944444444444444,
        98: 0.006944444444444444,
        99: 0.006944444444444444,
        100: 0.006944444444444444,
        101: 0.006944444444444444,
        102: 0.006944444444444444,
        103: 0.006944444444444444,
        104: 0.006944444444444444,
        105: 0.006944444444444444,
        106: 0.006944444444444444,
        107: 0.006944444444444444,
        108: 0.006944444444444444,
        109: 0.006944444444444444,
        110: 0.006944444444444444,
        111: 0.006944444444444444,
        112: 0.006944444444444444,
        113: 0.006944444444444444,
        114: 0.006944444444444444,
        115: 0.006944444444444444,
        116: 0.006944444444444444,
        117: 0.006944444444444444,
        118: 0.006944444444444444,
        119: 0.006944444444444444,
        120: 0.006944444444444444,
        121: 0.006944444444444444,
        122: 0.006944444444444444,
        123: 0.006944444444444444,
        124: 0.006944444444444444,
        125: 0.006944444444444444,
        126: 0.006944444444444444,
        127: 0.006944444444444444,
        128: 0.006944444444444444,
        129: 0.006944444444444444,
        130: 0.006944444444444444,
        131: 0.006944444444444444,
        132: 0.006944444444444444,
        133: 0.006944444444444444,
        134: 0.006944444444444444,
        135: 0.006944444444444444,
        136: 0.006944444444444444,
        137: 0.006944444444444444,
        138: 0.006944444444444444,
        139: 0.006944444444444444,
        140: 0.006944444444444444,
        141: 0.006944444444444444,
        142: 0.006944444444444444,
        143: 0.006944444444444444,
        144: 0.0,
        145: 0.0,
        146: 0.0,
        147: 0.0,
        148: 0.0,
        149: 0.0,
        150: 0.0,
        151: 0.0,
        152: 0.0,
        153: 0.0,
        154: 0.0,
        155: 0.0,
        156: 0.0,
        157: 0.0,
        158: 0.0,
        159: 0.0,
        160: 0.0,
        161: 0.0,
        162: 0.0,
        163: 0.0,
        164: 0.0,
        165: 0.0,
        166: 0.0,
        167: 0.0,
    }
)

More information on setting and getting the distribution can be found at TruckArrivalDistributionManager.

Container Dwell Time Distribution

The container dwell time distribution is used in two cases. First, the truck arrivals are made more likely whenever the container dwell time is close to its expected duration. Second, a vehicle that arrives at the terminal close to the expected container dwell time is more likely to pick up the container.

Note

DEFAULT_MINIMUM_DWELL_TIME_OF_IMPORT_CONTAINERS_IN_HOURS = 3

The minimum dwell time of import containers is the earliest time after the discharging and loading process has started that a vehicle arrives from the hinterland and tries to pick up the container. In practice, this is often determined by the IT system of the terminal operators which releases a container for being picked up once the container is on the terminal (it has been successfully discharged). The actual earliest feasible point is determined in the subsequent model which consumes the generated data because here no sequence of discharge is determined, i.e., the container might be still on the vessel when the truck arrives. Thus, this value must be checked for when using the synthetic data in, e.g., a simulation model or mathematical model.

DEFAULT_MINIMUM_DWELL_TIME_OF_EXPORT_CONTAINERS_IN_HOURS = 12

The minimum dwell time of export containers is the minimum time a container must reside on the terminal before the vessel discharging and loading process starts. This time is needed for, e.g., finalizing the stowage planning and avoiding that a container which is designated for a vessel arrives shortly before vessel departure. If the vehicle that delivers this container is waiting in a queue, actually the container might miss the vessel. This cut-off is typically defined by the shipping company. Here, as a simplification one cut-off period is used for all cases. Both the time interval and the logic are inspired by expert interviews.

DEFAULT_MINIMUM_DWELL_TIME_OF_TRANSSHIPMENT_CONTAINERS_IN_HOURS = 3

The minimum dwell time for transshipment is the minimum time difference of arrival between two vessels. This means that one vessel can request a container from another vessel if and only if the previous vessel has arrived these k hours before the first one. For short transshipment dwell times, it might result in a direct transfer from one vessel to the other without any storage if the user decides to support such activities in their model (such as a simulation model or optimization model).

DEFAULT_AVERAGE_CONTAINER_DWELL_TIMES

The container dwell time distribution is based on [A container terminal operator in the German Bight, 2021]. The average container dwell times are taken from a report and reflect the reality at a given time for a specific container terminal operator.

The default values can be overwritten with the help of ContainerDwellTimeDistributionManager.set_container_dwell_time_distribution().

[24]:
container_dwell_time_distribution_manager = (
    conflowgen.ContainerDwellTimeDistributionManager()
)

distributions = (
    container_dwell_time_distribution_manager.get_container_dwell_time_distribution()
)

number_days_in_hours = 30 * 24
x = np.linspace(0, number_days_in_hours, number_days_in_hours)
locator = matplotlib.ticker.MultipleLocator(24)

for storage_requirement in [
    conflowgen.StorageRequirement.standard,
    conflowgen.StorageRequirement.empty,
]:

    display(Markdown(f"### {str(storage_requirement).capitalize()} container"))

    for inbound_vehicle in conflowgen.ModeOfTransport:

        display(
            Markdown(
                f"#### {str(inbound_vehicle).replace('_', ' ').capitalize()} delivering a "
                f"{str(storage_requirement)} container"
            )
        )

        for outbound_vehicle in conflowgen.ModeOfTransport:

            distribution = distributions[inbound_vehicle][outbound_vehicle][
                storage_requirement
            ]

            plt.figure(figsize=(20, 5))
            plt.axvline(distribution.minimum, color="dimgray")
            if distribution.maximum < number_days_in_hours:
                plt.axvline(distribution.maximum, color="dimgray")

            x_in_range = x[
                np.where((distribution.minimum < x) & (x < distribution.maximum))
            ]

            plt.plot(
                x_in_range,
                distribution.get_probabilities(x_in_range),
                color="gray",
                lw=5,
                alpha=0.6,
            )
            plt.xlabel("Container Dwell Time (h)")
            plt.gca().xaxis.set_major_locator(locator)
            title = (
                f'Container dwell time from {str(inbound_vehicle).replace("_", " ")} to {str(outbound_vehicle).replace("_", " ")} '
                f'for a(n) {str(storage_requirement).replace("_", " ")} container\n'
                f"avg={distribution.average:.1f}h={distribution.average / 24:.1f}d, var={distribution.variance:.1f}h², "
                f"{distribution.minimum:.1f}h ≤ x ≤ {distribution.maximum:.1f}h or in other terms "
                f"{distribution.minimum / 24:.1f}d ≤ x ≤ {distribution.maximum / 24:.1f}d"
            )
            plt.title(title)
            plt.show()

Standard container

Truck delivering a standard container

../_images/notebooks_input_distributions_70_2.svg
../_images/notebooks_input_distributions_70_3.svg
../_images/notebooks_input_distributions_70_4.svg
../_images/notebooks_input_distributions_70_5.svg
../_images/notebooks_input_distributions_70_6.svg

Train delivering a standard container

../_images/notebooks_input_distributions_70_8.svg
../_images/notebooks_input_distributions_70_9.svg
../_images/notebooks_input_distributions_70_10.svg
../_images/notebooks_input_distributions_70_11.svg
../_images/notebooks_input_distributions_70_12.svg

Feeder delivering a standard container

../_images/notebooks_input_distributions_70_14.svg
../_images/notebooks_input_distributions_70_15.svg
../_images/notebooks_input_distributions_70_16.svg
../_images/notebooks_input_distributions_70_17.svg
../_images/notebooks_input_distributions_70_18.svg

Deep sea vessel delivering a standard container

../_images/notebooks_input_distributions_70_20.svg
../_images/notebooks_input_distributions_70_21.svg
../_images/notebooks_input_distributions_70_22.svg
../_images/notebooks_input_distributions_70_23.svg
../_images/notebooks_input_distributions_70_24.svg

Barge delivering a standard container

../_images/notebooks_input_distributions_70_26.svg
../_images/notebooks_input_distributions_70_27.svg
../_images/notebooks_input_distributions_70_28.svg
../_images/notebooks_input_distributions_70_29.svg
../_images/notebooks_input_distributions_70_30.svg

Empty container

Truck delivering a empty container

../_images/notebooks_input_distributions_70_33.svg
../_images/notebooks_input_distributions_70_34.svg
../_images/notebooks_input_distributions_70_35.svg
../_images/notebooks_input_distributions_70_36.svg
../_images/notebooks_input_distributions_70_37.svg

Train delivering a empty container

../_images/notebooks_input_distributions_70_39.svg
../_images/notebooks_input_distributions_70_40.svg
../_images/notebooks_input_distributions_70_41.svg
../_images/notebooks_input_distributions_70_42.svg
../_images/notebooks_input_distributions_70_43.svg

Feeder delivering a empty container

../_images/notebooks_input_distributions_70_45.svg
../_images/notebooks_input_distributions_70_46.svg
../_images/notebooks_input_distributions_70_47.svg
../_images/notebooks_input_distributions_70_48.svg
../_images/notebooks_input_distributions_70_49.svg

Deep sea vessel delivering a empty container

../_images/notebooks_input_distributions_70_51.svg
../_images/notebooks_input_distributions_70_52.svg
../_images/notebooks_input_distributions_70_53.svg
../_images/notebooks_input_distributions_70_54.svg
../_images/notebooks_input_distributions_70_55.svg

Barge delivering a empty container

../_images/notebooks_input_distributions_70_57.svg
../_images/notebooks_input_distributions_70_58.svg
../_images/notebooks_input_distributions_70_59.svg
../_images/notebooks_input_distributions_70_60.svg
../_images/notebooks_input_distributions_70_61.svg

More information on setting and getting the distribution can be found at ContainerDwellTimeDistributionManager.

Default Values

In addition to the input distributions, also some default values are defined. All of them are currently some kind of minimum or maximum value. Thus, they directly influence other distributions.

Note

DEFAULT_TRANSPORTATION_BUFFER = 0.2

The export buffer describes how much more a vehicle typically takes from the terminal compared to the amount of containers in TEU which it delivers. The value .2 means that 20% more than the moved capacity (which determines the containers that are delivered to the terminal) is available for exporting containers as long as the maximum capacity of the vehicle is not exceeded. This concept has been first proposed by Hartmann [2004].

The default values can be overwritten with the help of ContainerFlowGenerationManager.set_properties().

All default values are optional. They are only overwritten if provided. The parameters start_date and end_date are obligatory though and no default values are provided.

[25]:
container_flow_generation_manager = conflowgen.ContainerFlowGenerationManager()

container_flow_generation_manager.set_properties(
    start_date=datetime.date(2021, 1, 15),
    end_date=datetime.date(2021, 1, 31),
    transportation_buffer=0.4,
)
container_flow_generation_manager.get_properties()
Randomly set seed 1712046950597800452 for 'TruckForImportContainersManager'
Randomly set seed 1712046950601245843 for 'TruckForExportContainersManager'
Randomly set seed 1712046950604179184 for 'ContainerFactory'
Randomly set seed 1712046950606829896 for 'LargeScheduledVehicleForOnwardTransportationManager'
Randomly set seed 1712046950618934183 for 'AllocateSpaceForContainersDeliveredByTruckService'
Replace seed 1712046950604179184 with 1712046950621184900 for 'ContainerFactory' for the new round.
Randomly set seed 1712046950623948161 for 'AssignDestinationToContainerService'
Loading destination distribution...
[25]:
{'name': None,
 'start_date': datetime.date(2021, 1, 15),
 'end_date': datetime.date(2021, 1, 31),
 'transportation_buffer': 0.4}

More information on setting and getting the values can be found at ContainerFlowGenerationManager.