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.RegionStorage; 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; import fr.ifremer.isisfish.entities.*; import fr.ifremer.isisfish.types.Date; /** * CalibrationSimplexePasVariable2_BecDeCane. * * Created: 31 mai 2011 * * @author * @version $1$ * * 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 : "CalibrationSimplexePasVariable2_BecDeCane" 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 = "D:/Bastien/Sur Bureau/These_ISIS_Noumea/Parametrage/Calibration/debarquements_Bec.csv";//in row : time (months) ; in columns : metier protected File debarquementsObserves; protected MatrixND matrixDebarquement; 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 */ // Initialisation du plan de simu avec les donnees importees. public void init(AnalysePlanContext context) throws Exception { if (debarquements == null || "".equals(debarquements)) { // Si les objets sont vides on recupere les valeurs du fichier .csv. debarquementsObserves = FileUtil.getFile(".*.csv", "fichier csv separateur ';'"); } else { // Si les objets ne sont pas vides, on recupere les valeurs deja existantes. debarquementsObserves = new File(debarquements); } /* 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 = 10; // Si 1 seul groupe car valeurs sommees sur les groupes, ne pas mettre cette dimension. /////*** 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 = 8; int[] dimMatrix = {nbTrim, nbMet}; matrixDebarquement = MatrixFactory.getInstance().create(dimMatrix); //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}); //db.closeContext(); System.out.println("MatrixDebarquement : " + matrixDebarquement); System.out.println("debarquements : " + debarquements); System.out.println("debarquementsObserves : " + debarquementsObserves); */ SimulationParameter params = context.getParam(); RegionStorage region = params.getRegion(); TopiaContext tx = region.getStorage().beginTransaction(); FisheryRegion fisheryRegion = RegionStorage.getFisheryRegion(tx); List metiers = fisheryRegion.getMetier(); // reccup la liste des metiers //SiMatrix siMatrix = SiMatrix.getSiMatrix(context); //List metiers = siMatrix.getMetiers(new Date(0)); // creer la liste des metiers de ton fichier de debarq observes // tu rentres la liste de tes metiers dans l ordre de ton fichier d'import String[] metiersBecDeCane = new String[]{"PRO_Ligne_GranNou_FondLagon", "PRO_Ligne_CorneSud_FondLagon", "PRO_Filet_GranNou_FondLagon", "PRO_Filet_CorneSud_FondLagon", "PRO_Ligne_GranNou_Recif", "PRO_Filet_GranNou_Recif", "PRO_Filet_CorneSud_Recif", "PRO_Ligne_CorneSud_Recif" }; List metiersNous = new ArrayList(); for(String metiersNomCurrent : metiersBecDeCane){ for (Metier met : metiers){ if(met.getName().equals(metiersNomCurrent)){ metiersNous.add(met); } } } //creer la liste des dates //si par ex tes simu ont 60 pas de temps (60 trimestres,60 mois...) List dates = new ArrayList (); for (int i=0; i < 12; i++) { dates.add(new Date (i)); } // creation de la matrice en specifiant ses semantics plutot que sa taille log.info("dates :" + dates); MatrixND matrixDebarquement = MatrixFactory.getInstance().create(new List[]{dates,metiersNous}); matrixDebarquement.importCSV(new FileReader(debarquementsObserves),new int []{0,0}); log.info("debarquements : " + debarquements); log.info("debarquementsObserves : " + debarquementsObserves); log.info("dim de obs" + " " + Arrays.toString(matrixDebarquement.getDim())); log.info("matrixDebarquement : " + matrixDebarquement); tx.closeContext(); } 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 = 10; double q2 = 10; 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 can be cumulated over months(0), strategies(1), metiers(2), groups(3), and area(4). MatrixND L = result.getMatrix(param_Population, ResultName.MATRIX_CATCH_WEIGHT_PER_STRATEGY_MET_PER_ZONE_POP); log.info("dim de L2" + " " + Arrays.toString(L.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 388 and replace "L2" by "L" at line 377 /////*** 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(); /* pour connaitre les index des metiers faire: List listmet = L2.getSemantic(1); int[] indexMetagarder = new int[4]; for(Metier m : listmet){ if(m.getName().equals("PRO_Ligne_GN_FondLagon")) { indexMetagarder [1] = listmet.indexOf(m); }else if(m.getName().equals("PRO_Ligne_CS_FondLagon")) {indexMetagarder [2] = listmet.indexOf(m); }else if(m.getName().equals("PRO_Filet_GN_FondLagon")) {indexMetagarder [2] = listmet.indexOf(m); }else if(m.getName().equals("PRO_Filet_CS_FondLagon")) {indexMetagarder [2] = listmet.indexOf(m); } } // ensuite extraire la sous matrice: MatrixND L = L2.getSubMatrix(1, indexMetagarder).copy(); 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); ////*** 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); log.info("sommes sur les strategies, zones et groupes faites"); L = L.reduce(); // Affichage des dimensions et des matrices Observees et simulees. log.info("dim de L" + " " + Arrays.toString(L.getDim())); log.info("matriceSimule L :"+ L); log.info("matriceObs (= matrixDebarquement) :"+ matrixDebarquement); log.info("dim de obs" + " " + Arrays.toString(matrixDebarquement.getDim())); ///////////////////Calcul du critere////////////////// log.info("calcul du critere"); 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(); Object [] sem = g.getSemanticsCoordinates(); //double obs = matrixDebarquement.getValue(dim); double obs = matrixDebarquement.getValue(sem); 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; } } }