Skip to content

Commit

Permalink
Merge pull request #3514 from matsim-org/developmentOfSmallScaleComme…
Browse files Browse the repository at this point in the history
…rcialTraffic

Development of small scale commercial traffic & Move CarrierAnalysis to the freight contrib
  • Loading branch information
rewertvsp authored Oct 17, 2024
2 parents 80d36b0 + 6b1bc72 commit 9f7ea04
Show file tree
Hide file tree
Showing 34 changed files with 4,258 additions and 2,636 deletions.
8 changes: 8 additions & 0 deletions contribs/freight/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@
<version>2025.0-SNAPSHOT</version>
</dependency>


<!-- Needed for freight analysis, but is currently not possible because of circle dependency with Application-->
<!-- <dependency>-->
<!-- <groupId>org.matsim.contrib</groupId>-->
<!-- <artifactId>application</artifactId>-->
<!-- <version>2025.0-SNAPSHOT</version>-->
<!-- </dependency>-->

<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,19 @@
import org.apache.logging.log4j.Logger;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.Scenario;
import org.matsim.api.core.v01.events.Event;
import org.matsim.freight.carriers.Carriers;
import org.matsim.freight.carriers.events.CarrierShipmentDeliveryStartEvent;
import org.matsim.freight.carriers.events.CarrierShipmentPickupStartEvent;
import org.matsim.core.events.handler.BasicEventHandler;
import org.matsim.freight.carriers.events.eventhandler.CarrierShipmentDeliveryStartEventHandler;
import org.matsim.freight.carriers.events.eventhandler.CarrierShipmentPickupStartEventHandler;
import org.matsim.vehicles.Vehicle;
import org.matsim.vehicles.VehicleType;
import org.matsim.vehicles.VehicleUtils;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
Expand All @@ -47,27 +48,21 @@
/**
* @author Kai Martins-Turner (kturner)
*/
public class CarrierLoadAnalysis implements BasicEventHandler {
public class CarrierLoadAnalysis implements CarrierShipmentPickupStartEventHandler, CarrierShipmentDeliveryStartEventHandler {

private static final Logger log = LogManager.getLogger(CarrierLoadAnalysis.class);

private final String delimiter;
Carriers carriers;

private final Map<Id<Vehicle>, LinkedList<Integer>> vehicle2Load = new LinkedHashMap<>();

public CarrierLoadAnalysis(Carriers carriers) {
public CarrierLoadAnalysis(String delimiter, Carriers carriers) {
this.delimiter = delimiter;
this.carriers = carriers;
}

@Override public void handleEvent(Event event) {
if (event.getEventType().equals(CarrierShipmentPickupStartEvent.EVENT_TYPE)) {
handlePickup( event);
} if (event.getEventType().equals(CarrierShipmentDeliveryStartEvent.EVENT_TYPE)) {
handleDelivery(event);
}
}

private void handlePickup(Event event) {
@Override
public void handleEvent(CarrierShipmentPickupStartEvent event) {
Id<Vehicle> vehicleId = Id.createVehicleId(event.getAttributes().get("vehicle"));
Integer demand = Integer.valueOf(event.getAttributes().get(ATTRIBUTE_CAPACITYDEMAND));

Expand All @@ -82,8 +77,8 @@ private void handlePickup(Event event) {
vehicle2Load.put(vehicleId, list);
}


private void handleDelivery(Event event) {
@Override
public void handleEvent(CarrierShipmentDeliveryStartEvent event) {
Id<Vehicle> vehicleId = Id.createVehicleId(event.getAttributes().get("vehicle"));
Integer demand = Integer.valueOf(event.getAttributes().get(ATTRIBUTE_CAPACITYDEMAND));

Expand All @@ -95,12 +90,15 @@ private void handleDelivery(Event event) {
void writeLoadPerVehicle(String analysisOutputDirectory, Scenario scenario) throws IOException {
log.info("Writing out vehicle load analysis ...");
//Load per vehicle
String fileName = analysisOutputDirectory + "Load_perVehicle.tsv";
String fileName = Path.of(analysisOutputDirectory).resolve("Load_perVehicle.tsv").toString();

BufferedWriter bw1 = new BufferedWriter(new FileWriter(fileName));

//Write headline:
bw1.write("vehicleId \t capacity \t maxLoad \t load state during tour");
bw1.write(String.join(delimiter,"vehicleId",
"capacity",
"maxLoad",
"load state during tour"));
bw1.newLine();

for (Id<Vehicle> vehicleId : vehicle2Load.keySet()) {
Expand All @@ -112,13 +110,13 @@ void writeLoadPerVehicle(String analysisOutputDirectory, Scenario scenario) thro
final Double capacity = vehicleType.getCapacity().getOther();

bw1.write(vehicleId.toString());
bw1.write("\t" + capacity);
bw1.write("\t" + maxLoad);
bw1.write("\t" + load);
bw1.write(delimiter + capacity);
bw1.write(delimiter + maxLoad);
bw1.write(delimiter + load);
bw1.newLine();
}

bw1.close();
log.info("Output written to " + fileName);
log.info("Output written to {}", fileName);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
/*
* *********************************************************************** *
* project: org.matsim.*
* *********************************************************************** *
* *
* copyright : (C) 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.carriers.analysis;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.matsim.api.core.v01.Id;
import org.matsim.core.utils.misc.Time;
import org.matsim.freight.carriers.*;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Path;
import java.util.TreeMap;

/**
* Some basic analysis / data collection for {@link Carriers}(files)
* <p></p>
* For all carriers it writes out the:
* - score of the selected plan
* - number of tours (= vehicles) of the selected plan
* - number of Services (input)
* - number of Services (handled)
* - number of shipments (input)
* - number of shipments (handled)
* - number of not handled jobs
* - number of planned demand size
* - number of handled demand size
* to a tsv-file.
*
* @author Kai Martins-Turner (kturner), Ricardo Ewert
*/
public class CarrierPlanAnalysis {

private static final Logger log = LogManager.getLogger(CarrierPlanAnalysis.class);
public final String delimiter;

Carriers carriers;

public CarrierPlanAnalysis(String delimiter, Carriers carriers) {
this.delimiter = delimiter;
this.carriers = carriers;
}

public void runAnalysisAndWriteStats(String analysisOutputDirectory) throws IOException {
log.info("Writing out carrier analysis ...");
//Load per vehicle
String fileName = Path.of(analysisOutputDirectory).resolve("Carrier_stats.tsv").toString();

try (BufferedWriter bw1 = new BufferedWriter(new FileWriter(fileName))) {

//Write headline:
bw1.write(String.join(delimiter,
"carrierId",
"MATSimScoreSelectedPlan",
"jSpritScoreSelectedPlan",
"nuOfTours",
"nuOfShipments(input)",
"nuOfShipments(handled)",
"nuOfServices(input)",
"nuOfServices(handled)",
"noOfNotHandledJobs",
"nuOfPlanedDemandSize",
"nuOfHandledDemandSize",
"jspritComputationTime[HH:mm:ss]"
));
bw1.newLine();

final TreeMap<Id<Carrier>, Carrier> sortedCarrierMap = new TreeMap<>(carriers.getCarriers());

for (Carrier carrier : sortedCarrierMap.values()) {

int numberOfPlanedShipments = carrier.getShipments().size();
int numberOfPlanedServices = carrier.getServices().size();
int numberOfHandledPickups = (int) carrier.getSelectedPlan().getScheduledTours().stream().mapToDouble(
t -> t.getTour().getTourElements().stream().filter(te -> te instanceof Tour.Pickup).count()).sum();
int numberOfHandledDeliveries = (int) carrier.getSelectedPlan().getScheduledTours().stream().mapToDouble(
t -> t.getTour().getTourElements().stream().filter(te -> te instanceof Tour.Delivery).count()).sum();
int nuOfServiceHandled = (int) carrier.getSelectedPlan().getScheduledTours().stream().mapToDouble(
t -> t.getTour().getTourElements().stream().filter(te -> te instanceof Tour.ServiceActivity).count()).sum();
int numberOfPlanedDemandSize;
int numberOfHandledDemandSize;
int notHandledJobs;
if (numberOfPlanedShipments > 0) {
numberOfPlanedDemandSize = carrier.getShipments().values().stream().mapToInt(CarrierShipment::getSize).sum();
numberOfHandledDemandSize = carrier.getSelectedPlan().getScheduledTours().stream().mapToInt(
t -> t.getTour().getTourElements().stream().filter(te -> te instanceof Tour.Pickup).mapToInt(
te -> (((Tour.Pickup) te).getShipment().getSize())).sum()).sum();
notHandledJobs = numberOfPlanedShipments - numberOfHandledPickups;
} else {
numberOfPlanedDemandSize = carrier.getServices().values().stream().mapToInt(CarrierService::getCapacityDemand).sum();
numberOfHandledDemandSize = carrier.getSelectedPlan().getScheduledTours().stream().mapToInt(
t -> t.getTour().getTourElements().stream().filter(te -> te instanceof Tour.ServiceActivity).mapToInt(
te -> ((Tour.ServiceActivity) te).getService().getCapacityDemand()).sum()).sum();
notHandledJobs = numberOfPlanedServices - nuOfServiceHandled;
}

if (numberOfPlanedServices != nuOfServiceHandled) {
log.warn("Number of services in input and handled are not equal for carrier {}. Jobs Input: {}, Jobs Handled: {}",
carrier.getId(), numberOfPlanedServices, nuOfServiceHandled);
}
if (numberOfPlanedShipments != numberOfHandledPickups) {
log.warn("Number of shipments in input and handled are not equal for carrier {}. Jobs Input: {}, Jobs Handled: {}",
carrier.getId(), numberOfPlanedShipments, numberOfHandledPickups);
}
if (numberOfHandledDeliveries != numberOfHandledPickups) {
log.warn(
"Number of handled pickups and deliveries are not equal for carrier {}. Pickups: {}, Deliveries: {}. This should not happen!!",
carrier.getId(), numberOfHandledPickups, numberOfHandledDeliveries);
}
bw1.write(carrier.getId().toString());
bw1.write(delimiter + carrier.getSelectedPlan().getScore());
bw1.write(delimiter + carrier.getSelectedPlan().getJspritScore());
bw1.write(delimiter + carrier.getSelectedPlan().getScheduledTours().size());
bw1.write(delimiter + numberOfPlanedShipments);
bw1.write(delimiter + numberOfHandledPickups);
bw1.write(delimiter + numberOfPlanedServices);
bw1.write(delimiter + nuOfServiceHandled);
bw1.write(delimiter + notHandledJobs);
bw1.write(delimiter + numberOfPlanedDemandSize);
bw1.write(delimiter + numberOfHandledDemandSize);
if (CarriersUtils.getJspritComputationTime(carrier) != Integer.MIN_VALUE)
bw1.write(delimiter + Time.writeTime(CarriersUtils.getJspritComputationTime(carrier), Time.TIMEFORMAT_HHMMSS));
else
bw1.write(delimiter + "null");

bw1.newLine();
}

bw1.close();
log.info("Output written to {}", fileName);
} catch (IOException e) {
log.error("Error writing output to file: {}", fileName);
throw e;
}
}
}
Loading

0 comments on commit 9f7ea04

Please sign in to comment.