/* * #%L * IsisFish data * %% * Copyright (C) 2006 - 2014 Ifremer, CodeLutin, * %% * 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 * . * #L% */ package rules; import fr.ifremer.isisfish.datastore.ResultStorage; import fr.ifremer.isisfish.entities.EffortDescription; import fr.ifremer.isisfish.entities.Metier; import fr.ifremer.isisfish.entities.MetierSeasonInfo; import fr.ifremer.isisfish.entities.Population; import fr.ifremer.isisfish.entities.PopulationGroup; import fr.ifremer.isisfish.entities.Result; import fr.ifremer.isisfish.entities.Species; import fr.ifremer.isisfish.entities.Strategy; import fr.ifremer.isisfish.entities.TargetSpecies; import fr.ifremer.isisfish.entities.Zone; import fr.ifremer.isisfish.rule.AbstractRule; import fr.ifremer.isisfish.simulator.PopulationMonitor; import fr.ifremer.isisfish.simulator.SimulationContext; import fr.ifremer.isisfish.types.Month; import fr.ifremer.isisfish.types.TimeStep; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.nuiton.math.matrix.MatrixFactory; import org.nuiton.math.matrix.MatrixIterator; import org.nuiton.math.matrix.MatrixND; import org.nuiton.topia.*; import org.nuiton.util.*; //import scripts.ResultName; import scripts.RuleUtil; import scripts.SiMatrix; import resultinfos.*; import fr.ifremer.isisfish.annotations.Doc; /** * Cette regles tient compte de la taille minimum des poissons capturable. * * Created: 30 novembre 2006 * * @author smahevas * @version $Revision: 1.1 $ * * Last update: $Date: 2007-01-24 18:25:34 $ by : $Author: bpoussin $ */ public class TACseries_Month_Metier_OptionLO extends AbstractRule { /** to use log facility, just put in your code: log.info("..."); */ static private Log log = LogFactory.getLog(TACseries_Month_Metier_OptionLO.class); @Doc(value = "Begin step") public TimeStep param_beginStep = new TimeStep(0); @Doc(value = "End date") public TimeStep param_endStep = new TimeStep(119); @Doc(value = "Affected population") public Population param_pop = null; @Doc(value = "Affected Metiers names separated by ; ") public String param_metNames = "LLS_ESP;OTB_ESP"; @Doc(value = "TAC allocation (as a ratio)") public double param_alloc = 0.6; @Doc(value = "TAC monthly allocation (as ratios separated by ;) ") public String param_monthAlloc = "0.6;0.3;0.1;0;0;0;0;0;0;0;0;0"; @Doc(value = "If 0, TAC is computed elsewhere, tacName must be filled to retrieve value, otherwise enter TAC in kg time series separated by ; for ISIS fleets") public String param_tacInKgs = "3000;6000"; @Doc(value = "If tacInKgs = 0, TAC is computed elsewhere and stored in simulation context into this name") public String param_tacName = ""; @Doc(value = "Proportion survival of discards") public double param_propSurvie = 0; @Doc(value = "Landings Obligation Implemented ?") public boolean param_LandingsObligation = false; public boolean param_DeMinimis = false; protected boolean affectation = false; int nbY = param_endStep.getYear() - param_beginStep.getYear()+1 ; protected double [] tacSeries = new double[nbY]; protected double [] monthAlloc = new double[12]; List listMetNames; List listMet = new ArrayList(); protected MatrixND TacPopMatrix; protected String[] necessaryResult = { // put here all necessary result for this rule MatrixCatchPerStrategyMetPerZonePop.NAME, MatrixLandingPerMet.NAME, MatrixLandingWeight.NAME, MatrixTacPerPop.NAME, MatrixDiscardsPerStrMetPerZonePop.NAME // ResultName.MATRIX_BIOMASS, // ResultName.MATRIX_NET_VALUE_OF_LANDINGS_PER_STRATEGY_MET, }; @Override public String[] getNecessaryResult() { return this.necessaryResult; } /** * Permet d'afficher a l'utilisateur une aide sur la regle. * * @return L'aide ou la description de la regle */ @Override public String getDescription() throws Exception { return "Implement Quota for the selected metiers using provided annual values. If TAc = 0, uses values from the simulationContext. Saves month when fishing stops in a matrix."; } /** * Appele au demarrage de la simulation, cette methode permet * d'initialiser des valeurs de la * * @param context La simulation pour laquelle on utilise cette regle */ @Override public void init(SimulationContext context) throws Exception { // Add TAC values to a vector indexed by TAC year (from TAC starting year on) String[] StrTacSeries = param_tacInKgs.split(";"); for ( int i = 0 ; i < StrTacSeries.length; i++) { tacSeries[i] = Double.parseDouble(StrTacSeries[i]); } // Add metier names to a list String[] StrMetNames = param_metNames.split(";"); listMetNames = new ArrayList(Arrays.asList(StrMetNames)); listMet = new ArrayList(); for(String metN : listMetNames) { listMet.add((Metier) context.getMetierDAO().findByName(metN)); } // Create vector of values of montly allocation String[] StrMonthAlloc = param_monthAlloc.split(";"); for ( int i = 0 ; i < StrMonthAlloc.length; i++) { monthAlloc[i] = Double.parseDouble(StrMonthAlloc[i]); } } /** * @param context * @param date * @param param_species * @param metier * @return */ private boolean isCaptureDate(TimeStep step, Species species, Metier metier) { MetierSeasonInfo info = metier.getMetierSeasonInfo(step.getMonth()); TargetSpecies target = info.getSpeciesTargetSpecies(species); boolean result; if (target != null) { result = true; } else { result = false; } return result; } /** * La condition qui doit etre vrai pour faire les actions. * * @param context la simulation pour lequel on utilise cette regle * @param step le pas de temps courant * @param metier le metier concerne * @return vrai si on souhaite que les actions soit faites */ @Override public boolean condition(SimulationContext context, TimeStep step, Metier metier) throws Exception { boolean result = false; //if(listMetNames.contains(metier.getName())){ // read species in current session param_pop = (Population) context.getDB().findByTopiaId( param_pop.getTopiaId()); if (step.before(param_beginStep)) { result = false; } else if (step.after(param_endStep)) { result = false; /*}else if(step.getMonth().equals(Month.JANUARY)){ // reinit priceSwitch at the beginning of each year context.setValue("priceSwitch"+param_pop.getName(),0); context.setValue("TACatteint"+param_pop.getName(),false); context.setValue(metier.getName()+param_pop.getName()+"flag",0); result = false; } else { // metier flag = 0 si pas concern par le TAC // metier flag = 1 si TAC atteint et rejet // metier flag = 2 si TAC atteint et interdit if(context.getValue(metier.getName()+param_pop.getName()+"flag") != null && (int) context.getValue(metier.getName()+param_pop.getName()+"flag")!=0){ // tac deja atteint cette annee et metier concerne result = true; }else { // TAC pas encore atteint jusqu ici, test step if(context.getValue("TACatteint"+param_pop.getName()+param_metNames)==null || !(Boolean) context.getValue("TACatteint"+param_pop.getName()+param_metNames)){ log.info( "TAC pas encore atteint jusqu ici, test"); // Retrieve TAC value and allocation to the set of metiers double TAC = 0; int tacYear = step.getYear() - param_beginStep.getYear(); if (tacSeries[tacYear] != 0){ TAC = tacSeries[tacYear]; }else if(context.getValue(param_tacName+param_pop.getName()) != null){ // TAC is computed elsewhere TAC = (Double) context.getValue(param_tacName+ param_pop.getName()); }else TAC = 0; TAC = TAC * param_alloc; // Compute current landings for the set of metiers double landings = 0; int year = step.getYear(); ResultStorage matResult = context.getSimulationStorage().getResultStorage(); for (TimeStep dat = new TimeStep(0); dat.before(step); dat = dat.next()) { if( dat.getYear() == year) { MatrixND mat = matResult.getMatrix(dat, param_pop, MatrixLandingWeight.NAME); double catchListMet = 0; List listMetAll = mat.getSemantic(1); for(Metier met : listMetAll) { if(listMetNames.contains(met.getName())){ listMet.add(met); } } for(Metier met : listMet){ landings += mat.getSubMatrix(1,met).sumAll(); } } } log.info("[TAC] landings = " + landings+ " >= TAC:" + TAC); if (landings >= TAC) { context.setValue("TACatteint"+param_pop.getName()+param_metNames,true); log.info("tac atteint for " +param_metNames); //---------------------------------------------------------------------------------------------------- // Store infos in MatrixTacPerPop // add the month when TAC was reached to Matrix TAC per pop TimeStep janCurYear = new TimeStep(year * 12); //MatrixND TacPopMatrix = matResult.getMatrix(janCurYear,param_metNames,param_pop, MatrixTacPerPop.NAME); MatrixND TacPopMatrix = MatrixFactory.getInstance().create( MatrixTacPerPop.NAME, new List[] { Arrays.asList(new String[]{"TAC","landings","MonthStopFishing"})}); TacPopMatrix.setValue("TAC", TAC); TacPopMatrix.setValue("landings", landings); TacPopMatrix.setValue("MonthStopFishing", step.getMonth().getMonthNumber()); matResult.addResult(janCurYear, param_metNames, param_pop, TacPopMatrix); } } // Le TAC est atteint if(context.getValue("TACatteint"+param_pop.getName()+param_metNames)!=null && (Boolean) context.getValue("TACatteint"+param_pop.getName()+param_metNames)){ result = true; if(param_LandingsObligation){ context.setValue("priceSwitch"+param_pop.getName(),1); if(param_DeMinimis){ // If met landed >0.05% of pop landings -> forbidden // compute landings per met and landings tot double quantMat = 0; double quantMatPop = 0; int year = step.getYear(); ResultStorage matResult = context.getSimulationStorage().getResultStorage(); SiMatrix siMatrix = SiMatrix.getSiMatrix(context); List Pops = context.getPopulationMonitor().getPopulations(); for (TimeStep dat = new TimeStep(0); dat.before(step); dat = dat.next()) { if( dat.getYear() == year) { for(Population pop:Pops){ MatrixND tmp = matResult.getMatrix(dat, pop,MatrixCatchPerStrategyMetPerZonePop.NAME); quantMat += tmp.getSubMatrix(1,metier,1).sumAll(); if (pop.getName().equals(param_pop.getName())){ quantMatPop += tmp.getSubMatrix(1,metier,1).sumAll(); } } } } // compute % if(quantMatPop/ quantMat > 0.05) { context.setValue(metier.getName()+param_pop.getName()+"flag",2); }else { context.setValue(metier.getName()+param_pop.getName()+"flag",1); } }else{ // strict application double quantMatPop = 0; ResultStorage matResult = context.getSimulationStorage().getResultStorage(); SiMatrix siMatrix = SiMatrix.getSiMatrix(context); List Pops = context.getPopulationMonitor().getPopulations(); for (TimeStep dat = new TimeStep(0); dat.before(step); dat = dat.next()) { for(Population pop:Pops){ if (pop.getName().equals(param_pop.getName())){ MatrixND tmp = matResult.getMatrix(dat, pop, MatrixCatchPerStrategyMetPerZonePop.NAME); quantMatPop += tmp.getSubMatrix(1,metier,1).sumAll(); } } } // metier catch sp ? if(quantMatPop > 0.0) { // yes -> forbidden context.setValue(metier.getName()+param_pop.getName()+"flag",2); } // else can still fish flag stays at 0 } }else { // no LO fishes but discard context.setValue(metier.getName()+param_pop.getName()+"flag",1); log.info(metier.getName()+"flag"+1); } }else result = false; //TAC not reached } // first time reached } //not in january */ }else result = true; return result; } /** * Si la condition est vrai alors cette action est executee avant le pas de * temps de la simulation. * * @param context la simulation pour lequel on utilise cette regle * @param step le pas de temps courant * @param metier le metier concerne */ @Override public void preAction(SimulationContext context, TimeStep step, Metier metier) throws Exception { /*if((int) context.getValue(metier.getName()+param_pop.getName()+"flag") == 2){ context.getMetierMonitor().addforbiddenMetier(metier); }*/ affectation = true; } /** * Si la condition est vrai alors cette action est executee apres le pas * de temps de la simulation. * * @param context La simulation pour lequel on utilise cette regle * @param step le pas de temps courant * @param metier le metier concerne */ @Override public void postAction(SimulationContext context, TimeStep step, Metier metier) throws Exception { if (affectation) { // Retrieve TAC value and allocation to the set of metiers //---------------------------------------------------------- double TAC = 0; int tacYear = step.getYear() - param_beginStep.getYear(); if (tacSeries[tacYear] != 0){ TAC = tacSeries[tacYear]; }else if(context.getValue(param_tacName+param_pop.getName()) != null){ // TAC is computed elsewhere TAC = (Double) context.getValue(param_tacName+ param_pop.getName()); }else TAC = 0; TAC = TAC * param_alloc * monthAlloc[step.getMonth().getMonthNumber()]; // Compute current catch for the set of metiers and TAC/catch ratio //----------------------------------------------------------------- String TMP = "tmp"; PopulationMonitor popMon = context.getPopulationMonitor(); MatrixND mat = popMon.getCatch(param_pop).copy(); SiMatrix siMatrix = newSiMatrix(context); MatrixND matW = siMatrix.matrixToWeightMatrix(step, 2, TMP, mat); /*for(MatrixIterator i= matW.iteratorNotZero(); i.next();) { Object[] coordonnees = i.getSemanticsCoordinates(); PopulationGroup group = (PopulationGroup) coordonnees[2]; i.setValue(i.getValue() * group.getMeanWeight()); }*/ double catchListMet = 0; for(Metier met : listMet){ catchListMet += matW.getSubMatrix(1,met).sumAll(); } log.info ("Catch of the month =" + catchListMet); double ratio = TAC/catchListMet; log.info("ratio "+ "= " + ratio); // If TAC is reached, change catch and abundance and compute discards //----------------------------------------------------------------- if (catchListMet >= TAC) { log.info("[TAC] catch = " + catchListMet+ " >= TAC:" + TAC); MatrixND eff = popMon.getN(param_pop); MatrixND cat = popMon.getCatch(param_pop); MatrixND discard = popMon.getDiscard(step, param_pop); // if the matrix does not exist it is created with the same format as catch if(discard == null){ discard = popMon.getCatch(param_pop).copy().mults(0); discard.setName(MatrixDiscardsPerStrMetPerZonePop.NAME); } for (MatrixIterator i = cat.iteratorNotZero(); i.next();) { Object[] coordonnees = i.getSemanticsCoordinates(); Strategy str = (Strategy) coordonnees[0]; Metier met = (Metier) coordonnees[1]; PopulationGroup group = (PopulationGroup) coordonnees[2]; Zone zone = (Zone)coordonnees[3]; if(listMet.contains(met)){ if(param_LandingsObligation) { eff.setValue(group, zone,eff.getValue(group, zone)+ i.getValue() * (1-ratio)); }else{ //discard discard.setValue(str,met,group,zone,i.getValue()*(1-ratio)); if (param_propSurvie > 0) { eff.setValue(group, zone,eff.getValue(group, zone)+ i.getValue() * (1-ratio) * param_propSurvie); } } i.setValue(i.getValue()*ratio); } } popMon.addDiscard(step, param_pop, discard); } //---------------------------------------------------------------------------------------------------- // Store infos in MatrixTacPerPop // add the month when TAC was reached to Matrix TAC per pop TacPopMatrix = MatrixFactory.getInstance().create( MatrixTacPerPop.NAME, new List[] { Arrays.asList(new String[]{"TAC","catchListMet","ratio"})}); TacPopMatrix.setValue("TAC", TAC); TacPopMatrix.setValue("catchListMet", catchListMet); TacPopMatrix.setValue("ratio", ratio); ResultStorage matResult = context.getSimulationStorage().getResultStorage(); matResult.addResult(step, param_metNames, param_pop, TacPopMatrix); } // on a affecte une fois cette meta pop au rejet il ne faut pas le // refaire pour ce pas de temps affectation = false; } }