/* ********************************************************************
Vlakna pro vypocet predikce aproximacnimi metodami.
Pouziva se metoda nejmensich ctvercu.
main file:
PredictionMethod.java
classes:
Approximation ... obecne staticke metody potrebne pro aproximaci
LinearApproximation ... prolozeni bodu primkou (y = a*x + b)
GoniometricApproximation ... prolozeni goniometr. fcemi (y = a*sin(x) + b*cos(x) + c)
ApproximationWindow ... okno nastaveni parametru aproximacnich metod
ApproximationParams ... objekt pro predani parametru z okna
(c)1999 Kota (Kocian Jan - kocianj1@cs.felk.cvut.cz)
******************************************************************** */
package kota.applets.prediction;
import java.awt.*;
// ********************************************************************
/** Objekt pro predani nastavenych parametru aproximacnich metod.
* @author Kota (Kocian Jan)
*/
class ApproximationParams extends MethodParameters
{
// konstanty -----------------
//kody metod
public static final byte
/** prolozeni vsech bodu jednou krivkou */
SMOOTH_ALL = 1,
/** pro kazdy bod prolozeni krivky vsemi predchozimy */
SMOOTH_PREVIOUS = 2,
/** pro kazdy bod prolozeni krivky x predchozimy (dle inputCount) */
SMOOTH_INPUT = 3;
// data ----------------------
/** typ methody */
public byte
methodType;
// metody --------------------
public ApproximationParams(byte button, byte methodType)
{
super(button);
this.methodType = methodType;
}
} //ApproximationParams
// ********************************************************************
/** Okno nastaveni parametru aproximacnich metod.
* @author Kota (Kocian Jan)
*/
class ApproximationWindow extends ParameterWindow
{
// popisy metod ------------------
private static final String
SELECT_TEXT = "Select approximation type",
ALL_TEXT = "Smooth all points (1 curve)",
PREVIOUS_TEXT = "Smooth previous points",
INPUT_TEXT = "Smooth previous X points";
// komponenty -----------------------
private Label
_label;
private CheckboxGroup
_group;
private Checkbox
_cbAll,
_cbPrev,
_cbInput;
// data -----------------------------
/** Minimalni pocet vstupnich bodu pro predikci */
private int
_minInput;
// metody ---------------------------
/** Konstruktor */
public ApproximationWindow(String title, PredictionMethod caller, int minInput)
{
super(title, caller);
_minInput = minInput;
setSize(300, 180);
setResizable(false);
setLayout(null);
//komponenty
add(_label = new Label(SELECT_TEXT));
_group = new CheckboxGroup();
add(_cbAll = new Checkbox(ALL_TEXT, true, _group));
add(_cbPrev = new Checkbox(PREVIOUS_TEXT, false, _group));
add(_cbInput = new Checkbox(INPUT_TEXT, false, _group));
}
/** Iniciace okna podle aktualnich parametru */
protected void _InitialSetting(int learn, int input, int predict)
{
//? malo vstupnich bodu - nelze prolozeni jen vstupnich bodu
if (input < _minInput)
{
//prepnuti jinam, pokud aktivni a vypnuti
if (_cbInput.getState())
_cbAll.setState(true);
_cbInput.setEnabled(false);
}
else
_cbInput.setEnabled(true);
}
/** Vytvoreni objektu parametru - volano pred zavrenim. */
protected final MethodParameters _CreateParameters(byte buttonCode)
{
byte type = ApproximationParams.UNKNOWN;
//find selected method
Checkbox checked = _group.getSelectedCheckbox();
if (checked == _cbAll)
type = ApproximationParams.SMOOTH_ALL;
else if (checked == _cbPrev)
type = ApproximationParams.SMOOTH_PREVIOUS;
if (checked == _cbInput)
type = ApproximationParams.SMOOTH_INPUT;
//create result
return new ApproximationParams(buttonCode, type);
}
// pomocne metody - usporadani komponent ---------------------
/** Usporadani komponent v okne */
public void doLayout()
{
//nastaveni pozic
Dimension dim = getSize();
Insets border = getInsets();
int
W = dim.width, //sirka okna
H = dim.height, //vyska okna
LABEL = 50, //odsazeni labelu od kraje okna
CHECK = 10, //odsazeni checkboxu od labelu
BUTTON = 50, //mezera mezi buttony
TOP = 10, //odsazeni vrsku labelu od vrsku okna
CHECK_H = 25, //odsazeni prvniho checkboxu od labelu
LINE = 22, //radkovani mezi checkboxy
BUTTON_H = 10; //odsazeni spodku buttonu od spodku okna
//iniciace
Font f = _label.getFont();
f = new Font(f.getName(), Font.BOLD, f.getSize());
_label.setFont(f);
int ypos = border.top + TOP;
int xpos = border.left + LABEL;
//vyber metody (checkboxy a label)
_SetLocation(_label, xpos, ypos);
xpos += CHECK;
ypos += CHECK_H;
_SetLocation(_cbAll, xpos, ypos);
ypos += LINE;
_SetLocation(_cbPrev, xpos, ypos);
ypos += LINE;
_SetLocation(_cbInput, xpos, ypos);
//buttony
dim = _bCancel.getPreferredSize();
ypos = H - (BUTTON_H + dim.height + border.bottom);
xpos = W / 2;
int move = BUTTON / 2;
_bOK.setBounds(xpos - (move + dim.width), ypos, dim.width, dim.height);
_bCancel.setBounds(xpos + move, ypos, dim.width, dim.height);
}
/** nastaveni pozice s default (Preferred) velikosti komponentu. */
private static void _SetLocation(Component c, int xpos, int ypos)
{
if (c != null) {
c.setSize(c.getPreferredSize());
c.setLocation(xpos, ypos);
}
}
} //ApproximationWindow
// ********************************************************************
/** Abstraktni predek aproximacnich metod. Obstarava veci kolem zobrazovani
* okna a uschovani parametru, metody pak pouze definuji _Run - vlastni
* telo vypoctu.
* Trida tez definuje obecne metody pouzite v aproximacnich vypoctech
* (jsou staticke, lze vyuzit i odjinud)
* @author Kota (Kocian Jan)
*/
public abstract class Approximation extends PredictionMethod
{
// data ------------------------------------------
/** typ metody - nastavuje se v okne */
protected byte
_methodType;
// nastaveni predikcni metody ---------------------------------
/** Konstruktor - nadpis okna a min pocet vstupni bodu pro
* pedikci z vstupnich bodu. */
public Approximation(String title, int minInput)
{
_window = new ApproximationWindow(title, this, minInput);
}
/** Ulozeni parametru metody nastavenych v okne */
protected void _SaveParameters(MethodParameters params)
{
if (params instanceof ApproximationParams)
_methodType = ((ApproximationParams)params).methodType;
//default
else
_methodType = ApproximationParams.SMOOTH_ALL;
}
// metody pro vypocet ---------------------------------------
/** Sumace dane casti pole */
public static final double Sum(double data[], int start, int count)
{
double res = 0;
int index = start;
for(int i = 0; i < count; i++)
res += data[index++];
return res;
}
/** Sumace soucinu dane casti 2 poli */
public static final double SumProduct(double data1[], double data2[], int start, int count)
{
double res = 0;
int index = start;
for(int i = 0; i < count; i++) {
res += data1[index] * data2[index];
index++;
}
return res;
}
/** vygenerovani bodu na zadanem intervalu v linearnim rozlozeni. */
public static final double[] GeneratePoints(double min, double max, int count)
{
double res[] = new double[count];
double step = (max - min) / (count - 1);
double value = min;
for(int i = 0; i < count; i++) {
res[i] = value;
value += step;
}
return res;
}
} //Approximation
// ********************************************************************
/** Predikce pomoci Linerani aproximace - y = a*x + b
* Pro regresi se pouziva metoda nejmensich ctvercu
* @author Kota (Kocian Jan)
*/
class LinearApproximation extends Approximation
{
// data ---------------------------------------
private double
/** rozlozeni bodu na x-ove ose */
_xmin, _xmax;
// public metody ---------------------------------
/** Konstruktor */
public LinearApproximation()
{
super("Setting of LinearApproximation", 2);
_xmin = 0.0;
_xmax = 10.0;
}
// metody predikce ----------------------------------
/** vlastni beh predikce */
protected void _Run()
{
//vytvoreni x-ovych souradnici pro regresi
double x[] = GeneratePoints(_xmin, _xmax, _outputPoints.length);
//ruzne metody - plni vzdy _outputPoints
switch (_methodType)
{
case ApproximationParams.SMOOTH_PREVIOUS:
_PreviousRegresion(x, _inputPoints);
break;
case ApproximationParams.SMOOTH_INPUT:
_PartialRegresion(x, _inputPoints, _inputSize);
break;
case ApproximationParams.SMOOTH_ALL:
default:
_PureRegresion(x, _inputPoints);
break;
} //switch-end
}
// jednotlive moznosti regrese ---------------------------
/** Prolozeni jedne primky vsemi vsemi vstupnimi body */
protected void _PureRegresion(double x[], double y[])
{
//vypocet regresnich koeficientu
double coefs[] = _CountCoeficients(x, y, 0, y.length);
//vypocet bodu z koeficientu
for(int i = 0; i < x.length; i++)
_outputPoints[i] = coefs[0] + coefs[1] * x[i];
}
/** Prolozeni primky pro kazdy bod ze vsech predchozich bodu */
protected void _PreviousRegresion(double x[], double y[])
{
int i, counter = 0;
//prekopirovani znamych bodu
System.arraycopy(y, 0, _outputPoints, 0, y.length);
//vypocet predikovanych bodu
for(i = y.length; i < x.length; i++) {
_DoLearnErrorOutput(counter++);
double coefs[] = _CountCoeficients(x, _outputPoints, 0, i);
_outputPoints[i] = coefs[0] + coefs[1] * x[i];
}
//prepocet znamych bodu predikci
for(i = 2; i < y.length; i++) {
_DoLearnErrorOutput(counter++);
double coefs[] = _CountCoeficients(x, y, 0, i);
_outputPoints[i] = coefs[0] + coefs[1] * x[i];
}
}
/** Vypocet bodu prolozenim daneho poctu predchozich bodu */
protected void _PartialRegresion(double x[], double y[], int count)
{
int i, counter = 0;
//prekopirovani znamych bodu
System.arraycopy(y, 0, _outputPoints, 0, y.length);
//vypocet predikovanych bodu
for(i = y.length; i < x.length; i++) {
_DoLearnErrorOutput(counter++);
double coefs[] = _CountCoeficients(x, _outputPoints, i - count, count);
_outputPoints[i] = coefs[0] + coefs[1] * x[i];
}
//prepocet znamych bodu predikci
for(i = count; i < y.length; i++) {
_DoLearnErrorOutput(counter++);
double coefs[] = _CountCoeficients(x, y, i - count, count);
_outputPoints[i] = coefs[0] + coefs[1] * x[i];
}
}
// pomocne funkce pro vypocet ----------------------------
/** Vypocet koeficientu linearni regrese */
protected double[] _CountCoeficients(double x[], double y[], int start, int count)
{
double res[] = new double[2];
//vypocet sum
double
xSum = Sum(x, start, count),
ySum = Sum(y, start, count),
x2Sum = SumProduct(x, x, start, count),
xySum = SumProduct(x, y, start, count);
//spocteni koeficientu
res[0] = (x2Sum*ySum - xSum*xySum) / (count*x2Sum - xSum*xSum);
res[1] = (xSum*ySum - count*xySum) / (xSum*xSum - count*x2Sum);
return res;
}
} //LinearApproximation
// ********************************************************************
/** Predikce pomoci Goniometricke aproximace - y = a*sin(x) + b*cos(x) + c
* Pro regresi se pouziva metoda nejmensich ctvercu
* @author Kota (Kocian Jan)
*/
class GoniometricApproximation extends Approximation
{
// data ---------------------------------------
private double
/** rozlozeni bodu na x-ove ose */
_xmin, _xmax,
/** sinus a cosinus zadanych x-ovych souradnic */
_sin[], _cos[];
// konstruktory ---------------------------------
/** Konstruktor */
public GoniometricApproximation() {
super("Setting of GoniometricApproximation", 3);
_xmin = 0.0;
_xmax = 10.0;
}
// beh vlakna ----------------------------------
/** vlastni beh predikce */
protected void _Run()
{
//vytvoreni x-ovych souradnici pro regresi
double x[] = GeneratePoints(_xmin, _xmax, _outputPoints.length);
//napocteni sinovych a cosinovych hodnot x prvku
_sin = _CountSinus(x);
_cos = _CountCosinus(x);
//ruzne metody - plni vzdy _outputPoints
switch (_methodType)
{
case ApproximationParams.SMOOTH_PREVIOUS:
_PreviousRegresion(x, _inputPoints);
break;
case ApproximationParams.SMOOTH_INPUT:
_PartialRegresion(x, _inputPoints, _inputSize);
break;
case ApproximationParams.SMOOTH_ALL:
default:
_PureRegresion(x, _inputPoints);
break;
} //switch-end
}
// regresni metody ------------------------------------
/** Regrese prolozenim vsech zadanych bodu */
protected void _PureRegresion(double x[], double y[])
{
//vypocet regresnich koeficientu
double coefs[] = _CountCoeficients(x, y, 0, y.length);
//vypocet bodu z koeficientu
for(int i = 0; i < x.length; i++)
_outputPoints[i] = coefs[0] + coefs[1]*_sin[i] + coefs[2]*_cos[i];
}
/** Prolozeni primky pro kazdy bod ze vsech predchozich bodu */
protected void _PreviousRegresion(double x[], double y[])
{
int i, counter = 0;
//prekopirovani znamych bodu do vystuppnich
System.arraycopy(y, 0, _outputPoints, 0, y.length);
//vypocet predikovanych bodu
for(i = y.length; i < x.length; i++) {
_DoLearnErrorOutput(counter++);
double coefs[] = _CountCoeficients(x, _outputPoints, 0, i);
_outputPoints[i] = coefs[0] + coefs[1]*_sin[i] + coefs[2]*_cos[i];
}
//prepocet znamych bodu predikci
for(i = 3; i < y.length; i++) {
_DoLearnErrorOutput(counter++);
double coefs[] = _CountCoeficients(x, y, 0, i);
_outputPoints[i] = coefs[0] + coefs[1]*_sin[i] + coefs[2]*_cos[i];
}
}
/** Vypocet bodu prolozenim daneho poctu predchozich bodu */
protected void _PartialRegresion(double x[], double y[], int count)
{
int i, counter = 0;
//prekopirovani znamych bodu
System.arraycopy(y, 0, _outputPoints, 0, y.length);
//vypocet predikovanych bodu
for(i = y.length; i < x.length; i++) {
_DoLearnErrorOutput(counter++);
double coefs[] = _CountCoeficients(x, _outputPoints, i - count, count);
_outputPoints[i] = coefs[0] + coefs[1]*_sin[i] + coefs[2]*_cos[i];
}
//prepocet znamych bodu predikci
for(i = count; i < y.length; i++) {
_DoLearnErrorOutput(counter++);
double coefs[] = _CountCoeficients(x, y, i - count, count);
_outputPoints[i] = coefs[0] + coefs[1]*_sin[i] + coefs[2]*_cos[i];
}
}
// pomocne metody -------------------------------------
/** Vypocet koeficientu linearni regrese. Predpoklada napocteni
* poli _sin a _cos.
* Pokud se v tom hodla nekdo vyznat ci to kontrolovat, je mi ho
* lito - odvozeni mam u sebe na papiru, ktery stejne asi brzo
* ztratim, ale je to (snad) dobre.
*
* @returns pole koeficientu - y = a*sin(x) + b*cos(x) + c
*
[0] ... konstantni clen (c)
*
[1] ... sinus clen (a)
*
[2] ... cosinus clen (b)
*/
protected double[] _CountCoeficients(double x[], double y[], int start, int count)
{
double res[] = new double[3];
double sin[] = _sin;
double cos[] = _cos;
//vypocet sum
double
a = Approximation.SumProduct(cos, cos, start, count),
b = Approximation.SumProduct(sin, cos, start, count),
c = Approximation.Sum(cos, start, count),
d = Approximation.SumProduct(cos, y, start, count),
e = Approximation.SumProduct(sin, sin, start, count),
f = Approximation.Sum(sin, start, count),
g = Approximation.SumProduct(sin, y, start, count),
h = Approximation.Sum(y, start, count),
n = count;
//spocteni koeficientu
res[0] = ((d*b-g*a)*(c*e-b*f) - (b*b-a*e)*(g*c-b*h)) / ((c*b-a*f)*(c*e-b*f) - (f*c-b*n)*(b*b-a*e));
res[1] = ((d*b-g*a) - res[0]*(c*b-a*f)) / (b*b-a*e);
res[2] = (d - b*res[1] - c*res[0]) / a;
return res;
}
/** vypocet sinu polozek pole */
protected double[] _CountSinus(double x[])
{
double res[] = new double[x.length];
for(int i = 0; i < x.length; i++)
res[i] = Math.sin(x[i]);
return res;
}
/** vypocet cosinu polozek pole */
protected double[] _CountCosinus(double x[])
{
double res[] = new double[x.length];
for(int i = 0; i < x.length; i++)
res[i] = Math.cos(x[i]);
return res;
}
} //GoniometricApproximation