From 0ecd4268dbc673fd35d1c31b189085a47d3a5808 Mon Sep 17 00:00:00 2001 From: Nicolas Payette Date: Fri, 15 Nov 2024 18:29:37 +0000 Subject: [PATCH] flesh out epsilon-greedy destination supplier and lots of things around it, notably the idea of Evaluator and Evaluation objects to generate values for possible choices --- .../choices/AveragingOptionValuesFactory.java | 30 ++++++++ .../EpsilonGreedyChooser.java} | 40 +++++++---- .../agents/behaviours/choices/Evaluation.java | 25 +++++++ .../agents/behaviours/choices/Evaluator.java | 24 +++++++ .../destination/DestinationSupplier.java | 1 + ...silonGreedyDestinationSupplierFactory.java | 64 +++++++++++++++++ .../RandomDestinationSupplierFactory.java | 13 ++-- ...ghtPerHourDestinationEvaluatorFactory.java | 68 +++++++++++++++++++ .../fishing/DefaultFishingBehaviour.java | 9 ++- .../behaviours/fishing/FishingAction.java | 39 +++++++++++ .../ac/ox/poseidon/agents/vessels/Vessel.java | 8 +++ .../agents/vessels/VesselFactory.java | 1 + .../biology/biomass/FullBiomassAllocator.java | 34 ++++++++++ .../biomass/FullBiomassAllocatorFactory.java | 44 ++++++++++++ ...ombiningEphemeralAccumulatingListener.java | 63 +++++++++++++++++ .../ox/poseidon/examples/BasicScenario.java | 28 ++++---- .../geography/bathymetry/BathymetricGrid.java | 11 +++ .../geography/ports/DefaultPortGrid.java | 5 ++ .../ox/poseidon/geography/ports/PortGrid.java | 2 + .../VesselFieldPortrayalFactory.java | 4 +- 20 files changed, 471 insertions(+), 42 deletions(-) create mode 100644 agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/choices/AveragingOptionValuesFactory.java rename agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/{destination/EpsilonGreedyDestinationSupplier.java => choices/EpsilonGreedyChooser.java} (52%) create mode 100644 agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/choices/Evaluation.java create mode 100644 agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/choices/Evaluator.java create mode 100644 agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/destination/EpsilonGreedyDestinationSupplierFactory.java create mode 100644 agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/destination/TotalBiomassCaughtPerHourDestinationEvaluatorFactory.java create mode 100644 agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/fishing/FishingAction.java create mode 100644 biology/src/main/java/uk/ac/ox/poseidon/biology/biomass/FullBiomassAllocator.java create mode 100644 biology/src/main/java/uk/ac/ox/poseidon/biology/biomass/FullBiomassAllocatorFactory.java create mode 100644 core/src/main/java/uk/ac/ox/poseidon/core/events/CombiningEphemeralAccumulatingListener.java diff --git a/agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/choices/AveragingOptionValuesFactory.java b/agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/choices/AveragingOptionValuesFactory.java new file mode 100644 index 000000000..6bf099505 --- /dev/null +++ b/agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/choices/AveragingOptionValuesFactory.java @@ -0,0 +1,30 @@ +/* + * POSEIDON: an agent-based model of fisheries + * Copyright (c) 2024 CoHESyS Lab cohesys.lab@gmail.com + * + * 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 . + * + */ + +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 implements Factory> { + @Override + public OptionValues get(final Simulation simulation) { + return new AveragingOptionValues<>(); + } +} diff --git a/agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/destination/EpsilonGreedyDestinationSupplier.java b/agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/choices/EpsilonGreedyChooser.java similarity index 52% rename from agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/destination/EpsilonGreedyDestinationSupplier.java rename to agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/choices/EpsilonGreedyChooser.java index d71e37d88..456850aba 100644 --- a/agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/destination/EpsilonGreedyDestinationSupplier.java +++ b/agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/choices/EpsilonGreedyChooser.java @@ -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 implements Supplier { + private final ImmutableList options; private final double epsilon; - private final Supplier greedyDestinationSupplier; - private final Supplier nonGreedyDestinationSupplier; + private final OptionValues optionValues; + private final Evaluator evaluator; private final MersenneTwisterFast rng; + private O currentOption; + private Evaluation currentEvaluation; - EpsilonGreedyDestinationSupplier( + public EpsilonGreedyChooser( final double epsilon, - final Supplier greedyDestinationSupplier, - final Supplier nonGreedyDestinationSupplier, + final List options, + final OptionValues optionValues, + final Evaluator 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 bestOptions = optionValues.getBestOptions(); + final boolean explore = bestOptions.isEmpty() || rng.nextDouble() < epsilon; + currentOption = oneOf(explore ? options : bestOptions, rng); + currentEvaluation = evaluator.newEvaluation(currentOption); + return currentOption; } } diff --git a/agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/choices/Evaluation.java b/agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/choices/Evaluation.java new file mode 100644 index 000000000..f4dd1f83e --- /dev/null +++ b/agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/choices/Evaluation.java @@ -0,0 +1,25 @@ +/* + * POSEIDON: an agent-based model of fisheries + * Copyright (c) 2024 CoHESyS Lab cohesys.lab@gmail.com + * + * 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 . + * + */ + +package uk.ac.ox.poseidon.agents.behaviours.choices; + +@FunctionalInterface +public interface Evaluation { + double getResult(); +} diff --git a/agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/choices/Evaluator.java b/agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/choices/Evaluator.java new file mode 100644 index 000000000..be3c08281 --- /dev/null +++ b/agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/choices/Evaluator.java @@ -0,0 +1,24 @@ +/* + * POSEIDON: an agent-based model of fisheries + * Copyright (c) 2024 CoHESyS Lab cohesys.lab@gmail.com + * + * 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 . + * + */ + +package uk.ac.ox.poseidon.agents.behaviours.choices; + +public interface Evaluator { + Evaluation newEvaluation(O option); +} diff --git a/agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/destination/DestinationSupplier.java b/agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/destination/DestinationSupplier.java index dbdada4db..f8fa6f8d8 100644 --- a/agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/destination/DestinationSupplier.java +++ b/agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/destination/DestinationSupplier.java @@ -23,5 +23,6 @@ import java.util.function.Supplier; +@FunctionalInterface public interface DestinationSupplier extends Supplier { } diff --git a/agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/destination/EpsilonGreedyDestinationSupplierFactory.java b/agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/destination/EpsilonGreedyDestinationSupplierFactory.java new file mode 100644 index 000000000..3e73a2a66 --- /dev/null +++ b/agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/destination/EpsilonGreedyDestinationSupplierFactory.java @@ -0,0 +1,64 @@ +/* + * POSEIDON: an agent-based model of fisheries + * Copyright (c) 2024 CoHESyS Lab cohesys.lab@gmail.com + * + * 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 . + * + */ + +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 { + + private double epsilon; + private Factory bathymetricGrid; + private Factory> pathFinder; + private Factory> optionValues; + private VesselScopeFactory> 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; + } +} diff --git a/agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/destination/RandomDestinationSupplierFactory.java b/agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/destination/RandomDestinationSupplierFactory.java index e17a32f17..bc10e60a4 100644 --- a/agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/destination/RandomDestinationSupplierFactory.java +++ b/agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/destination/RandomDestinationSupplierFactory.java @@ -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 @@ -45,17 +43,14 @@ public class RandomDestinationSupplierFactory @Override protected DestinationSupplier newInstance( - Simulation simulation, - Vessel vessel + final Simulation simulation, + final Vessel vessel ) { - PathFinder pathFinder = this.pathFinder.get(simulation); + final PathFinder 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 ); } diff --git a/agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/destination/TotalBiomassCaughtPerHourDestinationEvaluatorFactory.java b/agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/destination/TotalBiomassCaughtPerHourDestinationEvaluatorFactory.java new file mode 100644 index 000000000..28a88980a --- /dev/null +++ b/agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/destination/TotalBiomassCaughtPerHourDestinationEvaluatorFactory.java @@ -0,0 +1,68 @@ +/* + * POSEIDON: an agent-based model of fisheries + * Copyright (c) 2024 CoHESyS Lab cohesys.lab@gmail.com + * + * 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 . + * + */ + +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> { + + @Override + protected Evaluator 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 + 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(); + } + } +} diff --git a/agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/fishing/DefaultFishingBehaviour.java b/agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/fishing/DefaultFishingBehaviour.java index 2a350cfd2..3cc58a485 100644 --- a/agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/fishing/DefaultFishingBehaviour.java +++ b/agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/fishing/DefaultFishingBehaviour.java @@ -53,11 +53,11 @@ public Action newAction( @Getter @ToString(callSuper = true) - public class Fishing extends Action { + public class Fishing extends FishingAction { Bucket fishCaught; - public Fishing( + private Fishing( final LocalDateTime start, final Duration duration, final Vessel vessel @@ -65,6 +65,11 @@ public Fishing( super(start, duration, vessel); } + @Override + public double getTotalBiomassCaught() { + return fishCaught.getTotalBiomass().getValue(); + } + @Override protected Action complete( final LocalDateTime dateTime diff --git a/agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/fishing/FishingAction.java b/agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/fishing/FishingAction.java new file mode 100644 index 000000000..24ceb4866 --- /dev/null +++ b/agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/fishing/FishingAction.java @@ -0,0 +1,39 @@ +/* + * POSEIDON: an agent-based model of fisheries + * Copyright (c) 2024 CoHESyS Lab cohesys.lab@gmail.com + * + * 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 . + * + */ + +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(); +} diff --git a/agents/src/main/java/uk/ac/ox/poseidon/agents/vessels/Vessel.java b/agents/src/main/java/uk/ac/ox/poseidon/agents/vessels/Vessel.java index 0ae5cc9d5..3f38104a6 100644 --- a/agents/src/main/java/uk/ac/ox/poseidon/agents/vessels/Vessel.java +++ b/agents/src/main/java/uk/ac/ox/poseidon/agents/vessels/Vessel.java @@ -29,6 +29,7 @@ import uk.ac.ox.poseidon.agents.fields.VesselField; import uk.ac.ox.poseidon.core.events.EventManager; import uk.ac.ox.poseidon.geography.ports.Port; +import uk.ac.ox.poseidon.geography.ports.PortGrid; @Getter @Setter @@ -36,6 +37,7 @@ public class Vessel implements Oriented2D { private final String id; private final VesselField vesselField; + private final PortGrid portGrid; private final EventManager eventManager; private Behaviour initialBehaviour; private Port homePort; @@ -45,12 +47,14 @@ public class Vessel implements Oriented2D { @SuppressFBWarnings("EI_EXPOSE_REP2") Vessel( final String id, + final PortGrid portGrid, final Port homePort, final double cruisingSpeed, final VesselField vesselField, final EventManager eventManager ) { this.id = id; + this.portGrid = portGrid; this.homePort = homePort; this.cruisingSpeed = cruisingSpeed; this.vesselField = vesselField; @@ -92,4 +96,8 @@ public void setLocation(final Double2D point) { public Int2D getCurrentCell() { return vesselField.getCell(this); } + + public boolean isAtPort() { + return portGrid.anyPortsAt(getCurrentCell()); + } } diff --git a/agents/src/main/java/uk/ac/ox/poseidon/agents/vessels/VesselFactory.java b/agents/src/main/java/uk/ac/ox/poseidon/agents/vessels/VesselFactory.java index f82b22d5e..c22ca7d55 100644 --- a/agents/src/main/java/uk/ac/ox/poseidon/agents/vessels/VesselFactory.java +++ b/agents/src/main/java/uk/ac/ox/poseidon/agents/vessels/VesselFactory.java @@ -49,6 +49,7 @@ public final Vessel get(final Simulation simulation) { final VesselField vesselField = this.vesselField.get(simulation); final var vessel = new Vessel( idSupplier.get(simulation).nextId(), + portGrid.get(simulation), portFactory.get(simulation), speed, vesselField, diff --git a/biology/src/main/java/uk/ac/ox/poseidon/biology/biomass/FullBiomassAllocator.java b/biology/src/main/java/uk/ac/ox/poseidon/biology/biomass/FullBiomassAllocator.java new file mode 100644 index 000000000..063f0eeab --- /dev/null +++ b/biology/src/main/java/uk/ac/ox/poseidon/biology/biomass/FullBiomassAllocator.java @@ -0,0 +1,34 @@ +/* + * POSEIDON: an agent-based model of fisheries + * Copyright (c) 2024 CoHESyS Lab cohesys.lab@gmail.com + * + * 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 . + * + */ + +package uk.ac.ox.poseidon.biology.biomass; + +import lombok.RequiredArgsConstructor; +import sim.util.Int2D; + +@RequiredArgsConstructor +public class FullBiomassAllocator implements BiomassAllocator { + + private final CarryingCapacityGrid carryingCapacityGrid; + + @Override + public double applyAsDouble(final Int2D cell) { + return carryingCapacityGrid.getCarryingCapacity(cell); + } +} diff --git a/biology/src/main/java/uk/ac/ox/poseidon/biology/biomass/FullBiomassAllocatorFactory.java b/biology/src/main/java/uk/ac/ox/poseidon/biology/biomass/FullBiomassAllocatorFactory.java new file mode 100644 index 000000000..92367a929 --- /dev/null +++ b/biology/src/main/java/uk/ac/ox/poseidon/biology/biomass/FullBiomassAllocatorFactory.java @@ -0,0 +1,44 @@ +/* + * POSEIDON: an agent-based model of fisheries + * Copyright (c) 2024 CoHESyS Lab cohesys.lab@gmail.com + * + * 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 . + * + */ + +package uk.ac.ox.poseidon.biology.biomass; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import uk.ac.ox.poseidon.core.Factory; +import uk.ac.ox.poseidon.core.Simulation; +import uk.ac.ox.poseidon.core.SimulationScopeFactory; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class FullBiomassAllocatorFactory extends SimulationScopeFactory { + + private Factory carryingCapacityGrid; + + @Override + protected BiomassAllocator newInstance(final Simulation simulation) { + return new FullBiomassAllocator( + carryingCapacityGrid.get(simulation) + ); + } +} diff --git a/core/src/main/java/uk/ac/ox/poseidon/core/events/CombiningEphemeralAccumulatingListener.java b/core/src/main/java/uk/ac/ox/poseidon/core/events/CombiningEphemeralAccumulatingListener.java new file mode 100644 index 000000000..63a5ba759 --- /dev/null +++ b/core/src/main/java/uk/ac/ox/poseidon/core/events/CombiningEphemeralAccumulatingListener.java @@ -0,0 +1,63 @@ +/* + * POSEIDON: an agent-based model of fisheries + * Copyright (c) 2024 CoHESyS Lab cohesys.lab@gmail.com + * + * 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 . + * + */ + +package uk.ac.ox.poseidon.core.events; + +import java.util.function.BiFunction; +import java.util.function.Supplier; + +import static com.google.common.base.Preconditions.checkNotNull; + +public class CombiningEphemeralAccumulatingListener implements Supplier { + + private final EphemeralAccumulatingListener firstListener; + private final EphemeralAccumulatingListener secondListener; + private final BiFunction combiner; + + public CombiningEphemeralAccumulatingListener( + final EventManager eventManager, + final Class firstEventClass, + final T1 firstInitialValue, + final BiFunction firstAccumulator, + final Class secondEventClass, + final T2 secondInitialValue, + final BiFunction secondAccumulator, + final BiFunction combiner + ) { + checkNotNull(eventManager); + firstListener = new EphemeralAccumulatingListener<>( + eventManager, + firstEventClass, + firstInitialValue, + firstAccumulator + ); + secondListener = new EphemeralAccumulatingListener<>( + eventManager, + secondEventClass, + secondInitialValue, + secondAccumulator + ); + this.combiner = checkNotNull(combiner); + } + + @Override + public R get() { + return combiner.apply(firstListener.get(), secondListener.get()); + } +} diff --git a/examples/src/main/java/uk/ac/ox/poseidon/examples/BasicScenario.java b/examples/src/main/java/uk/ac/ox/poseidon/examples/BasicScenario.java index c7a404627..6c0a30c19 100644 --- a/examples/src/main/java/uk/ac/ox/poseidon/examples/BasicScenario.java +++ b/examples/src/main/java/uk/ac/ox/poseidon/examples/BasicScenario.java @@ -25,11 +25,11 @@ import sim.util.Int2D; import uk.ac.ox.poseidon.agents.behaviours.BackToInitialBehaviourFactory; import uk.ac.ox.poseidon.agents.behaviours.WaitBehaviourFactory; +import uk.ac.ox.poseidon.agents.behaviours.choices.AveragingOptionValuesFactory; import uk.ac.ox.poseidon.agents.behaviours.destination.ChooseDestinationBehaviourFactory; -import uk.ac.ox.poseidon.agents.behaviours.destination.FixedDestinationSupplierFactory; +import uk.ac.ox.poseidon.agents.behaviours.destination.EpsilonGreedyDestinationSupplierFactory; import uk.ac.ox.poseidon.agents.behaviours.destination.HomePortDestinationSupplierFactory; -import uk.ac.ox.poseidon.agents.behaviours.destination.RandomDestinationSupplierFactory; -import uk.ac.ox.poseidon.agents.behaviours.fishing.DefaultFishingBehaviour; +import uk.ac.ox.poseidon.agents.behaviours.destination.TotalBiomassCaughtPerHourDestinationEvaluatorFactory; import uk.ac.ox.poseidon.agents.behaviours.fishing.DefaultFishingBehaviourFactory; import uk.ac.ox.poseidon.agents.behaviours.travel.TravelAlongPathBehaviourFactory; import uk.ac.ox.poseidon.agents.fields.VesselField; @@ -79,7 +79,7 @@ public class BasicScenario extends Scenario { private Factory biomassDiffusionRule = new SmoothBiomassDiffusionRuleFactory(0.01, 0.01); private Factory biomassGrowthRule = - new LogisticGrowthRuleFactory(0.2); + new LogisticGrowthRuleFactory(0.1); private GlobalScopeFactory gridExtent = new GridExtentFactory( @@ -123,7 +123,7 @@ public class BasicScenario extends Scenario { 5000 ); private Factory biomassAllocator = - new RandomBiomassAllocatorFactory(carryingCapacityGrid); + new FullBiomassAllocatorFactory(carryingCapacityGrid); private Factory biomassGridA = new BiomassGridFactory( gridExtent, @@ -179,20 +179,24 @@ public class BasicScenario extends Scenario { 0 ); private Factory fleet = new DefaultFleetFactory( - 100, + 500, new VesselFactory( new WaitBehaviourFactory( new ExponentiallyDistributedDurationSupplierFactory( new DurationFactory(10, 0, 0, 0) ), new ChooseDestinationBehaviourFactory( - new FixedDestinationSupplierFactory( - new RandomDestinationSupplierFactory(bathymetricGrid, pathFinder) + new EpsilonGreedyDestinationSupplierFactory( + 0.1, + bathymetricGrid, + pathFinder, + new AveragingOptionValuesFactory<>(), + new TotalBiomassCaughtPerHourDestinationEvaluatorFactory() ), new TravelAlongPathBehaviourFactory( new DefaultFishingBehaviourFactory<>( new FixedBiomassProportionGearFactory( - 1, + 0.05, new DurationFactory(0, 1, 0, 0) ), new VoidHoldFactory<>(), @@ -234,12 +238,6 @@ public static void main(final String[] args) { Path.of("/home/nicolas/Desktop/scenario.yaml") ); final Simulation simulation = scenario.newSimulation(); - simulation - .getEventManager() - .addListener( - DefaultFishingBehaviour.Fishing.class, - System.out::println - ); simulation.start(); while ( simulation diff --git a/geography/src/main/java/uk/ac/ox/poseidon/geography/bathymetry/BathymetricGrid.java b/geography/src/main/java/uk/ac/ox/poseidon/geography/bathymetry/BathymetricGrid.java index f61ace94b..69c011b8b 100644 --- a/geography/src/main/java/uk/ac/ox/poseidon/geography/bathymetry/BathymetricGrid.java +++ b/geography/src/main/java/uk/ac/ox/poseidon/geography/bathymetry/BathymetricGrid.java @@ -22,6 +22,7 @@ import sim.field.grid.DoubleGrid2D; import sim.util.Int2D; import uk.ac.ox.poseidon.geography.grids.NumberGrid; +import uk.ac.ox.poseidon.geography.paths.PathFinder; import java.util.List; @@ -45,6 +46,16 @@ default List getLandCells() { .collect(toImmutableList()); } + default List getAccessibleCells( + final Int2D startingCell, + final PathFinder pathFinder + ) { + return getWaterCells() + .stream() + .filter(cell -> pathFinder.getPath(startingCell, cell).isPresent()) + .collect(toImmutableList()); + } + default List getAllCells() { return getGridExtent().getAllCells(); } diff --git a/geography/src/main/java/uk/ac/ox/poseidon/geography/ports/DefaultPortGrid.java b/geography/src/main/java/uk/ac/ox/poseidon/geography/ports/DefaultPortGrid.java index 5831170a2..0f644dfa2 100644 --- a/geography/src/main/java/uk/ac/ox/poseidon/geography/ports/DefaultPortGrid.java +++ b/geography/src/main/java/uk/ac/ox/poseidon/geography/ports/DefaultPortGrid.java @@ -99,6 +99,11 @@ public Stream getPortsAt(final Int2D cell) { ); } + @Override + public boolean anyPortsAt(final Int2D cell) { + return sparseGrid2D.numObjectsAtLocation(cell.x, cell.y) > 0; + } + @Override public Stream getAllPorts() { return MasonUtils.bagToStream(sparseGrid2D.allObjects); diff --git a/geography/src/main/java/uk/ac/ox/poseidon/geography/ports/PortGrid.java b/geography/src/main/java/uk/ac/ox/poseidon/geography/ports/PortGrid.java index e3de6ace4..147ac10c8 100644 --- a/geography/src/main/java/uk/ac/ox/poseidon/geography/ports/PortGrid.java +++ b/geography/src/main/java/uk/ac/ox/poseidon/geography/ports/PortGrid.java @@ -30,5 +30,7 @@ public interface PortGrid extends Grid { Stream getPortsAt(Int2D location); + boolean anyPortsAt(Int2D cell); + Stream getAllPorts(); } diff --git a/gui/src/main/java/uk/ac/ox/poseidon/gui/portrayals/VesselFieldPortrayalFactory.java b/gui/src/main/java/uk/ac/ox/poseidon/gui/portrayals/VesselFieldPortrayalFactory.java index 00f4730ad..a940027e4 100644 --- a/gui/src/main/java/uk/ac/ox/poseidon/gui/portrayals/VesselFieldPortrayalFactory.java +++ b/gui/src/main/java/uk/ac/ox/poseidon/gui/portrayals/VesselFieldPortrayalFactory.java @@ -31,7 +31,7 @@ import uk.ac.ox.poseidon.core.Simulation; import uk.ac.ox.poseidon.core.SimulationScopeFactory; -import static java.awt.Color.*; +import static java.awt.Color.LIGHT_GRAY; import static sim.portrayal.simple.OrientedPortrayal2D.SHAPE_COMPASS; @Getter @@ -52,7 +52,7 @@ protected ContinuousPortrayal2D newInstance(final Simulation simulation) { new SimplePortrayal2D(), 0, SCALE, - WHITE, + LIGHT_GRAY, SHAPE_COMPASS ) );