22 * POSEIDON, an agent-based model of fisheries
33 * Copyright (C) 2024 CoHESyS Lab [email protected] 44 *
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.
5+ * This program is free software: you can redistribute it and/or modify it under the terms of the
6+ * GNU General Public License as published by the Free Software Foundation, either version 3
7+ * of the License, or (at your option) any later version.
98 *
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.
9+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11+ * See the GNU General Public License for more details.
1412 *
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/>.
13+ * You should have received a copy of the GNU General Public License along with this program.
14+ * If not, see <http://www.gnu.org/licenses/>.
1715 */
1816
1917package uk .ac .ox .poseidon .epo .calibration ;
2018
2119import com .beust .jcommander .JCommander ;
2220import com .beust .jcommander .Parameter ;
2321import com .beust .jcommander .converters .PathConverter ;
24- import com .google .common .collect .ImmutableList ;
2522import com .google .common .collect .ImmutableMap ;
2623import com .google .common .collect .ImmutableSet ;
2724import uk .ac .ox .oxfish .experiments .tuna .Runner ;
2825import uk .ac .ox .oxfish .fisher .purseseiner .fads .AbundanceFadAttractionEvent ;
2926import uk .ac .ox .oxfish .fisher .purseseiner .fads .FadManager ;
30- import uk .ac .ox .oxfish .maximization .GenericOptimization ;
31- import uk .ac .ox .oxfish .maximization .SolutionExtractor ;
3227import uk .ac .ox .oxfish .maximization .YearlyResultsRowProvider ;
3328import uk .ac .ox .oxfish .model .FishState ;
3429import uk .ac .ox .oxfish .model .data .monitors .loggers .AbundanceFadAttractionEventObserver ;
3530import uk .ac .ox .oxfish .model .scenario .Scenario ;
31+ import uk .ac .ox .oxfish .utility .yaml .FishYAML ;
3632
33+ import java .io .File ;
3734import java .io .FileNotFoundException ;
35+ import java .io .FileReader ;
3836import java .io .IOException ;
39- import java .nio .file .Files ;
4037import java .nio .file .Path ;
41- import java .nio .file .Paths ;
4238import java .util .Set ;
4339import java .util .concurrent .atomic .AtomicInteger ;
44- import java .util .stream .Stream ;
4540
46- import static com .google .common .base .Preconditions .checkState ;
47- import static com .google .common .collect .ImmutableList .toImmutableList ;
48- import static com .google .common .io .Files .getFileExtension ;
41+ import static com .google .common .base .Preconditions .checkNotNull ;
4942import static java .lang .Runtime .getRuntime ;
5043
5144public class Evaluator implements Runnable {
@@ -67,20 +60,10 @@ public class Evaluator implements Runnable {
6760 @ Parameter (converter = PathConverter .class )
6861 private Path calibrationFolder ;
6962
70- private static Scenario makeScenario (
71- final GenericOptimization optimization ,
72- final double [] optimalParameters
73- ) {
74- try {
75- return GenericOptimization .buildScenario (
76- optimalParameters ,
77- Paths .get (optimization .getScenarioFile ()).toFile (),
78- optimization .getParameters ()
79- );
80- } catch (final FileNotFoundException e ) {
81- throw new IllegalStateException (e );
82- }
83- }
63+ // If `scenarioFile` is not provided, the Evaluator will extract a scenario from
64+ // the calibration log and write it back to `calibrated_scenario.yaml`.
65+ @ Parameter (names = {"-s" , "--scenario" }, converter = PathConverter .class )
66+ private Path scenarioFile ;
8467
8568 public static void main (final String [] args ) {
8669
@@ -93,29 +76,12 @@ public static void main(final String[] args) {
9376 evaluator .run ();
9477 }
9578
96- private static Path findCalibrationFile (final Path folder ) {
97- try (final Stream <Path > paths = Files .list (folder )) {
98- final ImmutableList <Path > calibrationFiles = paths
99- .filter (path -> getFileExtension (path .toString ()).equals ("yaml" ))
100- .filter (Evaluator ::isCalibrationFile )
101- .collect (toImmutableList ());
102- checkState (!calibrationFiles .isEmpty (), "No calibration files found in %s" , folder );
103- checkState (calibrationFiles .size () == 1 , "More than one calibration files found in %s" , folder );
104- return calibrationFiles .get (0 );
105- } catch (final IOException e ) {
106- throw new IllegalStateException (e );
107- }
79+ public Path getScenarioFile () {
80+ return scenarioFile ;
10881 }
10982
110- private static boolean isCalibrationFile (final Path path ) {
111- try (final Stream <String > lines = Files .lines (path )) {
112- return lines
113- .findFirst ()
114- .filter (line -> line .equals ("!!uk.ac.ox.oxfish.maximization.GenericOptimization" ))
115- .isPresent ();
116- } catch (final IOException e ) {
117- throw new IllegalStateException (e );
118- }
83+ public void setScenarioFile (final Path scenarioFile ) {
84+ this .scenarioFile = scenarioFile ;
11985 }
12086
12187 @ SuppressWarnings ("unused" )
@@ -141,14 +107,13 @@ public void setCalibrationFolder(final Path calibrationFolder) {
141107 @ Override
142108 public void run () {
143109
144- final Path calibrationFilePath = findCalibrationFile ( calibrationFolder );
145- final Path logFilePath = calibrationFolder . resolve ( "calibration_log.md" );
146- final double [] solution = new SolutionExtractor ( logFilePath ). bestSolution (). getKey ();
147- final GenericOptimization optimization = GenericOptimization . fromFile ( calibrationFilePath );
110+ final Scenario scenario =
111+ scenarioFile == null
112+ ? new ScenarioExtractor ( calibrationFolder ). getAndWriteToFile ( "calibrated_scenario.yaml" )
113+ : loadScenario ( );
148114
149115 final Runner <Scenario > runner =
150- new Runner <>(() -> makeScenario (optimization , solution ), calibrationFilePath .getParent ())
151- .writeScenarioToFile ("calibrated_scenario.yaml" )
116+ new Runner <>(() -> scenario , calibrationFolder )
152117 .setParallel (parallel )
153118 .registerRowProvider ("yearly_results.csv" , YearlyResultsRowProvider ::new )
154119 .requestFisherYearlyData ();
@@ -169,6 +134,20 @@ public void run() {
169134 .run (numYearsToRuns , 1 , runCounter );
170135 }
171136
137+ private Scenario loadScenario () {
138+ checkNotNull (this .calibrationFolder );
139+ checkNotNull (this .scenarioFile );
140+ final File scenarioFile = calibrationFolder .resolve (this .scenarioFile ).toFile ();
141+ try (final FileReader fileReader = new FileReader (scenarioFile )) {
142+ final FishYAML fishYAML = new FishYAML ();
143+ return fishYAML .loadAs (fileReader , Scenario .class );
144+ } catch (final FileNotFoundException e ) {
145+ throw new IllegalArgumentException ("Can't find scenario file: " + scenarioFile , e );
146+ } catch (final IOException e ) {
147+ throw new IllegalStateException ("Error while reading file: " + scenarioFile , e );
148+ }
149+ }
150+
172151 private void registerFadAttractionEventProviders (final Runner <Scenario > runner ) {
173152 runner .setAfterStartConsumer (state -> {
174153 final FishState fishState = state .getModel ();
0 commit comments