i found good code to do some polynomial least squares fitting based on GSL.
i am using it with 3 degrees: y = Cx² + Bx + A.
In my application i know that A must be zero. Is it possible to change the algorithm so that A alway will be zero?
bool polynomialfit(int obs, int degree,
double *dx, double *dy, double *store) /* n, p */
{
gsl_multifit_linear_workspace *ws;
gsl_matrix *cov, *X;
gsl_vector *y, *c;
double chisq;
int i, j;
X = gsl_matrix_alloc(obs, degree);
y = gsl_vector_alloc(obs);
c = gsl_vector_alloc(degree);
cov = gsl_matrix_alloc(degree, degree);
for(i=0; i < obs; i++) {
gsl_matrix_set(X, i, 0, 1.0);
for(j=0; j < degree; j++) {
gsl_matrix_set(X, i, j, pow(dx[i], j));
}
gsl_vector_set(y, i, dy[i]);
}
ws = gsl_multifit_linear_alloc(obs, degree);
gsl_multifit_linear(X, y, c, cov, &chisq, ws);
/* store result ... */
for(i=0; i < degree; i++)
{
store[i] = gsl_vector_get(c, i);
}
gsl_multifit_linear_free(ws);
gsl_matrix_free(X);
gsl_matrix_free(cov);
gsl_vector_free(y);
gsl_vector_free(c);
return true; /* we do not "analyse" the result (cov matrix mainly)
to know if the fit is "good" */
}
You can replace y by y' = y/x and then perform fitting of a 1. degree polynomial y'= Cx + B?
(if point x = 0 is present in your data set you have to remove it but this point does not improve fit in case you want to apply the A = 0 constraint, you can still use it to re-compute goodness of fit)
In the code you posted there is this loop:
for(j=0; j < degree; j++) {
gsl_matrix_set(X, i, j, pow(dx[i], j));
}
and the function pow computes the x^j terms, you have to "ignore" the term where j==0.
I have no access to GSL and so the following is just off the top of my head and it is untested:
bool polynomialfit(int obs, int polynom_degree,
double *dx, double *dy, double *store) /* n, p */
{
gsl_multifit_linear_workspace *ws;
gsl_matrix *cov, *X;
gsl_vector *y, *c;
double chisq;
int i, j;
int degree = polynom_degree - 1;
X = gsl_matrix_alloc(obs, degree);
y = gsl_vector_alloc(obs);
c = gsl_vector_alloc(degree);
cov = gsl_matrix_alloc(degree, degree);
for(i=0; i < obs; i++) {
gsl_matrix_set(X, i, 0, 1.0);
for(j=0; j < degree; j++) {
gsl_matrix_set(X, i, j, pow(dx[i], j+1));
}
gsl_vector_set(y, i, dy[i]);
}
ws = gsl_multifit_linear_alloc(obs, degree);
gsl_multifit_linear(X, y, c, cov, &chisq, ws);
/* store result ... */
for(i=0; i < degree; i++)
{
store[i] = gsl_vector_get(c, i);
}
gsl_multifit_linear_free(ws);
gsl_matrix_free(X);
gsl_matrix_free(cov);
gsl_vector_free(y);
gsl_vector_free(c);
return true; /* we do not "analyse" the result (cov matrix mainly)
to know if the fit is "good" */
}
In order to fit to y=c*x*x+b*x you have to call it with polynom_degree set to 3.
You also may have a look at the theory:
Weisstein, Eric W. "Least Squares Fitting--Polynomial." From MathWorld--A Wolfram Web Resource. http://mathworld.wolfram.com/LeastSquaresFittingPolynomial.html
Related
For example, in Visual Studio there is tChart and its Series property, which is responsible for drawing lines of the graph. Here is an example of this code
for (int j = 1; j < Nt - 1; j++)
{
for (int i = 1; i < Nt - 1; i++)
{
chart2->Series["" + (j + 1).ToString()]->Points->AddXY(i, wht[j][i]);
}
}
And draw this graph with a lot of lines.
But my task is transfering in Qt Creator(because in Qt Creator may making a lot of opportunities)
This code
void MainWindow::drawdifnet(int Nt)
{
int N=Nt;
int N1=pow(N,2);
QVector<double> x22(N), y22(N1);
int ii=0,jj=0;
for (int j = 0; j < Nt ; j++)
{
for (int i = 0; i < Nt ; i++)
{
x22[jj]=i;
y22[ii]=wht[j][i];
ui->widget_2->addGraph();
ui->widget_2->graph(0)->setData(x22,y22);
ii++;
}
jj++;
}
ui->widget_2->xAxis->setLabel("OsX");
ui->widget_2->yAxis->setLabel("OsY");
ui->widget_2->xAxis->setRange(30,30);
ui->widget_2->replot();
}
Doesn't work correctly.
Result is the empty widget
In first I with help debugger check the QVectors data
In this pictures see that my dinamic array wht[j][i] in work and loaded in QVector yy[ii]
I think the problem in the loop.
In QtCustomPlot tutorial this problem solving this code
ui->widget_2->graph(0)->setData(x,y);
ui->widget_2->graph(1)->setData(x11,y11);
ui->widget_2->graph(2)->setData(x22,y22);
But in my situation the quantity of lines is know when the program working.
How I create and assigned my array
void created(int Nt, int Nx) ///This function creating my dynamic array
{
wht = new double *[Nt];
for (int i = 0; i < Nt; i++)
wht[i] = new double[Nx];
}
inline double fn(int T, double x) ///these 4 functions for my mathematical part(works good)
{
if (x >= 0)
return T;
return 0;
}
inline double u0(int T, double x)
{
return fn(T, x);
}
inline double u1(int T, double a, int xmin, double t)
{
return fn(T, xmin - a * t);
}
inline double u2(int T, double a, int xmax, double t)
{
return fn(T, xmax - a * t);
}
void calculatedifnet(int xmin, double hx, double ht, double a, int Nx, int Nt, int T)
//These main function.We have the empty array and in this function we fill array. Then we solve in the main loop and the fill the first indexes wht[j]
{
for (int i = 0; i < Nt; i++)
{
wht[0][i] = u0(T, xmin + i*hx);//fill the second indexeswht[null][i]
}
for (int j = 0; j < Nt - 1; j++)//the calculated code(works right).The result writing in wht[j]
{
wht[j + 1][0] = u1(T, a, xmin, j*ht);
for (int i = 1; i < Nt; i++)
{
double dudx = (wht[j][i] - wht[j][i - 1]) / hx;
wht[j + 1][i] = -a * dudx * ht + wht[j][i];
}
}
}
In your code there are the following errors:
If we observe x is a constant vector from 0 to Nt-1, then we only have to create it once:
QVector<double> x(Nt);
for (int i = 0; i < Nt ; i++)
x[i]=i;//0 to Nt-1
addGraph() adds a graph and places it in the last position, if you want to graph you must access by the last index, not by the index 0:
ui->widget_2->addGraph()->setData(xx, yy);
Assuming that wht is of type QVector<QVector<double>> and of size NtxNt, then is not necessary to access each element, we can access each QVector<double> since the function setData() accepts as input this type of data. To the function setData() you must pass 2 vectors of the same size, but you were passing 2 vectors of Nt and Nt*Nt, this generated a warning:
ui->widget_2->addGraph()->setData(x, wht[j]);
setRange() places the range from a to b, but if they are the same QCustomPlot will never fit the range, for my test I set it as follows:
ui->widget_2->xAxis->setRange(0,Nt);
ui->widget_2->yAxis->setRange(0,Nt*Nt);
In short the code would be as follows:
void MainWindow::drawdifnet(int Nt){
QVector<double> x(Nt);
for (int i = 0; i < Nt ; i++)
x[i]=i;//0 to Nt-1
for (int j = 0; j < Nt ; j++)
ui->widget_2->addGraph()->setData(x, wht[j]);
/* if c++11
for (auto& row: wht)
ui->widget_2->addGraph()->setData(x, row);
*/
ui->widget_2->xAxis->setLabel("OsX");
ui->widget_2->yAxis->setLabel("OsY");
ui->widget_2->xAxis->setRange(0,Nt);
ui->widget_2->yAxis->setRange(0,Nt*Nt);
ui->widget_2->replot();
}
Output:
Note: For the test wht[i][j] = i*j
In your case wht is a variable of type double**, also assume that Nx>=Nt, for this you must use the following code:
void MainWindow::drawdifnet(int Nt)
{
QVector<double> x(Nt);
for (int i = 0; i < Nt ; i++){
x[i]=i;//0 to Nt-1
}
QVector<double> y(Nt);
for(int i=0; i<Nt; i++){
for(int j=0; j<Nt; j++){
y[j] = wht[i][j];
}
ui->widget_2->addGraph()->setData(x, y);
}
ui->widget_2->xAxis->setLabel("OsX");
ui->widget_2->yAxis->setLabel("OsY");
ui->widget_2->xAxis->setRange(0,12);
ui->widget_2->yAxis->setRange(0,3.5);
ui->widget_2->replot();
}
Input:
created(12, 12);
calculatedifnet(1, .5, .5, 0.9, 12, 12, 3);
Output:
The code on Gauss-Jacobi method in Applied maths doesn't execute successfully on compilation although there are no errors:
void main(){
int a[3][4], i, j, k;
float x,y,z;
printf("Enter coeff of 3 equations and RHS :");
for(i = 1; i <= 3; i++){
printf("\nEQUATION %d",i);
for(j = 1; j <= 4; j++){
scanf("%d",&a[i][j]);
}
}
x = (a[1][4])/(a[1][1]);
y = (a[2][4])/(a[2][2]);
z = (a[3][4])/(a[3][3]);
printf("\nx0=%d y0=%d and z0=%d", x, y, z);
printf("\nEnter no. of iterations:");
scanf("%d", &k);
i=0;
while(i < k){
i++;
x = a[1][4]-(a[1][2]*y)-(a[1][3]*z);
y = a[2][4]-(a[2][3]*z)-(a[2][1]*x);
z = a[3][4]-(a[3][2]*y)-(a[3][1]*x);
printf("\n after %d itr,\n x=%f\ny=%f\n z=%f", i, x, y, z);
}
}
The problem your code are the things like these: x = (a[1][4])/(a[1][1]);. Here x is float var and calculation you are doing in that are both int values. As #PhilM stated, 3/4 == 0, because integers aren't floating point numbers. To fix this, you should consider doing casting. It will fix your problem.
How to cast example:
#include <stdio.h>
main() {
int sum = 17, count = 5;
double mean;
mean = (double) sum / count;
printf("Value of mean : %f\n", mean );
}
Casting is simple, you just put (the type of var) in front of the variable. In your case, (float)(a[1][4])/ (float)(a[1][1]);.
I have a 3d array containing a sphere where inside the spherical boundary the data points are one and outside the spherical boundary the data points are 0. I want to take a fftw of this array and then ifftw it back. I should end up back with the sphere.
Here is my code:
int num = 100;
int cube = pow(num, 3);
int i, j, k;
fftw_complex *out;
double *in, *fin;
/* Allocate memory*/
out = (fftw_complex *) fftw_malloc(num * num* (num/2 +1) sizeof(fftw_complex));
in = (double *) fftw_malloc(cube * sizeof(double));
fin = (double *) fftw_malloc(cube * sizeof(double));
/* Initialize fft & ifft plans */
fftw_plan plan;
fftw_plan inv_plan1 ;
plan = fftw_plan_dft_r2c_3d(num,num,num, in, out,FFTW_MEASURE);
inv_plan1 = fftw_plan_dft_c2r_3d(num, num, (num/2 +1), out, fin, FFTW_MEASURE);
int q = 0;
for (i = 0; i < num; i++)
{
for (j = 0; j < num; j++)
{
for (k = 0; k < num; k++)
{
in[q] = vals[i][j][k];
q++;
}
}
}
fftw_execute(plan);
fftw_execute(inv_plan1);
for (k = 0; k < cube; k++)
{
fin[k] =fin[k]/(cube);
}
When I execute this and then plot a slice through the resulting data set I get an image that contains many streaks (looks nothing like a sphere). However, if I change the dimensions of out from num * num * (num/2 +1) to num * num * num and the dimensions of inv_plan1 from num, num, (num/2 +1) to num, num, num then I get back the sphere. I am confused because from reading the fftw3 documentation for a r2c transformation if the input dimensions are n0 x n1 x n2, then the complex output should be n0 x n1 x (n2/2 + 1). Why is this not the case for the sphere?
(Also I am very new to c++, this is the first script I have written ! )
I am new to C++ and I am using the Eigen library. I was wondering if there was a way to sum certain elements in a vector. For example, say I have a vector that is a 100 by 1 and I just want to sum the first 10 elements. Is there a way of doing that using the Eigen library?
What I am trying to do is this: say I have a vector that is 1000 by 1 and I want to take the mean of the first 10 elements, then the next 10 elements, and so on and store that in some vector. Hence I will have a vector of size 100 of the averages. Any thoughts or suggestions are greatly appreciated.
Here is the beginning steps I have in my code. I have a S_temp4vector that is 1000 by 1. Now I intialize a new vector S_A that I want to have as the vector of the means. Here is my messy sloppy code so far: (Note that my question resides in the crudeMonteCarlo function)
#include <iostream>
#include <cmath>
#include <math.h>
#include <Eigen/Dense>
#include <Eigen/Geometry>
#include <random>
#include <time.h>
using namespace Eigen;
using namespace std;
void crudeMonteCarlo(int N,double K, double r, double S0, double sigma, double T, int n);
VectorXd time_vector(double min, double max, int n);
VectorXd call_payoff(VectorXd S, double K);
int main(){
int N = 100;
double K = 100;
double r = 0.2;
double S0 = 100;
double sigma = 0.4;
double T = 0.1;
int n = 10;
crudeMonteCarlo(N,K,r,S0,sigma,T,n);
return 0;
}
VectorXd time_vector(double min, double max, int n){
VectorXd m(n + 1);
double delta = (max-min)/n;
for(int i = 0; i <= n; i++){
m(i) = min + i*delta;
}
return m;
}
MatrixXd generateGaussianNoise(int M, int N){
MatrixXd Z(M,N);
static random_device rd;
static mt19937 e2(time(0));
normal_distribution<double> dist(0.0, 1.0);
for(int i = 0; i < M; i++){
for(int j = 0; j < N; j++){
Z(i,j) = dist(e2);
}
}
return Z;
}
VectorXd call_payoff(VectorXd S, double K){
VectorXd C(S.size());
for(int i = 0; i < S.size(); i++){
if(S(i) - K > 0){
C(i) = S(i) - K;
}else{
C(i) = 0.0;
}
}
return C;
}
void crudeMonteCarlo(int N,double K, double r, double S0, double sigma, double T, int n){
// Create time vector
VectorXd tt = time_vector(0.0,T,n);
VectorXd t(n);
double dt = T/n;
for(int i = 0; i < n; i++){
t(i) = tt(i+1);
}
// Generate standard normal Z matrix
//MatrixXd Z = generateGaussianNoise(N,n);
// Generate the log normal stock process N times to get S_A for crude Monte Carlo
MatrixXd SS(N,n+1);
MatrixXd Z = generateGaussianNoise(N,n);
for(int i = 0; i < N; i++){
SS(i,0) = S0;
for(int j = 1; j <= n; j++){
SS(i,j) = SS(i,j-1)*exp((double) (r - pow(sigma,2.0))*dt + sigma*sqrt(dt)*(double)Z(i,j-1));
}
}
// This long bit of code gives me my S_A.....
Map<RowVectorXd> S_temp1(SS.data(), SS.size());
VectorXd S_temp2(S_temp1.size());
for(int i = 0; i < S_temp2.size(); i++){
S_temp2(i) = S_temp1(i);
}
VectorXd S_temp3(S_temp2.size() - N);
int count = 0;
for(int i = N; i < S_temp2.size(); i++){
S_temp3(count) = S_temp2(i);
count++;
}
VectorXd S_temp4(S_temp3.size());
for(int i = 0; i < S_temp4.size(); i++){
S_temp4(i) = S_temp3(i);
}
VectorXd S_A(N);
S_A(0) = (S_temp4(0) + S_temp4(1) + S_temp4(2) + S_temp4(3) + S_temp4(4) + S_temp4(5) + S_temp4(6) + S_temp4(7) + S_temp4(8) + S_temp4(9))/(n);
S_A(1) = (S_temp4(10) + S_temp4(11) + S_temp4(12) + S_temp4(13) + S_temp4(14) + S_temp4(15) + S_temp4(16) + S_temp4(17) + S_temp4(18) + S_temp4(19))/(n);
int count1 = 0;
for(int i = 0; i < S_temp4.size(); i++){
S_A(count1) =
}
// Calculate payoff of Asian option
//VectorXd call_fun = call_payoff(S_A,K);
}
This question includes a lot of code, which makes it hard to understand the question you're trying to ask. Consider including only the code specific to your question.
In any case, you can use Eigen directly to do all of these things quite simply. In Eigen, Vectors are just matrices with 1 column, so all of the reasoning here is directly applicable to what you've written.
const Eigen::Matrix<double, 100, 1> v = Eigen::Matrix<double, 100, 1>::Random();
const int num_rows = 10;
const int num_cols = 1;
const int starting_row = 0;
const int starting_col = 0;
const double sum_of_first_ten = v.block(starting_row, starting_col, num_rows, num_cols).sum();
const double mean_of_first_ten = sum_of_first_ten / num_rows;
In summary: You can use .block to get a block object, .sum() to sum that block, and then conventional division to get the mean.
You can reshape the input using Map and then do all sub-summations at once without any loop:
VectorXd A(1000); // input
Map<MatrixXd> B(A.data(), 10, A.size()/10); // reshaped version, no copy
VectorXd res = B.colwise().mean(); // partial reduction, you can also use .sum(), .minCoeff(), etc.
The Eigen documentation at https://eigen.tuxfamily.org/dox/group__TutorialBlockOperations.html says an Eigen block is a rectangular part of a matrix or array accessed by matrix.block(i,j,p,q) where i and j are the starting values (eg 0 and 0) and p and q are the block size (eg 10 and 1). Presumably you would then iterate i in steps of 10, and use std::accumulate or perhaps an explicit summation to find the mean of matrix.block(i,0,10,1).
I've tried to implement Newton's method for polynomials. Like:
double xn=x0;
double gxn=g(w, n, xn);
int i=0;
while(abs(gxn)>e && i<100){
xn=xn-(gxn/dg(w, n, xn));
gxn=g(w, n, xn);
i++;
}
where g(w, n, xn) computes the value of the function and dg(w, n, xn) computes the derivative.
As x0 I use starting point M which I found using Sturm's theorem.
My problem is that this method is divergent for some polynomials like x^4+2x^3+2x^2+2x+1. Maybe it's not regular, but I noticed that it happens when the solution of the equation is a negative number. Where can I look for an explanation?
Edit:
dg
double result=0;
for(int i=0; i<n+1; i++)
result+=w[i]*(n-i)*pow(x, n-i-1);
where n is the degree of polynomial
I'm not sure why would you say it's divergent.
I implemented Newton's method similarly to yours:
double g(int w[], int n, double x) {
double result = 0;
for (int i = 0; i < n + 1; i++)
result += w[i] * pow(x, n - i);
return result;
}
double dg_dx(int w[], int n, double x) {
double result = 0;
for (int i = 0; i < n ; i++)
result += w[i] * (n - i) * pow(x, n - i - 1);
return result;
}
int main() {
double xn = 0; // Choose initial value. I chose 0.
double gx;
double dg_dx_x;
int w[] = { 1, 2, 2, 2, 1 };
int i = 0;
int n = 4;
do {
gx = g(w, n, xn);
dg_dx_x = dg_dx(w, n, xn);
xn = xn - (gx / dg_dx_x);
i++;
} while (abs(gx) > 10e-5 && i < 100);
std::cout << xn << '\n';
}
And it yields -0.997576, which is close to the solution -1.