Название: Разобрать программу по теории Пирсона
Отправлено: lexflax от Май 27, 2014, 12:51
Доброго времени суток. Сдал первую лабу по методу Монте-Карло.. Вторая лаба Цель работы: изучить методы моделирования нормально распределенных случайных величин и проверки их с помощью критерия Пирсона. Есть прога готовая, но по тексту программы во многих местах не понимаю что, где и как делается... от части потому что саму математическую модель не понимаю ... от части некоторый код просто не понимаю... Помогите разобратся в самом коде, я некоторые комментарии проставил но не факт что они верные... помогите проставить комментарии везде? и собственно понять саму проверку с помощью Пирсона может в более простом варианте объяснения? Просто те которые сижу читаю и пытаюсь понять , не могу осмыслить мат знаний не хватает... mainwindows.cpp #include "mainwindow.h" #include "ui_mainwindow.h" #include "stdlib.h" #include "time.h" #include "QDebug" #include "math.h" #include <QGraphicsScene> float chi2inv(float a, int n); MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); n=6; pi=M_PI; } MainWindow::~MainWindow() { delete ui; } float MainWindow::r() { float r= (float) rand() / RAND_MAX; return r; } void MainWindow::on_pushButton_clicked() { srand(time(NULL)); r_count=ui->sb_r_count->value();//количество случайных чисел mx=ui->dsb_mx->value();//математическое ожидание dx=ui->dsb_dx->value();//средне квадратичное отклонение z.clear(); x.clear(); v.clear(); fi.clear(); fp.clear(); xi.clear(); xip.clear(); for(int i=0;i<r_count;i++)// цикл по случайным числам for(int j=0;j<n;j++) //цикл по количеству эксперементов { if (j==0) v.append(r()); //если первый эксперемент то записать в конец строки v значение r else v[i]+=r();// иначе заполнять массив увеличивая каждый раз на значение r } for(int i=0;i<r_count;i++)// цикл по случайным числам { z.append((v[i]-(n/2.0))/sqrt(n/12.0));// не понимаю формулу } for(int i=0;i<r_count;i++)// цикл по случайным числам { x.append(mx+z[i]*dx); //не понимаю формулу } for(int i=0;i<r_count;i++)// цикл по случайным числам { int j=fi.indexOf((int)(x[i]*10)); if(j==-1) { fi.append((int)(x[i]*10)); fp.append(1); } else { fp[j]+=1; } } for(int i=0;i<fi.count();i++)// цикл по случайным числам { qDebug()<<"значения х:"<<fi[i]<<" вероятность: "<<fp[i]; } int count=0; for(int i=0;i<fi.count();i++)// цикл по случайным числам { count+=fp[i]; } qDebug()<<"Itogo: "<<count; this->update(); float pi2=sqrt(2.0*pi); for(float i=(mx-4*dx);i<=(mx+4*dx);i+=0.1) { xi.append(i*10); xip.append((1.0/(dx*pi2))*exp(-((i-mx)*(i-mx))/(2.0*dx*dx))); } QGraphicsScene *scena=new QGraphicsScene; scena->addLine(200,150,200,0,QPen(Qt::black)); scena->addLine(0,150,600,150,QPen(Qt::black)); for(int i=0;i<61;i++) { scena->addLine(i*10,150-5,i*10,150+5,QPen(Qt::black)); } for(int i=0;i<31;i++) { scena->addLine(i*100,150-10,i*100,150+10,QPen(Qt::black)); } for(int i=0;i<fi.count();i++) { scena->addEllipse(200+fi[i],150-10000*fp[i]/r_count,1,1,QPen(Qt::black)); } for(int i=0;i<xi.count();i++) { scena->addEllipse(200+xi[i],150-xip[i]*1000,1,1,QPen(Qt::red)); } xiexp=0.0; int countxi=xi.count(); int ix=0; float rc=(float)r_count; for(ix=0;ix<countxi;ix++) { int jf=0; while(xi[ix]!=fi[jf] && jf<fi.count()-1){jf++;} xiexp+=0.1*((fp[jf]-xip[ix]*r_count)*(fp[jf]-xip[ix]*r_count))/((xip[ix])*r_count); } ui->label_3->setText(QString::number(xiexp)); ui->graphicsView->setScene(scena); float min=chi2inv(1-0.01,r_count-3); float min25=chi2inv(1-0.25,r_count-3); float mid=chi2inv(1-0.5,r_count-3); float mid75=chi2inv(1-0.75,r_count-3); float max=chi2inv(1-0.999,r_count-3); ui->label_4->setText(QString::number(mid)); ui->label_5->setText(QString::number(max)); ui->label_10->setText(QString::number(min)); ui->label_12->setText(QString::number(min25)); ui->label_14->setText(QString::number(mid75)); } float chi2inv(float a, int n) { float d; if(a >= 0.001 && a < 0.5) d = - 2.0637 * pow((log(1.0/a) - 0.16), 0.4274) + 1.5774; else if(a <= 0.999) d = 2.0637 * pow((log(1.0/(1 - a)) - 0.16), 0.4274) - 1.5774; else return 0; float A = d * sqrt(2); float B = 2.0/3 * (d * d - 1); float C = d * (d * d - 7)/(9 * sqrt(2)); float D = (6 * pow(d, 4) + 14 * d * d - 32)/405; float E = d * (9 * pow(d, 4) + 256 * d * d - 433) / (4860 * sqrt(2)); return n + A * sqrt(n) + B + C/sqrt(n) + D/n + E/(n*sqrt(n)); } main.cpp #include <QtGui/QApplication> #include "mainwindow.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); } mainwindows.h #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QVector2D> #include "QPainter" namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); float r(); int r_count; int n; QVector<float> v; QVector<float> z; QVector<float> x; float mx; float dx; float pi; QVector<float> fi; QVector<float> fp; QVector<float> xi; QVector<float> xip; float xiexp; private slots: void on_pushButton_clicked(); private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H
Название: Re: Разобрать программу по теории Пирсона
Отправлено: vizir.vs от Май 27, 2014, 16:03
Здесь используется ЦПТ. Суть ее в том, что ты генеришь несколько выборок распределенных по равномерному закону (обычно от 12 выборок, но в вашем коде почему то только 6 (n=6)), а затем объединяешь их в одну выборку и получается нормальная выборка с параметрами 0;1. z.append((v[i]-(n/2.0))/sqrt(n/12.0)); это и есть объединение всех выборок в одну выборку. Так как нам нужна нормальная выборка, но с другими параметрами вы делаем следующие Вот здесь написано как можно моделировать нормальное распределение. (http://ru.wikipedia.org/wiki/%D0%9D%D0%BE%D1%80%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5_%D1%80%D0%B0%D1%81%D0%BF%D1%80%D0%B5%D0%B4%D0%B5%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5). Я сам раньше использовал для этого преобразование Бокса-Мюллера. Ну и у буста есть встроенные генераторы случайных чисел с различным распределением. Последнее время я его использую. Вот здесь пункт Г (http://www.ipages.ru/index.php?ref_item_id=116&ref_dl=1) более подробно объясняется как генерировать нормальный закон используя цпт. Что касается самого Пирсона, то суть его проста: 1. Разделить все пространство от минимума и до максимума на отрезки. Обычно используется формула 3,31ln n + 1. Где n-число элементов в выборке, но есть и другие формулы http://ami.nstu.ru/~headrd/seminar/publik_html/Z_lab_8.htm 2. Шаг второй - считаем количество элементов, которые попали в соответствующий интервал. 3. Шаг третий - смотрим разницу. Для этого суммируем по всем интервалам квадрат разницы между тем, сколько у нас попало элементов деленое на общее количество элементов и из дроби вычитаем вероятность попадания в интервал. Все это возводим в квадрат и делим на вероятность попадание в интервал. Полученную сумму умножаем на число элементов. Вот эта вычисление xiexp+=0.1*((fp[jf]-xip[ix]*r_count)*(fp[jf]-xip[ix]*r_count))/((xip[ix])*r_count);. Только я не совсем понял, почему здесь 0.1. Да и вообще периодически проскакивает умножение на 10, которое мне не очень понятно. Вот собственно и все. Вот это: float min=chi2inv(1-0.01,r_count-3); float min25=chi2inv(1-0.25,r_count-3); float mid=chi2inv(1-0.5,r_count-3); float mid75=chi2inv(1-0.75,r_count-3); float max=chi2inv(1-0.999,r_count-3); смотрит значение критерия пирсона при различном уровне значимости. Дальше глядим в таблицы и принимаем решение о принятие нулевой гипотезы (полученное распределение совпадает с предполагаемым) или отвергаем эту гипотезу (это нефига не наше распределение). P.S. Я бы выбросил эту прогу и переписал бы. Мух отдельно, котлеты отдельно. Да и магических чисел хватает.
Название: Re: Разобрать программу по теории Пирсона
Отправлено: Lagovas от Май 29, 2014, 01:21
Пол года назад делал преподу методу по лабе на эту тему. Только там python + orange. Делал конечно на отмашку, но помню сам тогда разобрался. Если интересует, обращайтесь через емейл.
Название: Re: Разобрать программу по теории Пирсона
Отправлено: vizir.vs от Май 29, 2014, 15:11
Я диссер пишу, у меня там используется нормальное распределение и критерий Пирсона для проверки на нормальность. Пишу все на Qt + C++
|