Skip to content

Commit

Permalink
added AuctionTimeStatsLogger, some refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
rinde committed Nov 16, 2016
1 parent b1e6e3f commit afab4a8
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 75 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<rinsim.version>4.2.0</rinsim.version>
<rinsim.version>4.3.0-SNAPSHOT</rinsim.version>
<sonar.language>java</sonar.language>
<reference.version>1.0.0</reference.version>
</properties>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*
* Copyright (C) 2011-2016 Rinde van Lon, iMinds-DistriNet, KU Leuven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.rinde.logistics.pdptw.mas.comm;

import java.util.ArrayList;
import java.util.List;

import com.github.rinde.logistics.pdptw.mas.comm.AuctionCommModel.AuctionEvent;
import com.github.rinde.rinsim.central.Measurable;
import com.github.rinde.rinsim.central.SolverTimeMeasurement;
import com.github.rinde.rinsim.core.model.DependencyProvider;
import com.github.rinde.rinsim.core.model.Model.AbstractModel;
import com.github.rinde.rinsim.core.model.ModelBuilder.AbstractModelBuilder;
import com.github.rinde.rinsim.event.Event;
import com.github.rinde.rinsim.event.Listener;
import com.google.auto.value.AutoValue;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ListMultimap;

/**
* Utility for keeping track of auction related statistics. To use it, simply
* add {@link #builder()} to a simulation configuration. The statistics that are
* tracked are all finished {@link AuctionEvent}s and using
* {@link #getTimeMeasurements()} all time measurements can be collected.
* @author Rinde van Lon
*/
public class AuctionTimeStatsLogger extends AbstractModel<Bidder<DoubleBid>> {
final List<AuctionEvent> finishEvents;
private final List<Bidder<DoubleBid>> bidders;

AuctionTimeStatsLogger(AuctionCommModel<?> model) {
finishEvents = new ArrayList<>();
bidders = new ArrayList<>();

model.getEventAPI().addListener(new Listener() {
@Override
public void handleEvent(Event e) {
finishEvents.add((AuctionEvent) e);
}
}, AuctionCommModel.EventType.FINISH_AUCTION);
}

/**
* @return A multimap of {@link Bidder}s to {@link SolverTimeMeasurement}s.
*/
public ImmutableListMultimap<Bidder<?>, SolverTimeMeasurement> getTimeMeasurements() {
final ListMultimap<Bidder<?>, SolverTimeMeasurement> map =
ArrayListMultimap.create();
for (final Bidder<DoubleBid> b : bidders) {
if (b instanceof Measurable) {
map.putAll(b, ((Measurable) b).getTimeMeasurements());
}
}
return ImmutableListMultimap.copyOf(map);
}

/**
* @return All auction finish events that have occured so far.
*/
public ImmutableList<AuctionEvent> getAuctionFinishEvents() {
return ImmutableList.copyOf(finishEvents);
}

@Override
public boolean register(Bidder<DoubleBid> element) {
bidders.add(element);
return true;
}

@Override
public boolean unregister(Bidder<DoubleBid> element) {
return false;
}

/**
* @return {@link Builder} for {@link AuctionTimeStatsLogger}.
*/
public static Builder builder() {
return new AutoValue_AuctionTimeStatsLogger_Builder();
}

/**
* Builder for {@link AuctionTimeStatsLogger}.
* @author Rinde van Lon
*/
@AutoValue
public abstract static class Builder
extends AbstractModelBuilder<AuctionTimeStatsLogger, Bidder<DoubleBid>> {

private static final long serialVersionUID = 5417079781123182630L;

Builder() {
setDependencies(AuctionCommModel.class);
}

@Override
public AuctionTimeStatsLogger build(DependencyProvider dependencyProvider) {
return new AuctionTimeStatsLogger(
dependencyProvider.get(AuctionCommModel.class));
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,15 @@
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;

import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;

import com.github.rinde.logistics.pdptw.mas.Truck;
import com.github.rinde.rinsim.central.GlobalStateObject;
import com.github.rinde.rinsim.central.Measurable;
import com.github.rinde.rinsim.central.SimSolverBuilder;
import com.github.rinde.rinsim.central.Solver;
import com.github.rinde.rinsim.central.SolverTimeMeasurement;
import com.github.rinde.rinsim.central.SolverUser;
import com.github.rinde.rinsim.central.Solvers;
import com.github.rinde.rinsim.central.Solvers.SolveArgs;
Expand Down Expand Up @@ -70,7 +73,7 @@
*/
public class RtSolverBidder
extends AbstractBidder<DoubleBid>
implements RtSolverUser, TickListener {
implements RtSolverUser, TickListener, Measurable {

// 5 minutes
private static final long MAX_LOSING_TIME = 5 * 60 * 1000;
Expand Down Expand Up @@ -420,6 +423,15 @@ public void setSolverProvider(RtSimSolverBuilder builder) {
.build(solver));
}

@Override
public List<SolverTimeMeasurement> getTimeMeasurements() {
if (getSolver() instanceof Measurable) {
return ((Measurable) getSolver()).getTimeMeasurements();
}
throw new IllegalStateException(
"Solver " + getSolver() + " is not measurable.");
}

public static Builder realtimeBuilder(ObjectiveFunction objFunc,
StochasticSupplier<? extends RealtimeSolver> solverSupplier) {
return Builder.createRt(solverSupplier, objFunc);
Expand Down Expand Up @@ -484,7 +496,7 @@ static CallForBids create(Auctioneer<DoubleBid> auctioneer, Parcel parcel,
public abstract static class Builder
implements StochasticSupplier<Bidder<DoubleBid>> {
static final BidFunction DEFAULT_BID_FUNCTION = BidFunctions.PLAIN;
static final long DEFAULT_COOLDOWN_VALUE = -1L;
static final long DEFAULT_COOLDOWN_VALUE = 0L;

Builder() {}

Expand All @@ -502,6 +514,7 @@ public abstract static class Builder
@Nullable
abstract StochasticSupplier<? extends Solver> getStSolverSupplier();

@CheckReturnValue
public Builder withBidFunction(BidFunction bidFunction) {
return create(
getObjectiveFunction(),
Expand All @@ -511,7 +524,21 @@ public Builder withBidFunction(BidFunction bidFunction) {
getStSolverSupplier());
}

/**
* Set the reauction cooldown period. An unsuccessful reauction is defined
* as the event where a bidder wins its own reauction, meaning that the
* parcel allocation remains unchanged. The reauction cooldown period is
* defined as the time that a bidder is not allowed to start a new reauction
* for a parcel that was previously reauctioned unsuccessful. This is to
* avoid bidders to flood the system with reauctions that are doomed to
* fail.
* @param periodMs The cooldown period in milliseconds, cannot be negative.
* @return A new {@link Builder} instance with the new period.
*/
@CheckReturnValue
public Builder withReauctionCooldownPeriod(long periodMs) {
checkArgument(periodMs >= 0L,
"A negative cooldown period is not allowed.");
return create(
getObjectiveFunction(),
getBidFunction(),
Expand All @@ -520,6 +547,7 @@ public Builder withReauctionCooldownPeriod(long periodMs) {
getStSolverSupplier());
}

@SuppressWarnings("null")
@Override
public Bidder<DoubleBid> get(long seed) {
if (getRtSolverSupplier() != null) {
Expand Down Expand Up @@ -604,4 +632,5 @@ public String toString() {
+ "}";
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,11 @@
import com.github.rinde.logistics.pdptw.solver.optaplanner.ParcelVisit.VisitType;
import com.github.rinde.rinsim.central.GlobalStateObject;
import com.github.rinde.rinsim.central.GlobalStateObject.VehicleStateObject;
import com.github.rinde.rinsim.central.MeasureableSolver;
import com.github.rinde.rinsim.central.Solver;
import com.github.rinde.rinsim.central.SolverTimeMeasurement;
import com.github.rinde.rinsim.central.SolverValidator;
import com.github.rinde.rinsim.central.Solvers;
import com.github.rinde.rinsim.central.Solvers.MeasureableSolver;
import com.github.rinde.rinsim.central.Solvers.SolverTimeMeasurement;
import com.github.rinde.rinsim.central.rt.MeasurableRealtimeSolver;
import com.github.rinde.rinsim.central.rt.RealtimeSolver;
import com.github.rinde.rinsim.central.rt.Scheduler;
Expand Down Expand Up @@ -551,76 +551,6 @@ static String resourceToString(String resourcePath) {
}
}

// FIXME factory should be merged with builder as they are conceptually very
// similar (but not exactly the same).
/**
* Factory for instantiating Optaplanner solvers. See
* {@link OptaplannerSolvers#getFactoryFromBenchmark(String)} for obtaining an
* instance.
* @author Rinde van Lon
*/

// public interface OptaplannerFactory {
/**
* Create an OptaPlanner solver.
* @param unimprovedMs Maximum interval of time (in ms) the solver will run
* without finding an improving solution.
* @param nm The name of the solver.
* @return A supplier that will construct the specified solver.
* @throws IllegalArgumentException if a solver with the specified name does
* not exist in the factory.
*/
// StochasticSupplier<RealtimeSolver> createRT(long unimprovedMs, String nm);
//
// StochasticSupplier<Solver> create(long unimprovedMs, String nm);
//
// StochasticSupplier<Solver> createWithMaxCount(int unimprovedCount,
// String nm);
//
// // ImmutableSet<String> getAvailableSolvers();
// }

// static class OptaplannerSolversFactory implements OptaplannerFactory {
// private final String xmlResource;
//
// OptaplannerSolversFactory(String xmlLocation) {
// xmlResource = xmlLocation;
// }
//
// @Override
// public StochasticSupplier<RealtimeSolver> createRT(long ms, String nm) {
// return builderHelper(ms, nm).buildRealtimeSolverSupplier();
// }
//
// @Override
// public StochasticSupplier<Solver> create(long unimprovedMs, String nm) {
// return builderHelper(unimprovedMs, nm).buildSolverSupplier();
// }
//
// @Override
// public StochasticSupplier<Solver> createWithMaxCount(int unimprovedCount,
// String nm) {
// return builder()
// .withUnimprovedStepCountLimit(unimprovedCount)
// .withSolverFromBenchmark(xmlResource, nm)
// .withName(nm)
// .buildSolverSupplier();
// }
//
// Builder builderHelper(long ms, String nm) {
// return builder()
// .withUnimprovedMsLimit(ms)
// .withSolverFromBenchmark(xmlResource, nm)
// .withName(nm);
// }
//
// // @Override
// // public ImmutableSet<String> getAvailableSolvers() {
// // return builder().withSolverFromBenchmark(benchmarkXmlResource,
// solverKey)
// // }
// }

static class OptaplannerSolver implements MeasureableSolver {
@Nullable
PDPSolution lastSolution;
Expand Down

0 comments on commit afab4a8

Please sign in to comment.