/* ******************************************************************** 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