Ne serait-il pas plus "user-friendly" de "délier" le changement de classe et la saison et de le lier à un (ou des) mois (désolé Benjamin, c'est pas "programmer-friendly")? L'utilisateur cocherait les mois où il veut un changement de classe et remplirait la matrice correspondant si structuré en longueur. * Certes on fait l'hypothèse que au cours d'une saison, les processus biologiques sont sensés être uniforme mais parfois il est plus facile de ne mettre qu'une seule croissance pour toute une saison même si l'on est structuré en longueur (il semble me souvenir qu'on n'avait eu un pb de ce type avec Maga l'an dernier: un calcul assez horrible de proba de mue à chacun de mois combiné à une proba d'incréments de croissance >:o ). Maintenant qu'on peut importer des matrices via de fichiers texte, c'est plus très compliqué de recopier la même matrice si on veut l'applique à tous les mois de la saison * Avec la solution de Stéphanie, si on veut chipoter, si la pop est structuré en âge, qu'on veutr faire un changement de groupe en avril alors qu'on a une saison mars-juin... * Au moins l'utilisateur ne se poserait plus les questions qu'à peu près tous les utilisateurs ont posées: "quand je clique, est-ce que ça s'applique à tous les mois ou seulement au premier de la saison? que faut-il faire pour les pop en âge? A+ Hilaire Stephanie MAHEVAS a écrit :
voila la modif dont je parlais dans mon precedent mail.
Changement a faire pour eviter a celui qui definit une pop en age de devoir definir une saison d'un mois pour le changement de classe.
Avec Hilaire, on a modifie le DefaultSimulator (il a ete teste sur la pecherie DemoRegion) - il faudrait integrer le lignes 334 a 367 dans ton dernier defaultSimulator.
Petite explication: Dans le default simulator actuel, il n'y a pas de difference entre une pop en age et en longueur pour CA. Pendant une saison, CA s'applique a chaque mois de la saison. Donc on a ajoute un test pour savoir s'il s'agissait d'une pop en age et en longueur et on applique CA dans le cas d'une pop en age uniquement si on est dans une saison avec changement de groupe et si c'est le premier mois de la saison. En fait, pour l'utilisateur rien ne change il coche la saison au cours de laquelle la population passe dans le groupe d'age suivant (traditionnellement janvier mais libre a l'utilisateur de choisir un autre mois) et ce changement n'a lieu qu'au premier mois de la saison.
A METTRE DANS LE MANUEL
merci a+ stephanie
Stephanie MAHEVAS a écrit :
Salut
je viens de m'apercevoir que les choses ne se passaient pas exactement comme voulu a date = 0. Intuitivement pour chaque population on mettait les effectifs initiaux dans la zone et dans le groupe ou ils seront à t+epsilon. Or dans default.simulator, a date =0, il n'y a pas de croissance (ca c'est ok) mais il y a les migrations (incluant emigrations et immigrations), or ca c'etait ce que l'on avait prevu. Ca n'a aucune incidence pour les especes qui ne se deplacent pas en janvier et encore moins pour les sedentaires. J'en ai discute avec Hilaire (heureusement pour sa vieille appli, il etait conscient de ca et il avait mis des effectifs initiaux en coherence avec le default.simulator). On est arrive a la conclusion suivante : pour avoir des vecteurs d'abondance qui soient comparables entre les annees et que cela soit intuitif pour l'utilisateur (soit croissance + migration, soit rien), on propose de mettre le standard suivant: 1/ croissance et migration a date = 0 (ie enlever le si date=0 {CA=Id } else {CA =CA} et mettre uniquement CA= CA (quelque soit date) dans le default.simulator) 2/ mettre un gros warning dans l'interface en aide contextuelle "Les effectifs initaiux sont les effectifs initiaux en fin decembre avant croissance et migration du mois de janvier". (CE DERNIER MESSAGE EST A RAJOUTER DANS LE MANUEL-COMMENT LANCER UNE SIMULATION)
Dominique ca te convient?
a+ stephanie
------------------------------------------------------------------------
/* *##% * Copyright (C) 2006 * Ifremer, Code Lutin, C?dric Pineau, Benjamin Poussin * * 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 2 * 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *##%*/
/* * * DefaultSimulator.java * * Created: 21 ao?t 2006 10:57:46 * * @author poussin * @version $Revision: 1.16 $ * * Last update: $Date: 2007/06/07 16:24:00 $ * by : $Author: bpoussin $ */
package simulators;
import static org.codelutin.i18n.I18n._; import static org.codelutin.i18n.I18n.n_;
import java.util.Collection; import java.util.List;
import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.codelutin.math.matrix.MatrixFactory; import org.codelutin.math.matrix.MatrixND; import org.codelutin.topia.TopiaContext; import org.codelutin.topia.TopiaException;
import scripts.GravityModel; import scripts.ResultName; import scripts.SiMatrix; import fr.ifremer.isisfish.IsisFishException; import fr.ifremer.isisfish.datastore.ResultStorage; import fr.ifremer.isisfish.entities.Metier; import fr.ifremer.isisfish.entities.Population; import fr.ifremer.isisfish.entities.PopulationSeasonInfo; import fr.ifremer.isisfish.entities.Zone; import fr.ifremer.isisfish.rule.Rule; import fr.ifremer.isisfish.simulator.MetierMonitor; import fr.ifremer.isisfish.simulator.PopulationMonitor; import fr.ifremer.isisfish.simulator.RuleMonitor; import fr.ifremer.isisfish.simulator.SimulationContext; import fr.ifremer.isisfish.simulator.SimulationControl; import fr.ifremer.isisfish.simulator.SimulationParameter; import fr.ifremer.isisfish.simulator.Simulator; import fr.ifremer.isisfish.types.Date; import fr.ifremer.isisfish.types.Month;
/** * @author poussin * */
public class DefaultSimulator implements Simulator {
/** to use log facility, just put in your code: log.info("..."); */ static private Log log = LogFactory.getLog(DefaultSimulator.class);
/** * Called by isis don't modify signature */ public void simulate(SimulationContext context) throws Exception {
SimulationParameter param = context.getSimulationStorage().getParameter(); SimulationControl control = context.getSimulationControl(); int lastYear = param.getNumberOfYear(); int lastDate = lastYear * Month.NUMBER_OF_MONTH; Date date = control.getDate(); control.setProgressMax(lastDate);
ResultStorage resManager = context.getSimulationStorage().getResultStorage(); TopiaContext db = context.getDB();
SiMatrix siMatrix = new SiMatrix(context); GravityModel gravityModel = new GravityModel(context, siMatrix);
PopulationMonitor populationMonitor = context.getPopulationMonitor(); MetierMonitor metierMonitor = context.getMetierMonitor(); RuleMonitor ruleMonitor = context.getRuleMonitor();
for (Population pop : siMatrix.getPopulations(date)) { MatrixND N = param.getNumberOf(pop); N.setName(ResultName.MATRIX_ABUNDANCE); populationMonitor.setN(pop, N); }
// // Rule initialisation // List<Rule> rules = param.getRules(); control.setText("Rules initialisation:" + rules); for (Rule rule : rules) { rule.init(context); log.info("Rule " +rule.getClass().getSimpleName()+ " initialized"); }
// // Commit all change done un init rules methods. // context.getDB().commitTransaction();
// // Simulation loop // while (date.getDate() < lastDate) { // // if user stop simulation before last year // if (control.isStopSimulationRequest()) { break; }
control.setDate(date); control.setProgress(date.getDate()); control.setText(_("begin step " + date));
// raz des metiers interdits et des licences metierMonitor.clear();
if (date.getMonth().equals(Month.JANUARY)) { populationMonitor.clearCatch(); }
if (resManager.isEnabled(ResultName.MATRIX_NO_ACTIVITY)) { MatrixND mat = metierMonitor.getOrCreateNoActivity(date, ResultName.MATRIX_NO_ACTIVITY, siMatrix.getStrategies(date), siMatrix.getMetiers(date)); resManager.addResult(date, mat); }
// // Rule condition evaluation // control.setText("Evalute Rules conditions"); for (Rule rule : rules) { for (Metier metier : siMatrix.getMetiers(date)) { boolean active = false; try { active = rule.condition(context, date, metier); } catch (Exception eee) { if (log.isWarnEnabled()) { log.warn("Can't evaluate rule condition for: " + rule, eee); } } ruleMonitor.setEvaluationCondition(date, rule, metier, active); if (active) { log.info("Activate rule: " + rule.getClass().getSimpleName()); resManager.addActiveRule(date, rule); } } }
// // Rule pre action // control.setText("Do pre action Rules"); for (Rule rule : rules) { for (Metier metier : siMatrix.getMetiers(date)) { boolean condition = ruleMonitor.getEvalutionCondition(date, rule, metier); if (condition) { rule.preAction(context, date, metier); } } }
// // Keep modification's information done in rule // if (resManager.isEnabled(ResultName.MATRIX_METIER_ZONE)) { MatrixND metierZone = siMatrix.getMetierZone(date); resManager.addResult(date, metierZone); }
// // Simulate one step for all pop // control.setText("Simulate one month"); for (Population pop : siMatrix.getPopulations(date)) { computeMonth(context, siMatrix, date, pop); }
// // Add some result not population dependante // control.setText("Add some results"); if (resManager.isEnabled(ResultName.MATRIX_EFFORT_PER_STRATEGY_MET)) { MatrixND effortPerStrategyMet = siMatrix.matrixEffortPerStrategyMet(date); resManager.addResult(date, effortPerStrategyMet); }
if (resManager.isEnabled(ResultName.MATRIX_STD_TRAVEL_EFFORT_PER_STRATEGY_MET)) { MatrixND stdTravelEffortPerStrategyMet = siMatrix.matrixEffortPerStrategyMet(date); resManager.addResult(date, stdTravelEffortPerStrategyMet); }
if (resManager.isEnabled(ResultName.MATRIX_EFFORT_PER_ZONE_POP)) { MatrixND effortPerZonePop = siMatrix.matrixEffortPerStrategyMet(date); resManager.addResult(date, effortPerZonePop); }
// // Add economics results // if (resManager.isEnabled(ResultName.MATRIX_PRICE)) { for (Population pop : siMatrix.getPopulations(date)) { MatrixND matPrice = siMatrix.matrixPrice(date, pop); resManager.addResult(date, pop, matPrice); } }
if (!"false".equalsIgnoreCase(param.getTagValue().get("ecoResult"))) { control.setText("Add economics results"); saveGravityModel(date, resManager, gravityModel); }
// // Rule post action // control.setText("Do post action Rules"); for (Rule rule : rules) { for (Metier metier : siMatrix.getMetiers(date)) { if (ruleMonitor.getEvalutionCondition(date, rule, metier)) { rule.postAction(context, date, metier); } } }
// discard and landing must be done after post action rules control.setText("Compute discard and landing"); for (Population pop : siMatrix.getPopulations(date)) { // // discard computation // MatrixND discard = populationMonitor.getDiscard(date, pop); if (discard != null || date.getDate() == 0) { // force discard for the first month to have discard in result if (discard == null) { discard = MatrixFactory.getInstance().create(ResultName.MATRIX_DISCARDS_PER_STR_MET, new List[]{siMatrix.getStrategies(date), siMatrix.getMetiers(date), pop.getPopulationGroup(), pop.getPopulationZone()}, new String[]{n_("Strategies"), n_("Metiers"), n_("Groups"), n_("Zones")}); } resManager.addResult(date, pop, discard);
if (resManager.isEnabled(ResultName.MATRIX_DISCARDS_WEIGHT_PER_STR_MET)) { MatrixND discardWeightPerStrategyMet = siMatrix.matrixDiscardWeightPerStrategyMet(pop, date, discard); resManager.addResult(date, pop, discardWeightPerStrategyMet); }
}
// // add landing result // if (resManager.isEnabled(ResultName.MATRIX_LANDING_PER_MET)) { MatrixND landing = MatrixFactory.getInstance().create(populationMonitor.getCatch(pop)); if (discard != null) { landing = landing.minus(discard); } landing.setName(ResultName.MATRIX_LANDING_PER_MET); resManager.addResult(date, pop, landing); } }
// // revert modification for next step // control.setText("Rollback rules changes"); db.rollbackTransaction();
// // commit result // control.setText("Commit results"); TopiaContext tx = context.getDbResult(); tx.commitTransaction();
// // Go next step // date = date.next(); } }
protected void computeMonth(SimulationContext context, SiMatrix siMatrix, Date date, Population pop) throws IsisFishException, TopiaException { // to add result ResultStorage resManager = context.getSimulationStorage().getResultStorage();
PopulationMonitor popMon = context.getPopulationMonitor(); MatrixND N = popMon.getN(pop);
if (log.isInfoEnabled()) { log.info("====================== begin "+ date + " - " + pop +" ==========================="); log.info("N: " + N); }
// add N and biomass result now, before computation // N is reassigned during computation resManager.addResult(date, pop, N);
if (resManager.isEnabled(ResultName.MATRIX_BIOMASS)) { MatrixND biomass = siMatrix.matrixBiomass(N, pop, date); resManager.addResult(date, pop, biomass); }
Month month = date.getMonth(); PopulationSeasonInfo info = pop.getPopulationSeasonInfo(month);
// group change MatrixND CA = null;
if (info.getGroupChange() || !pop.getSpecies().getAgeGroupType()){ CA = info.getGroupChangeMatrix(month); }
log.debug("CA: " + CA);
//migration MatrixND M = info.getMigrationMatrix(month, N); log.debug("M: " + M); //emigration MatrixND EM = info.getEmigrationMatrix(month, N); log.debug("EM: " + EM); //immigration MatrixND IM = info.getImmigrationMatrix(month, N).transpose(); log.debug("IM: " + IM);
// pour les premiers calculs on met N en une matrice 1D MatrixND N1D = pop.N2DToN1D(N); log.debug("N1D: " + N1D);
MatrixND tmp0 = N1D.copy();
if (pop.getSpecies().getAgeGroupType()){ if (info.getGroupChange() && info.getFirstMonth().equals(month)){ System.out.println(pop.getName()+" "+month+" changement de classe"); System.out.println(CA); tmp0 = N1D.mult(CA); } } else if (!pop.getSpecies().getAgeGroupType()){ System.out.println(pop.getName()+" "+month+" changement de classe"); System.out.println(CA); tmp0 = N1D.mult(CA); } MatrixND tmp1 = M.minus(EM); MatrixND tmp2 = tmp0.mult(tmp1); MatrixND tmp3 = tmp2.add(IM);
log.debug("N1D after mig: " + tmp3);
// On reconvertie en une matrice Semantique N = pop.split2D(tmp3);
log.debug("N after mig: " + N);
//Recrutement MatrixND R = info.getReproductionMatrix(month, N); log.debug("R: " + R);
// ajout de la matrice R dans le suivi de la pop comme etant // la reproduction pour le mois courant. popMon.setReproduction(date, pop, R);
// recrutement MatrixND recruitment = popMon.getRecruitment(date, pop); log.debug("recruitment: " + recruitment);
// mortalite de la reproduction popMon.applyReproductionMortality(pop);
N = N.add(recruitment); log.debug("N after recru: " + N);
// compute some Matrix and add result MatrixND abundance = siMatrix.matrixAbundance(N, pop, date);
// this matrix is necessary for matrixCatchPerStrategyMet MatrixND catchRatePerStrategyMet = siMatrix.matrixCatchRatePerStrategyMet(pop, date); resManager.addResult(date, pop, catchRatePerStrategyMet);
// this matrix is necessary for PopulationMonitor.holdCatch (reused in rule) MatrixND catchPerStrategyMet = siMatrix.matrixCatchPerStrategyMet(N, pop, date, catchRatePerStrategyMet); popMon.holdCatch(pop, catchPerStrategyMet); resManager.addResult(date, pop, catchPerStrategyMet);
if (resManager.isEnabled(ResultName.MATRIX_CATCH_WEIGHT_PER_STRATEGY_MET)) { MatrixND catchWeightPerStrategyMet = siMatrix.matrixCatchWeightPerStrategyMet(pop, date, catchPerStrategyMet); resManager.addResult(date, pop, catchWeightPerStrategyMet); }
log.debug("abundance: " + abundance);
// Keep new N popMon.setN(pop, abundance);
log.debug("====================== end " + date + " - " + pop +" ===========================");
}
/** * @param date * @param resManager * @throws IsisFishException * @throws TopiaException */ private void saveGravityModel(Date date, ResultStorage resManager, GravityModel gravityModel) throws IsisFishException, TopiaException { if (resManager.isEnabled(ResultName.MATRIX_FISHING_TIME_PER_MONTH_PER_VESSEL)) { MatrixND mat = gravityModel.matrixFishingTimePerMonthPerVessel(date); resManager.addResult(date, mat); } if (resManager.isEnabled(ResultName.MATRIX_FUEL_COSTS_OF_TRAVEL_PER_VESSEL)) { MatrixND mat = gravityModel.matrixFuelCostsOfTravelPerVessel(date); resManager.addResult(date, mat); } if (resManager.isEnabled(ResultName.MATRIX_COSTS_OF_FISHING_PER_VESSEL)) { MatrixND mat = gravityModel.matrixCostsOfFishingPerVessel(date); resManager.addResult(date, mat); } if (resManager.isEnabled(ResultName.MATRIX_FUEL_COSTS_PER_VESSEL)) { MatrixND mat = gravityModel.matrixFuelCostsOfTravelPerVessel(date); resManager.addResult(date, mat); } if (resManager.isEnabled(ResultName.MATRIX_REPAIR_AND_MAINTENANCE_GEAR_COSTS_PER_VESSEL)) { MatrixND mat = gravityModel.matrixRepairAndMaintenanceGearCostsPerVessel(date); resManager.addResult(date, mat); } if (resManager.isEnabled(ResultName.MATRIX_OTHER_RUNNING_COSTS_PER_VESSEL)) { MatrixND mat = gravityModel.matrixOtherRunningCostsPerVessel(date); resManager.addResult(date, mat); } if (resManager.isEnabled(ResultName.MATRIX_SHARED_NOT_FIXED_COSTS_PER_VESSEL)) { MatrixND mat = gravityModel.matrixSharedNotFixedCostsPerVessel(date); resManager.addResult(date, mat); } // if (resManager.isEnabled(ResultName.MATRIX_SHARED_FIXED_COSTS_PER_VESSEL_PER_MET)) { // MatrixND mat = gravityModel.matrixSharedFixedCostsPerVesselPerMet(date); // resManager.addResult(date, mat); // } if (resManager.isEnabled(ResultName.MATRIX_GROSS_VALUE_OF_LANDINGS_PER_SPECIES_PER_STRATEGY_MET)) { MatrixND mat = gravityModel.matrixGrossValueOfLandingsPerSpeciesPerStrategyMet(date); resManager.addResult(date, mat); } if (resManager.isEnabled(ResultName.MATRIX_GROSS_VALUE_OF_LANDINGS_PER_STRATEGY_MET)) { MatrixND mat = gravityModel.matrixGrossValueOfLandingsPerStrategyMet(date); resManager.addResult(date, mat); } if (resManager.isEnabled(ResultName.MATRIX_GROSS_VALUE_OF_LANDINGS_PER_STRATEGY_MET_PER_VESSEL)) { MatrixND mat = gravityModel.matrixGrossValueOfLandingsPerStrategyMetPerVessel(date); resManager.addResult(date, mat); } if (resManager.isEnabled(ResultName.MATRIX_NET_VALUE_OF_LANDINGS_PER_STRATEGY_MET)) { MatrixND mat = gravityModel.matrixNetValueOfLandingsPerStrategyMet(date); resManager.addResult(date, mat); } if (resManager.isEnabled(ResultName.MATRIX_NET_VALUE_OF_LANDINGS_PER_STRATEGY_MET_PER_VESSEL)) { MatrixND mat = gravityModel.matrixNetValueOfLandingsPerStrategyMetPerVessel(date); resManager.addResult(date, mat); } if (resManager.isEnabled(ResultName.MATRIX_NET_RENEVUE_TO_SHARE_PER_STRATEGY_MET_PER_VESSEL)) { MatrixND mat = gravityModel.matrixNetRenevueToSharePerStrategyMetPerVessel(date); resManager.addResult(date, mat); } if (resManager.isEnabled(ResultName.MATRIX_CREW_SHARE_PER_STRATEGY_MET_PER_VESSEL)) { MatrixND mat = gravityModel.matrixCrewSharePerStrategyMetPerVessel(date); resManager.addResult(date, mat); } if (resManager.isEnabled(ResultName.MATRIX_OWNER_MARGIN_OVER_VARIABLE_COSTS_PER_STRATEGY_MET_PER_VESSEL)) { MatrixND mat = gravityModel.matrixOwnerMarginOverVariableCostsPerStrategyMetPerVessel(date); resManager.addResult(date, mat); } if (resManager.isEnabled(ResultName.MATRIX_VESSEL_MARGIN_OVER_VARIABLE_COSTS_PER_STRATEGY_MET_PER_VESSEL)) { MatrixND mat = gravityModel.matrixVesselMarginOverVariableCostsPerStrategyMetPerVessel(date); resManager.addResult(date, mat); } if (resManager.isEnabled(ResultName.MATRIX_OWNER_MARGIN_OVER_VARIABLE_COSTS_PER_STRATEGY_PER_VESSEL)) { MatrixND mat = gravityModel.matrixOwnerMarginOverVariableCostsPerStrategyPerVessel(date); resManager.addResult(date, mat); } if (resManager.isEnabled(ResultName.MATRIX_OWNER_MARGIN_OVER_VARIABLE_COSTS_PER_STRATEGY)) { MatrixND mat = gravityModel.matrixOwnerMarginOverVariableCostsPerStrategy(date); resManager.addResult(date, mat); } if (resManager.isEnabled(ResultName.MATRIX_VESSEL_MARGIN_OVER_VARIABLE_COSTS_PER_STRATEGY_PER_VESSEL)) { MatrixND mat = gravityModel.matrixVesselMarginOverVariableCostsPerStrategyPerVessel(date); resManager.addResult(date, mat); } if (resManager.isEnabled(ResultName.MATRIX_VESSEL_MARGIN_OVER_VARIABLE_COSTS_PER_STRATEGY)) { MatrixND mat = gravityModel.matrixVesselMarginOverVariableCostsPerStrategy(date); resManager.addResult(date, mat); } }
}
------------------------------------------------------------------------
_______________________________________________ Isis-fish-devel mailing list Isis-fish-devel@lists.labs.libre-entreprise.org http://lists.labs.libre-entreprise.org/mailman/listinfo/isis-fish-devel
-- Hilaire Drouineau IFREMER, département EMH Centre de Nantes - BP 21105 - 44311 Nantes Cedex 3 tel : +33 (0)2 40 37 42 12 - fax : +33 (0)2 40 37 40 75 email : hilaire.drouineau@ifremer.fr - web : http://www.ifremer.fr/emh **********************************************************************