Skip to content

Commit

Permalink
flesh out epsilon-greedy destination supplier
Browse files Browse the repository at this point in the history
and lots of things around it, notably the idea of Evaluator and
Evaluation objects to generate values for possible choices
  • Loading branch information
nicolaspayette committed Nov 15, 2024
1 parent bba9fb2 commit 0ecd426
Show file tree
Hide file tree
Showing 20 changed files with 471 additions and 42 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* POSEIDON: an agent-based model of fisheries
* Copyright (c) 2024 CoHESyS Lab [email protected]
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

package uk.ac.ox.poseidon.agents.behaviours.choices;

import uk.ac.ox.poseidon.core.Factory;
import uk.ac.ox.poseidon.core.Simulation;

public class AveragingOptionValuesFactory<O> implements Factory<OptionValues<O>> {
@Override
public OptionValues<O> get(final Simulation simulation) {
return new AveragingOptionValues<>();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,43 +17,55 @@
*
*/

package uk.ac.ox.poseidon.agents.behaviours.destination;
package uk.ac.ox.poseidon.agents.behaviours.choices;

import com.google.common.collect.ImmutableList;
import ec.util.MersenneTwisterFast;
import sim.util.Int2D;

import java.util.List;
import java.util.function.Supplier;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static uk.ac.ox.poseidon.core.MasonUtils.oneOf;

class EpsilonGreedyDestinationSupplier implements DestinationSupplier {
public class EpsilonGreedyChooser<O> implements Supplier<O> {

private final ImmutableList<O> options;
private final double epsilon;
private final Supplier<Int2D> greedyDestinationSupplier;
private final Supplier<Int2D> nonGreedyDestinationSupplier;
private final OptionValues<O> optionValues;
private final Evaluator<O> evaluator;
private final MersenneTwisterFast rng;
private O currentOption;
private Evaluation currentEvaluation;

EpsilonGreedyDestinationSupplier(
public EpsilonGreedyChooser(
final double epsilon,
final Supplier<Int2D> greedyDestinationSupplier,
final Supplier<Int2D> nonGreedyDestinationSupplier,
final List<O> options,
final OptionValues<O> optionValues,
final Evaluator<O> evaluator,
final MersenneTwisterFast rng
) {
this.options = ImmutableList.copyOf(options);
this.optionValues = checkNotNull(optionValues);
this.evaluator = checkNotNull(evaluator);
checkArgument(
epsilon >= 0 && epsilon <= 1,
"epsilon must be between 0 and 1"
);
this.epsilon = epsilon;
this.greedyDestinationSupplier = checkNotNull(greedyDestinationSupplier);
this.nonGreedyDestinationSupplier = checkNotNull(nonGreedyDestinationSupplier);
this.rng = checkNotNull(rng);
}

@Override
public Int2D get() {
return rng.nextBoolean(epsilon)
? greedyDestinationSupplier.get()
: nonGreedyDestinationSupplier.get();
public O get() {
if (currentOption != null) {
optionValues.observe(currentOption, currentEvaluation.getResult());
}
final List<O> bestOptions = optionValues.getBestOptions();
final boolean explore = bestOptions.isEmpty() || rng.nextDouble() < epsilon;
currentOption = oneOf(explore ? options : bestOptions, rng);
currentEvaluation = evaluator.newEvaluation(currentOption);
return currentOption;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* POSEIDON: an agent-based model of fisheries
* Copyright (c) 2024 CoHESyS Lab [email protected]
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

package uk.ac.ox.poseidon.agents.behaviours.choices;

@FunctionalInterface
public interface Evaluation {
double getResult();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* POSEIDON: an agent-based model of fisheries
* Copyright (c) 2024 CoHESyS Lab [email protected]
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

package uk.ac.ox.poseidon.agents.behaviours.choices;

public interface Evaluator<O> {
Evaluation newEvaluation(O option);
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,6 @@

import java.util.function.Supplier;

@FunctionalInterface
public interface DestinationSupplier extends Supplier<Int2D> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* POSEIDON: an agent-based model of fisheries
* Copyright (c) 2024 CoHESyS Lab [email protected]
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

package uk.ac.ox.poseidon.agents.behaviours.destination;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import sim.util.Int2D;
import uk.ac.ox.poseidon.agents.behaviours.choices.EpsilonGreedyChooser;
import uk.ac.ox.poseidon.agents.behaviours.choices.Evaluator;
import uk.ac.ox.poseidon.agents.behaviours.choices.OptionValues;
import uk.ac.ox.poseidon.agents.vessels.Vessel;
import uk.ac.ox.poseidon.agents.vessels.VesselScopeFactory;
import uk.ac.ox.poseidon.core.Factory;
import uk.ac.ox.poseidon.core.Simulation;
import uk.ac.ox.poseidon.geography.bathymetry.BathymetricGrid;
import uk.ac.ox.poseidon.geography.paths.PathFinder;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class EpsilonGreedyDestinationSupplierFactory extends VesselScopeFactory<DestinationSupplier> {

private double epsilon;
private Factory<? extends BathymetricGrid> bathymetricGrid;
private Factory<? extends PathFinder<Int2D>> pathFinder;
private Factory<? extends OptionValues<Int2D>> optionValues;
private VesselScopeFactory<? extends Evaluator<Int2D>> destinationEvaluator;

@Override
protected DestinationSupplier newInstance(
final Simulation simulation,
final Vessel vessel
) {
return new EpsilonGreedyChooser<>(
epsilon,
bathymetricGrid
.get(simulation)
.getAccessibleCells(vessel.getCurrentCell(), pathFinder.get(simulation)),
optionValues.get(simulation),
destinationEvaluator.get(simulation, vessel),
simulation.random
)::get;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@
import uk.ac.ox.poseidon.geography.bathymetry.BathymetricGrid;
import uk.ac.ox.poseidon.geography.paths.PathFinder;

import static com.google.common.collect.ImmutableList.toImmutableList;

@Getter
@Setter
@NoArgsConstructor
Expand All @@ -45,17 +43,14 @@ public class RandomDestinationSupplierFactory

@Override
protected DestinationSupplier newInstance(
Simulation simulation,
Vessel vessel
final Simulation simulation,
final Vessel vessel
) {
PathFinder<Int2D> pathFinder = this.pathFinder.get(simulation);
final PathFinder<Int2D> pathFinder = this.pathFinder.get(simulation);
return new RandomDestinationSupplier(
bathymetricGrid
.get(simulation)
.getWaterCells()
.stream()
.filter(cell -> pathFinder.getPath(vessel.getCurrentCell(), cell).isPresent())
.collect(toImmutableList()),
.getAccessibleCells(vessel.getCurrentCell(), pathFinder),
simulation.random
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* POSEIDON: an agent-based model of fisheries
* Copyright (c) 2024 CoHESyS Lab [email protected]
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

package uk.ac.ox.poseidon.agents.behaviours.destination;

import sim.util.Int2D;
import uk.ac.ox.poseidon.agents.behaviours.Action;
import uk.ac.ox.poseidon.agents.behaviours.choices.Evaluator;
import uk.ac.ox.poseidon.agents.behaviours.fishing.FishingAction;
import uk.ac.ox.poseidon.agents.vessels.Vessel;
import uk.ac.ox.poseidon.agents.vessels.VesselScopeFactory;
import uk.ac.ox.poseidon.core.Simulation;
import uk.ac.ox.poseidon.core.events.CombiningEphemeralAccumulatingListener;

public class TotalBiomassCaughtPerHourDestinationEvaluatorFactory
extends VesselScopeFactory<Evaluator<Int2D>> {

@Override
protected Evaluator<Int2D> newInstance(
final Simulation simulation,
final Vessel vessel
) {
return option -> new Evaluation(vessel);
}

private static class Evaluation implements uk.ac.ox.poseidon.agents.behaviours.choices.Evaluation {

private final CombiningEphemeralAccumulatingListener
<FishingAction, Double, Action, Double, Double> listener;

private Evaluation(final Vessel vessel) {
listener = new CombiningEphemeralAccumulatingListener<>(
vessel.getEventManager(),
FishingAction.class,
0.0,
(caughtSoFar, fishingAction) -> caughtSoFar + fishingAction.getTotalBiomassCaught(),
Action.class,
0.0,
(hoursSoFar, action) ->
vessel.isAtPort()
? hoursSoFar
: hoursSoFar + action.getDuration().getSeconds() / 3600.0,
(caught, hours) -> caught / hours
);
}

@Override
public double getResult() {
return listener.get();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,18 +53,23 @@ public Action newAction(

@Getter
@ToString(callSuper = true)
public class Fishing extends Action {
public class Fishing extends FishingAction {

Bucket<C> fishCaught;

public Fishing(
private Fishing(
final LocalDateTime start,
final Duration duration,
final Vessel vessel
) {
super(start, duration, vessel);
}

@Override
public double getTotalBiomassCaught() {
return fishCaught.getTotalBiomass().getValue();
}

@Override
protected Action complete(
final LocalDateTime dateTime
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* POSEIDON: an agent-based model of fisheries
* Copyright (c) 2024 CoHESyS Lab [email protected]
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

package uk.ac.ox.poseidon.agents.behaviours.fishing;

import uk.ac.ox.poseidon.agents.behaviours.Action;
import uk.ac.ox.poseidon.agents.vessels.Vessel;

import java.time.Duration;
import java.time.LocalDateTime;

public abstract class FishingAction extends Action {

public FishingAction(
final LocalDateTime start,
final Duration duration,
final Vessel vessel
) {
super(start, duration, vessel);
}

public abstract double getTotalBiomassCaught();
}
Loading

0 comments on commit 0ecd426

Please sign in to comment.