Skip to content

Commit 1994c6b

Browse files
add "external biomass grid process" using gRPC and tables using TableSaw
A bit of a sloppy commit since I tackled those two things in parallel. They could have been better separated...
1 parent 6dfe878 commit 1994c6b

20 files changed

+361
-244
lines changed

agents/build.gradle.kts

+1
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,5 @@ plugins {
2424
dependencies {
2525
api(project(":biology"))
2626
api(project(":geography"))
27+
api(project(":io"))
2728
}

agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/destination/TotalBiomassCaughtPerHourDestinationEvaluatorFactory.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ private Evaluation(final Vessel vessel) {
4949
vessel.getEventManager(),
5050
FishingAction.class,
5151
0.0,
52-
(caughtSoFar, fishingAction) -> caughtSoFar + fishingAction.getTotalBiomassCaught(),
52+
(caughtSoFar, fishingAction) -> caughtSoFar +
53+
fishingAction.getFishCaught().getTotalBiomass().getValue(),
5354
Action.class,
5455
0.0,
5556
(hoursSoFar, action) ->

agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/fishing/DefaultFishingBehaviour.java

-5
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,6 @@ private Fishing(
6565
super(start, duration, vessel, vessel.getCurrentCell());
6666
}
6767

68-
@Override
69-
public double getTotalBiomassCaught() {
70-
return fishCaught.getTotalBiomass().getValue();
71-
}
72-
7368
@Override
7469
protected Action complete(
7570
final LocalDateTime dateTime

agents/src/main/java/uk/ac/ox/poseidon/agents/behaviours/fishing/FishingAction.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import sim.util.Int2D;
2323
import uk.ac.ox.poseidon.agents.behaviours.GridAction;
2424
import uk.ac.ox.poseidon.agents.vessels.Vessel;
25+
import uk.ac.ox.poseidon.biology.Bucket;
2526

2627
import java.time.Duration;
2728
import java.time.LocalDateTime;
@@ -37,5 +38,6 @@ public FishingAction(
3738
super(start, duration, vessel, cell);
3839
}
3940

40-
public abstract double getTotalBiomassCaught();
41+
public abstract Bucket<?> getFishCaught();
42+
4143
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* POSEIDON: an agent-based model of fisheries
3+
* Copyright (c) 2024 CoHESyS Lab [email protected]
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*
18+
*/
19+
20+
package uk.ac.ox.poseidon.agents.tables;
21+
22+
import tech.tablesaw.api.DateTimeColumn;
23+
import tech.tablesaw.api.StringColumn;
24+
import tech.tablesaw.api.Table;
25+
import uk.ac.ox.poseidon.agents.behaviours.Action;
26+
import uk.ac.ox.poseidon.io.tables.ListenerTable;
27+
28+
public abstract class ActionListenerTable<A extends Action> implements ListenerTable<A> {
29+
private final StringColumn vesselId = StringColumn.create("vessel_id");
30+
private final DateTimeColumn actionStart = DateTimeColumn.create("action_start");
31+
private final DateTimeColumn actionEnd = DateTimeColumn.create("action_end");
32+
33+
private final Table table =
34+
Table.create(
35+
vesselId,
36+
actionStart,
37+
actionEnd
38+
);
39+
40+
@Override
41+
public void receive(final A action) {
42+
actionStart.append(action.getStart());
43+
actionEnd.append(action.getEnd());
44+
vesselId.append(action.getVessel().getId());
45+
}
46+
47+
@Override
48+
public Table get() {
49+
return table;
50+
}
51+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* POSEIDON: an agent-based model of fisheries
3+
* Copyright (c) 2024 CoHESyS Lab [email protected]
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*
18+
*/
19+
20+
package uk.ac.ox.poseidon.agents.tables;
21+
22+
import tech.tablesaw.api.DoubleColumn;
23+
import tech.tablesaw.api.StringColumn;
24+
import uk.ac.ox.poseidon.agents.behaviours.fishing.FishingAction;
25+
import uk.ac.ox.poseidon.geography.grids.GridExtent;
26+
27+
public class FishingActionListenerTable extends GridActionListenerTable<FishingAction> {
28+
29+
private final StringColumn speciesCode = StringColumn.create("species_code");
30+
private final DoubleColumn biomassCaught = DoubleColumn.create("biomass_caught");
31+
32+
public FishingActionListenerTable(final GridExtent gridExtent) {
33+
super(gridExtent);
34+
get().addColumns(speciesCode, biomassCaught);
35+
}
36+
37+
@Override
38+
public void receive(final FishingAction fishingAction) {
39+
super.receive(fishingAction);
40+
fishingAction.getFishCaught().getMap().forEach((species, content) -> {
41+
speciesCode.append(species.getCode());
42+
biomassCaught.append(content.asBiomass().getValue());
43+
});
44+
}
45+
46+
@Override
47+
public Class<FishingAction> getEventClass() {
48+
return FishingAction.class;
49+
}
50+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* POSEIDON: an agent-based model of fisheries
3+
* Copyright (c) 2024 CoHESyS Lab [email protected]
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*
18+
*/
19+
20+
package uk.ac.ox.poseidon.agents.tables;
21+
22+
import lombok.AllArgsConstructor;
23+
import lombok.Getter;
24+
import lombok.NoArgsConstructor;
25+
import lombok.Setter;
26+
import uk.ac.ox.poseidon.agents.behaviours.fishing.FishingAction;
27+
import uk.ac.ox.poseidon.core.Factory;
28+
import uk.ac.ox.poseidon.core.Simulation;
29+
import uk.ac.ox.poseidon.geography.grids.GridExtent;
30+
import uk.ac.ox.poseidon.io.tables.ListenerTableFactory;
31+
32+
@Getter
33+
@Setter
34+
@NoArgsConstructor
35+
@AllArgsConstructor
36+
public class FishingActionListenerTableFactory
37+
extends ListenerTableFactory<FishingAction, FishingActionListenerTable> {
38+
39+
private Factory<? extends GridExtent> gridExtent;
40+
41+
@Override
42+
protected FishingActionListenerTable newTable(final Simulation simulation) {
43+
return new FishingActionListenerTable(gridExtent.get(simulation));
44+
}
45+
46+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* POSEIDON: an agent-based model of fisheries
3+
* Copyright (c) 2024 CoHESyS Lab [email protected]
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*
18+
*/
19+
20+
package uk.ac.ox.poseidon.agents.tables;
21+
22+
import com.vividsolutions.jts.geom.Coordinate;
23+
import tech.tablesaw.api.DoubleColumn;
24+
import uk.ac.ox.poseidon.agents.behaviours.GridAction;
25+
import uk.ac.ox.poseidon.geography.grids.GridExtent;
26+
27+
public abstract class GridActionListenerTable<A extends GridAction> extends ActionListenerTable<A> {
28+
private final GridExtent gridExtent;
29+
private final DoubleColumn lon = DoubleColumn.create("lon");
30+
private final DoubleColumn lat = DoubleColumn.create("lat");
31+
32+
public GridActionListenerTable(final GridExtent gridExtent) {
33+
super();
34+
get().addColumns(lon, lat);
35+
this.gridExtent = gridExtent;
36+
}
37+
38+
@Override
39+
public void receive(final A action) {
40+
super.receive(action);
41+
final Coordinate coordinate = gridExtent.toCoordinate(action.getCell());
42+
lon.append(coordinate.x);
43+
lat.append(coordinate.y);
44+
}
45+
}

core/src/main/java/uk/ac/ox/poseidon/core/time/DistributedDurationSupplier.java core/src/main/java/uk/ac/ox/poseidon/core/time/DurationSupplier.java

+3-4
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,18 @@
2020
package uk.ac.ox.poseidon.core.time;
2121

2222
import lombok.RequiredArgsConstructor;
23-
import sim.util.distribution.AbstractDistribution;
2423

2524
import java.time.Duration;
2625
import java.util.function.Supplier;
2726

2827
@RequiredArgsConstructor
29-
public class DistributedDurationSupplier implements Supplier<Duration> {
28+
public class DurationSupplier implements Supplier<Duration> {
3029

31-
private final AbstractDistribution distribution;
30+
private final Supplier<Long> secondsSupplier;
3231

3332
@Override
3433
public Duration get() {
35-
return Duration.ofSeconds(distribution.nextInt());
34+
return Duration.ofSeconds(secondsSupplier.get());
3635
}
3736

3837
}

core/src/main/java/uk/ac/ox/poseidon/core/time/ExponentiallyDistributedDurationSupplierFactory.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,13 @@ public class ExponentiallyDistributedDurationSupplierFactory
4242

4343
@Override
4444
protected Supplier<Duration> newInstance(final Simulation simulation) {
45-
return new DistributedDurationSupplier(
45+
final Exponential exponential =
4646
new Exponential(
4747
1.0 / meanDuration.get(simulation).getSeconds(),
4848
simulation.random
49-
)
49+
);
50+
return new DurationSupplier(
51+
() -> (long) (1 + exponential.nextInt())
5052
);
5153
}
5254
}

examples/src/main/java/uk/ac/ox/poseidon/examples/BasicScenario.java

+14-19
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import lombok.Setter;
2424
import sim.engine.Steppable;
2525
import sim.util.Int2D;
26+
import tech.tablesaw.api.Table;
2627
import uk.ac.ox.poseidon.agents.behaviours.BackToInitialBehaviourFactory;
2728
import uk.ac.ox.poseidon.agents.behaviours.WaitBehaviourFactory;
2829
import uk.ac.ox.poseidon.agents.behaviours.choices.BestOptionsFromFriendsSupplierFactory;
@@ -39,6 +40,7 @@
3940
import uk.ac.ox.poseidon.agents.registers.Register;
4041
import uk.ac.ox.poseidon.agents.registers.RegisterFactory;
4142
import uk.ac.ox.poseidon.agents.registers.RegisteringFactory;
43+
import uk.ac.ox.poseidon.agents.tables.FishingActionListenerTableFactory;
4244
import uk.ac.ox.poseidon.agents.vessels.RandomHomePortFactory;
4345
import uk.ac.ox.poseidon.agents.vessels.VesselFactory;
4446
import uk.ac.ox.poseidon.agents.vessels.VesselScopeFactory;
@@ -50,7 +52,6 @@
5052
import uk.ac.ox.poseidon.core.Factory;
5153
import uk.ac.ox.poseidon.core.GlobalScopeFactory;
5254
import uk.ac.ox.poseidon.core.Scenario;
53-
import uk.ac.ox.poseidon.core.Simulation;
5455
import uk.ac.ox.poseidon.core.schedule.ScheduledRepeatingFactory;
5556
import uk.ac.ox.poseidon.core.schedule.SteppableSequenceFactory;
5657
import uk.ac.ox.poseidon.core.suppliers.PoissonIntSupplierFactory;
@@ -72,7 +73,9 @@
7273

7374
import java.nio.file.Path;
7475
import java.time.LocalDate;
76+
import java.time.Period;
7577
import java.util.List;
78+
import java.util.function.Supplier;
7679

7780
@SuppressWarnings("MagicNumber")
7881
@Getter
@@ -84,9 +87,9 @@ public class BasicScenario extends Scenario {
8487
private Factory<? extends Species> speciesA = new SpeciesFactory("A");
8588
private Factory<? extends Species> speciesB = new SpeciesFactory("B");
8689
private Factory<? extends BiomassDiffusionRule> biomassDiffusionRule =
87-
new SmoothBiomassDiffusionRuleFactory(0.001, 0.01);
90+
new SmoothBiomassDiffusionRuleFactory(0.01, 0.01);
8891
private Factory<? extends BiomassGrowthRule> biomassGrowthRule =
89-
new LogisticGrowthRuleFactory(0.7);
92+
new LogisticGrowthRuleFactory(0.1);
9093

9194
private GlobalScopeFactory<? extends GridExtent> gridExtent =
9295
new GridExtentFactory(
@@ -97,6 +100,8 @@ public class BasicScenario extends Scenario {
97100
-5,
98101
5
99102
);
103+
private Factory<? extends Supplier<Table>> catchTable =
104+
new FishingActionListenerTableFactory(gridExtent);
100105
private Factory<? extends VesselField> vesselField = new VesselFieldFactory(gridExtent);
101106
private Factory<? extends Distance> distance = new EquirectangularDistanceFactory(gridExtent);
102107
private Factory<? extends BathymetricGrid> bathymetricGrid =
@@ -117,7 +122,6 @@ public class BasicScenario extends Scenario {
117122
3,
118123
2
119124
);
120-
121125
private Factory<? extends GridPathFinder> pathFinder =
122126
new DefaultPathFinderFactory(
123127
bathymetricGrid,
@@ -200,20 +204,20 @@ public class BasicScenario extends Scenario {
200204
),
201205
new ChooseDestinationBehaviourFactory(
202206
new EpsilonGreedyDestinationSupplierFactory(
203-
0.2,
207+
0.25,
204208
optionValues,
205209
new NeighbourhoodGridExplorerFactory(
206210
optionValues,
207211
pathFinder,
208212
new ShiftedIntSupplierFactory(
209-
new PoissonIntSupplierFactory(5),
213+
new PoissonIntSupplierFactory(1),
210214
1
211215
)
212216
),
213217
new ImitatingPickerFactory<>(
214218
optionValues,
215219
new BestOptionsFromFriendsSupplierFactory<>(
216-
2,
220+
5,
217221
optionValuesRegister
218222
)
219223
),
@@ -222,7 +226,7 @@ public class BasicScenario extends Scenario {
222226
new TravelAlongPathBehaviourFactory(
223227
new DefaultFishingBehaviourFactory<>(
224228
new FixedBiomassProportionGearFactory(
225-
0.05,
229+
0.1,
226230
new DurationFactory(0, 1, 0, 0)
227231
),
228232
new VoidHoldFactory<>(),
@@ -263,16 +267,7 @@ public static void main(final String[] args) {
263267
scenario,
264268
Path.of("/home/nicolas/Desktop/scenario.yaml")
265269
);
266-
final Simulation simulation = scenario.newSimulation();
267-
simulation.start();
268-
while (
269-
simulation
270-
.getTemporalSchedule()
271-
.getDateTime()
272-
.isBefore(LocalDate.of(LocalDate.now().getYear() + 10, 1, 1).atStartOfDay())
273-
) {
274-
simulation.schedule.step(simulation);
275-
}
276-
simulation.finish();
270+
new QuickRunner(scenario).runFor(Period.ofYears(1));
271+
277272
}
278273
}

0 commit comments

Comments
 (0)