package gov.nasa.ial.mde.solver;
import gov.nasa.ial.mde.math.IntervalXY;
import gov.nasa.ial.mde.solver.classifier.TrigClassifier;
import gov.nasa.ial.mde.solver.features.individual.AmplitudeFeature;
import gov.nasa.ial.mde.solver.features.individual.FrequencyFeature;
import gov.nasa.ial.mde.solver.features.individual.OffsetFeature;
import gov.nasa.ial.mde.solver.features.individual.PeriodFeature;
import gov.nasa.ial.mde.solver.features.individual.PhaseFeature;
import gov.nasa.ial.mde.solver.symbolic.AnalyzedEquation;
import gov.nasa.ial.mde.util.MathUtil;
public class SolvedSineFunction extends SolvedTrigFunction implements FrequencyFeature, AmplitudeFeature, PhaseFeature, OffsetFeature, PeriodFeature{
protected String[] newFeatures = {"frequency" , "amplitude", "phase", "offset", "period"};
protected TrigClassifier TC;
public SolvedSineFunction(AnalyzedEquation analyzedEquation) {
super(analyzedEquation, "sine function");
// for a basic sinusoid y=A*sin(Bx+C)+D
// amplitude = A
// period = 2*pi / |B|
// frequency = |B| / 2*pi
// phase shift = C/B ???
// offset = D
double A = 1;
double B = Double.NaN;
double C = Double.NaN;
double D = 0;
double amplitude = Double.NaN;
String period= null;
String frequency = null;
double phase = Double.NaN;
double offset = Double.NaN;
IntervalXY domain = null; // domain
IntervalXY range = null; // Range
String getCoeff = "y=(-?\\d*[\\./]?\\d*)\\*sin\\([^)\\n]*\\)([\\+-]\\d*[\\./]?\\d*)?";
String insideSIN = "sin\\(([^)\\n]*)\\)";
String getOffset = "sin\\([^)\\n]*\\)([\\+\\-]\\d*[\\./]?\\d*)";
TC = (TrigClassifier) analyzedEquation.getClassifier();
String equat = analyzedEquation.getInputEquation();
//System.out.println(equat);
equat = equat.trim();
equat = equat.replaceAll("-sin", "-1*sin");
//System.out.println(equat);
String innerEquat = equat.replaceAll(insideSIN, "____$1____");
//System.out.println(" Sine: " + innerEquat);
innerEquat = "y= " + innerEquat.split("____")[1];
//System.out.println(" Sine: " + innerEquat);
Solver solver = new Solver();
solver.add(innerEquat);
solver.solve();
Solution solution = solver.get(0);
SolvedGraph features = solution.getFeatures();
if(features instanceof SolvedLine){
String coeff = equat.replaceAll(getCoeff, "____$1____");
// System.out.println(" Coeff: " + coeff);
if(coeff.contains("____")){
coeff= coeff.split("____")[1];
if(coeff.contains("/")){
String[] fraction= coeff.split("/");
A = Double.valueOf(fraction[0])/Double.valueOf(fraction[1]);
}else{
A = Double.valueOf(coeff);
}
}
B = ((SolvedLine) features).getSlope();
C = ((SolvedLine) features).getYIntercept();
String offsetString = equat.replaceAll(getOffset, "____$1____");
// System.out.println(" Offset: " + offsetString);
if(offsetString.contains("____")){
offsetString = offsetString.split("____")[1];
if(offsetString.contains("/")){
String[] fraction= offsetString.split("/");
D = Double.valueOf(fraction[0])/Double.valueOf(fraction[1]);
}else{
D = Double.valueOf(offsetString);
}
}
// System.out.println(" Offset: " + offsetString);
// System.out.println(" A: " + A);
// System.out.println(" B: " + B);
// System.out.println(" C: " + C);
// System.out.println(" D: " + D);
//TODO: Create a method to give a more well define value, such as 2/3 pi or 5/6 pi or 1/4
phase = -C/B;
amplitude = A;
if(isMultipleOfPi(B)){
period = MathUtil.trimDouble((2*3.142)/Math.abs(B), 3)+"";
frequency = MathUtil.trimDouble(Math.abs(B)/(2*3.142) ,3)+"";
}
else{
period = MathUtil.trimDouble(2/Math.abs(B), 3)+"pi";
frequency = MathUtil.trimDouble(Math.abs(B)/2, 3) + "/pi";
}
offset = D;
domain = new IntervalXY(analyzedEq.getActualVariables()[0], Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
range = new IntervalXY(analyzedEq.getActualVariables()[1], - Math.abs(amplitude) + offset, Math.abs(amplitude)+offset);
putNewFeatures(newFeatures);
putFeature("amplitude", MathUtil.trimDouble(amplitude, -1));
putFeature("phase", MathUtil.trimDouble(phase, -1));
putFeature("offset", MathUtil.trimDouble(offset, -1));
putFeature("frequency", frequency);
putFeature("period", period);
putFeature("domain", domain);
putFeature("range", range);
}
}
public String getFrequency() {
Object value = this.getValue(FrequencyFeature.PATH, FrequencyFeature.KEY);
String frequencyString = (String)value;
System.out.println("Getting frequency.\nFrequency is : " + frequencyString);
return frequencyString;
}
public String getPeriod() {
Object value = this.getValue(PeriodFeature.PATH, PeriodFeature.KEY);
String periodString = (String)value;
System.out.println("Getting period.\nPeriod is : " + periodString);
return periodString;
}
public double getAmplitude() {
Object value = this.getValue(AmplitudeFeature.PATH, AmplitudeFeature.KEY);
Double doubleValue = new Double((String)value);
System.out.println("Getting Amplitude.\nAmplitude is : " + doubleValue);
return doubleValue;
}
public double getPhase() {
Object value = this.getValue(PhaseFeature.PATH, PhaseFeature.KEY);
Double doubleValue = new Double((String)value);
System.out.println("Getting Phase.\nPhase is : " + doubleValue);
return doubleValue;
}
public double getOffset() {
Object value = this.getValue(OffsetFeature.PATH, OffsetFeature.KEY);
Double doubleValue = new Double((String)value);
System.out.println("Getting Offset.\nOffset is : " + doubleValue);
return doubleValue;
}
public static void main(String[] args){
//TODO USE EXPRESSION THE EVALUATE A AND D
String getCoeff = "y=(-?\\d*[\\./]?\\d*)\\*sin\\([^)\\n]*\\)([\\+-]\\d*[\\./]?\\d*)?";
//String insideSIN = "sin\\(([^)\\n]*)\\)";
//String getOffset = "sin\\([^)\\n]*\\)([\\+\\-]\\d*[\\./]?\\d*)";
//String all = "(-?\\d*[\\./]?\\d*)\\*sin\\(([^)\\n]*)\\)";
String[] test = {"y= sin( x)","y=-sin(4 * x)", "y= sin (x)", "y=-3 * sin(4*x+20)", "y=-4.3*sin(4*x+432)+9"," y=5 /3 * sin( x/3)-4"};
for(int i= 0; i<test.length; i++){
test[i] = test[i].replaceAll(" ", "");
test[i] = test[i].replaceAll("-sin", "-1*sin");
System.out.println("\nTest case "+i);
System.out.println("Equation: " + test[i]);
System.out.println(" Coeff: " + test[i].replaceAll(getCoeff, "____ $1 ____"));
//System.out.println(" Sine: " + test[i].replaceAll(insideSIN, "____ $1 ____"));
//System.out.println(" Offset: " + test[i].replaceAll(getOffset, "____ $1 ____"));
//System.out.println(" All: " + test[i].replaceAll(all, "____ $1 ____ $2 ____"));
}
}
}