Skip to content

Commit

Permalink
Introduce service tasks
Browse files Browse the repository at this point in the history
  • Loading branch information
steffenaxer committed Sep 16, 2024
1 parent 22d8b7e commit 7fa8b22
Show file tree
Hide file tree
Showing 59 changed files with 3,951 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,13 @@
import javax.annotation.Nullable;

import org.matsim.contrib.drt.extension.companions.DrtCompanionParams;
import org.matsim.contrib.drt.extension.services.services.params.DrtServicesParams;
import org.matsim.contrib.drt.extension.operations.DrtOperationsParams;
import org.matsim.contrib.drt.run.DrtConfigGroup;

/**
* @author Steffen Axer
*
* <p>
* This class summarizes all optional drt parametersets and should be used while creating MultiModeDrtConfigGroup instances
*/
public class DrtWithExtensionsConfigGroup extends DrtConfigGroup {
Expand All @@ -40,14 +41,21 @@ public class DrtWithExtensionsConfigGroup extends DrtConfigGroup {
@Nullable
private DrtOperationsParams drtOperationsParams;

@Nullable
private DrtServicesParams drtServicesParams;

public DrtWithExtensionsConfigGroup() {
// Optional
addDefinition(DrtCompanionParams.SET_NAME, DrtCompanionParams::new, () -> drtCompanionParams,
params -> drtCompanionParams = (DrtCompanionParams) params);
params -> drtCompanionParams = (DrtCompanionParams) params);

// Optional
addDefinition(DrtOperationsParams.SET_NAME, DrtOperationsParams::new, () -> drtOperationsParams,
params -> drtOperationsParams = (DrtOperationsParams) params);
params -> drtOperationsParams = (DrtOperationsParams) params);

// Optional
addDefinition(DrtServicesParams.SET_TYPE, DrtServicesParams::new, () -> drtServicesParams,
params -> drtServicesParams = (DrtServicesParams) params);
}

public Optional<DrtCompanionParams> getDrtCompanionParams() {
Expand All @@ -57,5 +65,9 @@ public Optional<DrtCompanionParams> getDrtCompanionParams() {
public Optional<DrtOperationsParams> getDrtOperationsParams() {
return Optional.ofNullable(drtOperationsParams);
}


public Optional<DrtServicesParams> getServicesParams() {
return Optional.ofNullable(drtServicesParams);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
/*
* *********************************************************************** *
* 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.contrib.drt.extension.services.analysis;

import com.google.common.base.Verify;
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.IdMap;
import org.matsim.contrib.common.timeprofile.TimeDiscretizer;
import org.matsim.contrib.drt.extension.services.events.DrtServiceEndedEvent;
import org.matsim.contrib.drt.extension.services.events.DrtServiceEndedEventHandler;
import org.matsim.contrib.drt.extension.services.events.DrtServiceStartedEvent;
import org.matsim.contrib.drt.extension.services.events.DrtServiceStartedEventHandler;
import org.matsim.contrib.drt.extension.services.schedule.DrtService;
import org.matsim.contrib.dvrp.fleet.DvrpVehicleSpecification;
import org.matsim.contrib.dvrp.fleet.FleetSpecification;
import org.matsim.core.config.groups.QSimConfigGroup;

import java.util.HashMap;
import java.util.Map;

/**
* @author steffenaxer
*/
public class DrtServiceProfileCalculator implements DrtServiceEndedEventHandler,
DrtServiceStartedEventHandler {

private final TimeDiscretizer timeDiscretizer;

private Map<String, double[]> serviceProfile;

private final Map<Id<DrtService>, DrtServiceStartedEvent> vehicleServices = new IdMap<>(DrtService.class);

private final double analysisEndTime;

private final String dvrpMode;

private boolean wasConsolidatedInThisIteration = false;

public DrtServiceProfileCalculator(String dvrpMode, FleetSpecification fleet, int timeInterval,
QSimConfigGroup qsimConfig) {
this.dvrpMode = dvrpMode;
double qsimEndTime = qsimConfig.getEndTime().orElse(0);
double maxServiceEndTime = fleet.getVehicleSpecifications()
.values()
.stream()
.mapToDouble(DvrpVehicleSpecification::getServiceEndTime)
.max()
.orElse(0);
analysisEndTime = Math.max(qsimEndTime, maxServiceEndTime);
timeDiscretizer = new TimeDiscretizer((int)Math.ceil(analysisEndTime), timeInterval);
}


public TimeDiscretizer getTimeDiscretizer() {
return timeDiscretizer;
}

public Map<String, double[]> getProfile()
{
this.consolidate();
return this.serviceProfile;
}

private void consolidate() {
if (!wasConsolidatedInThisIteration) {
serviceProfile.values().forEach(this::normalizeProfile);
wasConsolidatedInThisIteration = true;
}
}

private void normalizeProfile(double[] profile) {
for (int i = 0; i < profile.length; i++) {
profile[i] /= timeDiscretizer.getTimeInterval();
}
}

private void increment(String serviceType,double beginTime, double endTime) {
Verify.verify(serviceType != null);

double[] profile = serviceProfile.computeIfAbsent(serviceType,
v -> new double[timeDiscretizer.getIntervalCount()]);
increment(profile, Math.min(beginTime, endTime), endTime);
}

private void increment(double[] values, double beginTime, double endTime) {
if (beginTime == endTime && beginTime >= analysisEndTime) {
return;
}
endTime = Math.min(endTime, analysisEndTime);

double timeInterval = timeDiscretizer.getTimeInterval();
int fromIdx = timeDiscretizer.getIdx(beginTime);
int toIdx = timeDiscretizer.getIdx(endTime);

for (int i = fromIdx; i < toIdx; i++) {
values[i] += timeInterval;
}
}


/* Event handling starts here */

@Override
public void handleEvent(DrtServiceEndedEvent event) {
if (!event.getMode().equals(dvrpMode)) {
return;
}

DrtServiceStartedEvent serviceStartedEvent = this.vehicleServices.remove(event.getDrtServiceId());
increment(serviceStartedEvent.getServiceType(), serviceStartedEvent.getTime(), event.getTime());
}

@Override
public void handleEvent(DrtServiceStartedEvent event) {
if (!event.getMode().equals(dvrpMode)) {
return;
}

this.vehicleServices.putIfAbsent(event.getDrtServiceId(), event);
}

@Override
public void reset(int iteration) {
vehicleServices.clear();
serviceProfile = new HashMap<>();
wasConsolidatedInThisIteration = false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@

/*
* *********************************************************************** *
* 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.contrib.drt.extension.services.analysis;

import static java.util.Map.Entry;

import java.awt.Paint;
import java.util.Collections;
import java.util.Map;

import org.matsim.contrib.common.timeprofile.ProfileWriter;
import org.matsim.contrib.dvrp.schedule.Task;

import com.google.common.collect.ImmutableMap;

public class DrtServiceProfileView implements ProfileWriter.ProfileView {

private final DrtServiceProfileCalculator calculator;

public DrtServiceProfileView(DrtServiceProfileCalculator calculator) {
this.calculator = calculator;
}

@Override
public ImmutableMap<String, double[]> profiles() {
return calculator.getProfile()
.entrySet()
.stream()
.collect(ImmutableMap.toImmutableMap(Entry::getKey, Entry::getValue));
}

@Override
public Map<String, Paint> seriesPaints() {
return Collections.emptyMap();
}

@Override
public double[] times() {
return calculator.getTimeDiscretizer().getTimes();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* *********************************************************************** *
* 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.contrib.drt.extension.services.analysis;


import org.matsim.contrib.common.timeprofile.ProfileWriter;
import org.matsim.contrib.drt.extension.services.analysis.DrtServiceProfileCalculator;
import org.matsim.contrib.drt.extension.services.analysis.DrtServiceProfileView;
import org.matsim.contrib.drt.extension.services.tasks.DefaultStackableTasksImpl;
import org.matsim.contrib.drt.extension.services.tasks.StackableTasks;
import org.matsim.contrib.drt.run.DrtConfigGroup;
import org.matsim.contrib.dvrp.fleet.FleetSpecification;
import org.matsim.contrib.dvrp.run.AbstractDvrpModeModule;
import org.matsim.core.config.groups.QSimConfigGroup;
import org.matsim.core.controler.MatsimServices;

/**
* @author steffenaxer
*/
public class ServiceAnalysisModule extends AbstractDvrpModeModule {
private static final int TIME_RESOLUTION = 5; // High resolution req. to visualize short tasks
DrtConfigGroup drtConfigGroup;

public ServiceAnalysisModule(DrtConfigGroup drtConfigGroup) {
super(drtConfigGroup.mode);
this.drtConfigGroup = drtConfigGroup;
}

@Override
public void install() {

bindModal(DrtServiceProfileCalculator.class).toProvider(modalProvider(
getter -> new DrtServiceProfileCalculator(getMode(), getter.getModal(FleetSpecification.class), TIME_RESOLUTION,
getter.get(QSimConfigGroup.class)))).asEagerSingleton();
addEventHandlerBinding().to(modalKey(DrtServiceProfileCalculator.class));

addControlerListenerBinding().toProvider(modalProvider(getter -> {
MatsimServices matsimServices = getter.get(MatsimServices.class);
String mode = drtConfigGroup.getMode();
var profileView = new DrtServiceProfileView(getter.getModal(DrtServiceProfileCalculator.class));
return new ProfileWriter(matsimServices, mode, profileView, "service_time_profiles");
}));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* *********************************************************************** *
* 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.contrib.drt.extension.services.dispatcher;

import org.matsim.api.core.v01.Id;
import org.matsim.contrib.drt.extension.services.schedule.DrtService;
import org.matsim.contrib.dvrp.fleet.DvrpVehicle;

/**
* @author steffenaxer
*/
public interface ServiceTaskDispatcher {
void dispatch(double timeStep);
void startService(DvrpVehicle dvrpVehicle, Id<DrtService> drtServiceId);
void stopService(DvrpVehicle dvrpVehicle, Id<DrtService> drtServiceId);
}
Loading

0 comments on commit 7fa8b22

Please sign in to comment.