/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Copyright (C) 2011-2013 Marchand Eric <ricoh51@free.fr>
This file is part of Freegressi.
Freegressi 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.
Freegressi 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 Freegressi. If not, see <http://www.gnu.org/licenses/>.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package freegressi.fit.functions;
import freegressi.fit.FitModel;
import freegressi.parser.Lexer;
import freegressi.parser.Verificateur;
import freegressi.tableur.Noeud;
import freegressi.tableur.Sym;
import freegressi.tableur.Tableur;
import freegressi.utils.Utils;
import java.util.ArrayList;
/**
* La classe qui définit une fonction quelconque.
* y = f(x)
* @author marchand, 11 mai 2013, 11:31:00
*/
public class AnyFunc extends FreegressiFunction{
private final Noeud node;
private double delta = 1e-14;
private final String expr;
public AnyFunc(Noeud node, String expr) {
super();
this.node = node;
//this.sheet = sheet;
this.expr = expr;
}
@Override
public String getTextToDisplay(double[] a, String xName, int CS) {
return reconstruitExpressionTendance(expr, a, xName, true);
}
@Override
public Noeud getNode(Tableur sheet, double[] a, String xName) {
String newExpr = reconstruitExpressionTendance(expr, a, xName, false);
return Verificateur.parseExpression(sheet, newExpr, "");
}
@Override
public double getY(double x, double[] a) {
FitModel.getInstance().setIndexParameter(-1);
return FitModel.getInstance().calculeTendance(node, x, a);
}
@Override
public double getPartialDerivate(double x, double[] a, int parameterIndex) {
double a1 = a[parameterIndex] - delta;
double a2 = a[parameterIndex] + delta;
double[] aa1 = new double[a.length];
System.arraycopy(a, 0, aa1, 0, a.length);
aa1[parameterIndex] = a1;
double[] aa2 = new double[a.length];
System.arraycopy(a, 0, aa2, 0, a.length);
aa2[parameterIndex] = a2;
return (getY(x, aa2) - getY(x, aa1)) / (a2 - a1);
}
/**
* Fabrique l'expression du résultat de la tendance à partir de l'expression
* contenant le nom des paramètres. Les paramètres sont remplacés par leurs
* valeur (formattée ou non selon le flag "formatte". Lorsqu'un paramètre
* négatif est placé après un signe +, on supprime le signe +, sinon on
* l'entoure de parenthèses
* @param expression l'exression avec les constantes (a, b, ... )
* @param params la liste des valeurs des constantes dans leur ordre d'apparition
* @param nomSerieX le nom de la série X
* @param formatte Flag qui dit si on doit formatter la chaine
* @return une chaine de caracteres correspondant au modèle trouvé
*/
public String reconstruitExpressionTendance(String expression, double params[], String nomSerieX, boolean formatte) {
// Créer la liste de noeuds avec le lexer
ArrayList<Noeud> liste = new ArrayList<>();
try {
Lexer lex = new Lexer(new java.io.StringReader(expression), liste);
lex.yylex();
} catch (Exception e) {
System.err.println("Erreur interne du lexer!");
return null;
}
int n = 0;
String resultat = "";
String nombre = "";
Noeud noeudPrecedent = null;
boolean flagParenthese = false;
for (Noeud noeud : liste) {
if (noeud.getType() == Sym.ID) {
if (!noeud.getNom().equals(nomSerieX)) {
if (params[n] < 0) { // si paramètre négatif
if (noeudPrecedent != null
&& noeudPrecedent.getType() == Sym.PLUS) { // si un + précède
int pos = resultat.length() - 1;
String str = resultat.substring(0, pos);
resultat = str;
} else { // entourer le paramètre de parenthèses
resultat += "(";
flagParenthese = true;
}
}
if (formatte) {
resultat += Utils.formatteNombre(params[n], 3);
} else {
resultat += params[n];
}
if (flagParenthese) {
resultat += ")";
flagParenthese = false;
}
n++;
} else {
resultat += noeud.getTexteLexer();
}
} else {
resultat += noeud.getTexteLexer();
}
noeudPrecedent = noeud;
}
System.out.println("************** " + resultat);
return resultat;
}
@Override
public int getParamNumber() {
return node.getNombreNoeudParametre();
}
}