package analyseplans; import static org.nuiton.i18n.I18n._; import java.io.File; import java.io.FileReader; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; 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.TopiaContext; import org.nuiton.util.FileUtil; import org.nuiton.util.StringUtil; import scripts.ResultName; import fr.ifremer.isisfish.datastore.ResultStorage; import fr.ifremer.isisfish.datastore.SimulationStorage; import fr.ifremer.isisfish.entities.Population; import fr.ifremer.isisfish.entities.PopulationGroup; import fr.ifremer.isisfish.simulator.AnalysePlan; import fr.ifremer.isisfish.simulator.AnalysePlanContext; import fr.ifremer.isisfish.simulator.SimulationParameter; import fr.ifremer.isisfish.util.Doc; /** * CalibrationSimplexePasVariable2Capturabilite. * * Created: 31 mai 2011 * * @author * @version $$ * * Last update: $$ * by : $$ */ /////***You can modify class name if you want /////***BUT attention : file name and class name must be the same (without the extention ".java"), ie here : "CalibrationSimplexePasVariable2Capturabilite" public class CalibrationSimplexePasVariable2_BecDeCane implements AnalysePlan { /** to use log facility, just put in your code: log.info("..."); */ static private Log log = LogFactory .getLog(CalibrationSimplexePasVariable2_BecDeCane.class); enum State { STATE_INIT, STATE_0, STATE_1, STATE_2, STATE_3, STATE_4 }; /////***here must appear the path to export the historic file ("Historic.csv") //where q1, q2 and criteria computed at each simulation are written /////***Attention : before beginning a new calibration rename your eventual //old file Historic.csv otherwise it will be lost protected File exportHistoric = new File("D:/Bastien/Sur Bureau/These_ISIS_Noumea/Parametrage/Calibration/HistoricBecDeCane.csv"); protected String exportHisto = ""; @Doc("Population which parameters are calibrated") public Population param_Population = null; @Doc("First initial point of the simplex: de la forme(\"xx;yy\")") public String param_M1 = "2.42e-5;2.11e-6";// devient un parametre du plan d analyse @Doc("Second initial point of the simplex") public String param_M2 = "2.34e-5;2.59e-6";// devient un parametre du plan d analyse @Doc("Third initial point of the simplex") public String param_M3 = "2.59e-5;2.41e-6";// devient un parametre du plan d analyse ///// ***put here the path and name of the file containing the data on which you calibrate your fichery ( here observed catches) @Doc(value = "file name and path of observed landings") public String debarquements_Ligne_GN = "D:/Bastien/Sur Bureau/These_ISIS_Noumea/Parametrage/Calibration/cmt_PRO_Ligne_GN_FondLag.csv";//in row : time (months) ; in columns : age or length group// Matrix for metier 1 public String debarquements_Ligne_CS = "D:/Bastien/Sur Bureau/These_ISIS_Noumea/Parametrage/Calibration/cmt_PRO_Ligne_CS_FondLag.csv";// Matrix for metier 2 public String debarquements_Filet_GN = "D:/Bastien/Sur Bureau/These_ISIS_Noumea/Parametrage/Calibration/cmt_PRO_Filet_GN_FondLag.csv";// Matrix for metier 3 public String debarquements_Filet_CS = "D:/Bastien/Sur Bureau/These_ISIS_Noumea/Parametrage/Calibration/cmt_PRO_Filet_CS_FondLag.csv";// Matrix for metier 3 protected File debarquementsObserves1; protected File debarquementsObserves2; protected File debarquementsObserves3; protected File debarquementsObserves4; protected File debarquementsObserves; // Est-il necessaire de mettre cette ligne? protected MatrixND matrixDebarquement1; protected MatrixND matrixDebarquement2; protected MatrixND matrixDebarquement3; protected MatrixND matrixDebarquement4; protected MatrixND matrixDebarquement; // Est-il necessaire de mettre cette ligne? protected State state = State.STATE_INIT; public Experiences experiences = new Experiences(); public String[] necessaryResult = { ResultName.MATRIX_CATCH_WEIGHT_PER_STRATEGY_MET_PER_ZONE_POP }; public String[] getNecessaryResult() { return this.necessaryResult; } /** * Permet d'afficher a l'utilisateur une aide sur le plan. * @return L'aide ou la description du plan */ public String getDescription() throws Exception { return _("Calibration using variable step Simplex method (Walters): user gives a file of observations (here catches) by time step and group (.csv), output will try to approach oservations by changing the values of catchability"); } /** * Appele au demarrage de la simulation, cette methode permet d'initialiser * des valeurs * @param context La simulation pour lequel on utilise cette regle */ public void init(AnalysePlanContext context) throws Exception { if (debarquements_Ligne_GN == null && debarquements_Ligne_CS == null && debarquements_Filet_GN == null && debarquements_Filet_CS == null || "".equals(debarquements_Ligne_GN) && "".equals(debarquements_Ligne_CS) && "".equals(debarquements_Filet_GN) && "".equals(debarquements_Filet_CS)) { debarquementsObserves1 = FileUtil.getFile(".*.csv", "fichier csv separateur ';'"); debarquementsObserves2 = FileUtil.getFile(".*.csv", "fichier csv separateur ';'"); debarquementsObserves3 = FileUtil.getFile(".*.csv", "fichier csv separateur ';'"); debarquementsObserves4 = FileUtil.getFile(".*.csv", "fichier csv separateur ';'"); } else { debarquementsObserves1 = new File(debarquements_Ligne_GN); debarquementsObserves2 = new File(debarquements_Ligne_CS); debarquementsObserves3 = new File(debarquements_Filet_GN); debarquementsObserves4 = new File(debarquements_Filet_CS); } int nbYear = context.getParam().getNumberOfYear(); //TopiaContext db = context.getParam().getRegion().getStorage().beginTransaction(); //Population pop = (Population) db.findByTopiaId(param_Population.getTopiaId()); /////*** specify dimention of the matrix containning observations (observed landings for instance) /////*** numbers of group/columns : could be equal to your number of classes in ISIS but may also be different if your had only aggregated data int nbGroup = 1; /////*** enter number of observation per year (if you have observation by quarter put 4) / lines of the observations file int nbTrim = nbYear * 12; /////*** enter the number of metiers int nbMet = 4; int[] dimMatrix2 = { nbTrim, nbGroup }; int[] dimMatrix = {nbTrim, nbMet, nbGroup }; matrixDebarquement = MatrixFactory.getInstance().create(dimMatrix); matrixDebarquement1 = MatrixFactory.getInstance().create(dimMatrix2); matrixDebarquement2 = MatrixFactory.getInstance().create(dimMatrix2); matrixDebarquement3 = MatrixFactory.getInstance().create(dimMatrix2); matrixDebarquement4 = MatrixFactory.getInstance().create(dimMatrix2); //matrixDebarquement = MatrixFactory.getInstance().create(new int[]{nbGroup}); // List groups = pop.getPopulationGroup(); // matrixDebarquement = MatrixFactory.getInstance().create(new List[]{groups}); //matrixDebarquement.importCSV(new FileReader(debarquementsObserves), new int[] {0, 0}); matrixDebarquement1.importCSV(new FileReader(debarquementsObserves1), new int[] {0, 0 }); matrixDebarquement2.importCSV(new FileReader(debarquementsObserves2), new int[] {0, 0 }); matrixDebarquement3.importCSV(new FileReader(debarquementsObserves3), new int[] {0, 0 }); matrixDebarquement4.importCSV(new FileReader(debarquementsObserves4), new int[] {0, 0 }); //db.closeContext(); for( MatrixIterator i=matrixDebarquement.iterator(); i.hasNext();){ i.next(); int [] debarquementsObserves = i.getCoordinates(); if (debarquementsObserves[1] == 0){ i.setValue(matrixDebarquement1.getValue(debarquementsObserves[0],debarquementsObserves[2])); }else if (debarquementsObserves[1] == 1){ i.setValue(matrixDebarquement2.getValue(debarquementsObserves[0],debarquementsObserves[2])); }else if (debarquementsObserves[1] == 2){ i.setValue(matrixDebarquement3.getValue(debarquementsObserves[0],debarquementsObserves[2])); }else if (debarquementsObserves[1] == 3){ i.setValue(matrixDebarquement4.getValue(debarquementsObserves[0],debarquementsObserves[2])); } } log.info("MatrixDebarquement1 : " + matrixDebarquement1); } double g1; double g2; double worst1; double worst2; /** * Call before each simulation * @param context plan context * @param nextSimulation storage used for next simulation * @return true if we must do next simulation, false to stop plan * @throws Exception */ public boolean beforeSimulation(AnalysePlanContext context, SimulationStorage nextSimulation) throws Exception { boolean doNext = true; boolean doBoucle = true; log.info("before simulation"); int number = nextSimulation.getParameter().getAnalysePlanNumber(); if (number < 3) { log.info("number<3"); String[] M1 = param_M1.split(";"); String[] M2 = param_M2.split(";"); String[] M3 = param_M3.split(";"); double[] q1 = StringUtil.toArrayDouble(M1[0], M2[0], M3[0]); double[] q2 = StringUtil.toArrayDouble(M1[1], M2[1], M3[1]); experiences.getExperience(number).q1 = q1[number]; experiences.getExperience(number).q2 = q2[number]; changeDB(experiences.getExperience(number), nextSimulation); } else { double q1 = 1000; double q2 = 1000; double lastCritere = experiences.getExperience(number - 1).criteria; while (doBoucle) { doBoucle = false; if (state == State.STATE_INIT) { doBoucle = false; log.info("state init"); //ordonne les 3 premieres experiences selon leur critere Collections.sort(experiences.current); //log.info("SIMPLEXE : current 0 = " + experiences.current.get(0).criteria + "current 1 = " + experiences.current.get(1).criteria + "current 2 = " + experiences.current.get(2).criteria ); log.info("SIMPLEXE : current 0 = " + experiences.current.get(0).criteria + "current 1 = " + experiences.current.get(1).criteria + "current 2 = " + experiences.current.get(2).criteria); log.info("SIMPLEXE : Best q1 = " + experiences.current.get(0).q1 + " q2 = " + experiences.current.get(0).q2); log.info("SIMPLEXE : NextBest q1 = " + experiences.current.get(1).q1 + " q2 = " + experiences.current.get(1).q2); log.info("SIMPLEXE : Worst q1 = " + experiences.current.get(2).q1 + " q2 = " + experiences.current.get(2).q2); //Calcul et evaluation de R double g1 = (experiences.current.get(0).q1 + experiences.current .get(1).q1) / 2.0; double g2 = (experiences.current.get(0).q2 + experiences.current .get(1).q2) / 2.0; double worst1 = experiences.current.get(2).q1; double worst2 = experiences.current.get(2).q2; state = State.STATE_0; q1 = 2 * g1 - worst1; q2 = 2 * g2 - worst2; log.info("R : q1 = " + q1 + " q2 = " + q2); } else if (state == State.STATE_0) { doBoucle = false; log.info("state 0"); // on fait la 5eme avec des q qui dependent de la 4eme dans le dernier cas //log.info("g1 = " + g1 + " " + "g2 = " + g2); //log.info("worst1 = " + worst1 + " " + "worst2 = " + worst2); if (lastCritere > experiences.current.get(2).criteria) { log.info("State 0 : R : lastCtritere > current2 : R pire de W"); state = State.STATE_1; //calcul de Cw q1 = ((experiences.current.get(0).q1 + experiences.current .get(1).q1) / 2.0) - (((experiences.current.get(0).q1 + experiences.current .get(1).q1) / 2.0) - experiences.current .get(2).q1) / 2.0; q2 = ((experiences.current.get(0).q2 + experiences.current .get(1).q2) / 2.0) - (((experiences.current.get(0).q2 + experiences.current .get(1).q2) / 2.0) - experiences.current .get(2).q2) / 2.0; log.info("Cw : q1 = " + q1 + " q2 = " + q2); } else if (lastCritere > experiences.current.get(1).criteria) { log.info("State 0 :R : lastCritere > current 1 : R meilleur que W et moins bon que N"); state = State.STATE_2; // calcul de Cr q1 = ((experiences.current.get(0).q1 + experiences.current .get(1).q1) / 2.0) + (((experiences.current.get(0).q1 + experiences.current .get(1).q1) / 2.0) - experiences.current .get(2).q1) / 2.0; q2 = ((experiences.current.get(0).q2 + experiences.current .get(1).q2) / 2.0) + (((experiences.current.get(0).q2 + experiences.current .get(1).q2) / 2.0) - experiences.current .get(2).q2) / 2.0; log.info("Cr : q1 = " + q1 + " q2 = " + q2); } else if (lastCritere > experiences.current.get(0).criteria) { log.info("State 0 :R : lastCritere > current0 : R meilleur que N et moins bon que B"); state = State.STATE_INIT; experiences.current.remove(2);//remove(3)avant doBoucle = true; log.info("remove W, simplex BNR"); } else { // dernier cas possible: if (lastCritere < experiences.current.get(0).critere) { log.info("State 0 :R : lastCritere < current 0 : R meilleur que B, calcul de E"); state = State.STATE_4; q1 = experiences.getExperience(number - 1).q1 + (experiences.current.get(0).q1 + experiences.current .get(1).q1) / 2.0 - experiences.current.get(2).q1; q2 = experiences.getExperience(number - 1).q2 + (experiences.current.get(0).q2 + experiences.current .get(1).q2) / 2.0 - experiences.current.get(2).q2; //q1 = experiences.current.get(3).q1 + (experiences.current.get(0).q1 + experiences.current.get(1).q1) / 2.0 - experiences.current.get(2).q1; //q2 = experiences.current.get(3).q2 + (experiences.current.get(0).q2 + experiences.current.get(1).q2) / 2.0 - experiences.current.get(2).q2; log.info("E : q1 = " + q1 + " q2 = " + q2); } } else if (state == State.STATE_1) { log.info("state 1, simplex BNCw"); experiences.current.remove(3); experiences.current.remove(2); state = State.STATE_INIT; doBoucle = true; } else if (state == State.STATE_2) { log.info("state 2, simplex BNCr"); experiences.current.remove(3); experiences.current.remove(2); state = State.STATE_INIT; doBoucle = true; } else if (state == State.STATE_4) { log.info("state 4 :comparaison de E a B"); doBoucle = true; if (lastCritere < experiences.current.get(0).criteria) { log.info("E meilleur que B, remove 2 et 3 : simplex BNE"); experiences.current.remove(3); experiences.current.remove(2); } else { log.info("E moins bon que B, remove 2 et 4, simplex BNR"); experiences.current.remove(4); experiences.current.remove(2); } state = State.STATE_INIT; } }//fin du while //on remplit la table experiences experiences.getExperience(number).q1 = q1; experiences.getExperience(number).q2 = q2; log.info("on change Q dans la DB avec : q1 = " + q1 + " " + "q2 = " + q2); // on change la valeur de q dans la DB changeDB(experiences.getExperience(number), nextSimulation); }// fin du else (number > 3) return doNext; }// fin du before simulation /** * Call after each simulation, compute criteria for last simulation * @param context plan context * @param lastSimulation storage used for next simulation * @return true if we must do next simulation, false to stop plan * @throws Exception */ public boolean afterSimulation(AnalysePlanContext context, SimulationStorage lastSimulation) throws Exception { boolean doNext = true; log.info("after simulation"); int number = lastSimulation.getParameter().getAnalysePlanNumber(); ResultStorage result = lastSimulation.getResultStorage(); /////*** Simulated catches are cumulated over strategies, areas and metiers MatrixND L2 = result.getMatrix(param_Population, ResultName.MATRIX_CATCH_WEIGHT_PER_STRATEGY_MET_PER_ZONE_POP); log.info("dim de L2" + " " + Arrays.toString(L2.getDim())); //System.out.println("matriceObs :"+ matrixDebarquement); //System.out.println("matriceSimule :"+ L); // log.info("dim de L2" + " " + Arrays.toString(L2.getDim())); /////*** If some strategies, metiers or areas must not be included in the cumulated catches see below else put "//" at the beginning of line 297 and replace "L2" by "L" at line 289 /////*** the strategies or so to exclude must be at the begining or end of the list you enter in the parameters interface /////*** fill the line MatrixND L = L2.getSubMatrix(a,b,c).copy(); as follow : /////*** a = 1 if you want to exclude strategies, 2 if metiers and 4 if areas /////*** b = indice of the first object considered /////*** c = number of object to keep after b, b included MatrixND L = L2.getSubMatrix(2, 4, 4).copy(); // for instance : keep strategies 2,3,4,5 //log.info("sous matrice extraite"); L = L.sumOverDim(1);// sum over strategies //L = L.sumOverDim(2);// sum over metiers L = L.sumOverDim(4);// sum over zones /////*** if observations are cumulated by groups else put "//" at the beginning of the following line L = L.sumOverDim(3); log.info("sommes sur les strategies et groupes faites"); ///log.info("matriceSimule L :"+ L); /////*** else if number of groups in your database differs from number of groups in observations ... write me an e-mail ////*** if observations are cumulated over quarter put 3, over year 12, else put "//" at the beginning of the following line //L = L.sumOverDim(0, 12); L = L.reduce(); //log.info("matriceSimule L reduce:"+ L); System.out.println("matriceObs :"+ matrixDebarquement); System.out.println("matriceSimule :"+ L); ///////////////////Calcul du critere////////////////// log.info("calcul du critere"); log.info("dim de L" + " " + Arrays.toString(L.getDim())); log.info("dim de obs" + " " + Arrays.toString(matrixDebarquement.getDim())); double crit = 0; for (MatrixIterator g = L.iterator(); g.hasNext();) { g.next(); //boucle sur les trimestres et les classes d age int[] dim = g.getCoordinates(); double obs = matrixDebarquement.getValue(dim); double simules = g.getValue(); crit += Math.pow(obs - simules, 2); // crit = crit + (obs-simules)^2 }// fin du for log.info("critere " + number + " = " + crit); //ajoute le critere dans la table experiences experiences.getExperience(number).criteria = crit; //ecriture de la table historic exportHisto += experiences.getExperience(number).q1 + ";" + experiences.getExperience(number).q2 + ";" + experiences.getExperience(number).criteria + "\n"; org.nuiton.util.FileUtil.writeString(exportHistoric, exportHisto); return doNext; }// fin du after simulation /** * Modify nextSimulation database with q1 and q2 in exp. * * @param exp * @param nextSimulation * @throws Exception */ protected void changeDB(Experience exp, SimulationStorage nextSimulation) throws Exception { //methode appelee dans before simualtion TopiaContext db = nextSimulation.getStorage().beginTransaction();//ouvrir un context pour modifier les donnees Population pop = (Population) db.findByTopiaId(param_Population.getTopiaId()); //reccupere la pop ciblee MatrixND c = pop.getCapturability(); // reccupere la matrice de capturabilite //log.info("Pour cette simulation : q1 = " + exp.q1 + ";" + "q2 = " + exp.q2 ); /////*** that is where you explain how to fill the catchability matrix with q1 and q2 for (MatrixIterator i = c.iterator(); i.hasNext();) { i.next(); Object[] sem = i.getSemanticsCoordinates(); PopulationGroup group = (PopulationGroup) sem[0]; //PopulationSeasonInfo season = (PopulationSeasonInfo) sem[1]; ////*** exemple when q2 corresponds to the 12 first groups (groups 0 to 11) if (group.getId() < 5) { i.setValue(exp.q1); } else { i.setValue(exp.q2); } /////*** exemple when it depends on seasons and groups /* if (season.getFirstMonth().after(Month.JULY) && group.getId() >=18){ //month >= aout && groupID >= 18 i.setValue(exp.q2); }else { i.setValue(exp.q1); } */ }//fin du for db.commitTransaction(); // effectue la modification db.closeContext(); // ferme le context } static public class Experiences { // cree la liste experiences ou sont stoques q1,q2 et critere pour chaque simulation /** contains last simplex and potentialy 2 more simulation */ public List current = new ArrayList(); /** contains all experience done */ public List history = new ArrayList(); /** * return experience requested, if this experience doesn't exist * create it. * * @param i simulation number * @return experience with simulation number fixed if new experience * is returned */ public Experience getExperience(int i) { Experience result; if (i < history.size()) { result = history.get(i); } else { result = new Experience(); result.simNumber = i; history.add(i, result); current.add(result); } return result; }//fin de la definition de getExperience /** * @return the history */ public List getHistory() { return this.history; } }// fin de la creation des listes experiences static public class Experience implements Comparable { public int simNumber; public double criteria; public double q1; public double q2; /** * Permit to order experience, first is experience with smallest criteria */ public int compareTo(Experience other) { int result = Double.compare(this.criteria, other.criteria); return result; } } }