Рефераты - Афоризмы - Словари
Русские, белорусские и английские сочинения
Русские и белорусские изложения
 

Интерполяционные сплайны на прямоугольных сетках

Работа из раздела: «Математика»

/

/

Введение

математика интерполяционный программа многочлен

Теория приближений -- раздел математики, изучающий вопрос о возможности приближенного представления одних математических объектов другими, как правило, более простой природы, а также вопросы об оценках вносимой при этом погрешности. Значительная часть теории приближения относится к приближению одних функций другими, однако есть и результаты, относящиеся к абстрактным векторным или топологическим пространствам.

Теория приближений активно используется при построении численных алгоритмов, а также при сжатии информации.

В вычислительной математике существенную роль играет интерполяция функций. Она представляет собой один из простых и старейших способов восстановления неизвестной функции на некотором множестве по набору известных значений в отдельных точках этого множества. Для нахождения многих функций, оказывается, эффективно приблизить их алгебраическими многочленами. Наиболее известная интерполяционная формула была открыта Лагранжем в 1975 г. В Scopus опубликовано немало работ связанных с полиномом Лагранжа (см. [1], [2], [3]).

1. Построение интерполяционного многочлена из пространства

Дана функция f(x,y), необходимо найти интерполяционный многочлен и найти точность приближения.

Общая формула интерполяционного многочлена Лагранжа p(x,y) ?, имеет вид

? R.

На квадрате Q[0;1]2 строятся узлы. D = dim =(m+1)(n+1) - минимально число узлов интерполяции, гарантирующее единственное решение задачи.

Выбор узлов выглядит так,

Рис. 1 Выбор узлов

Ось X - на отрезке [0;1] делится на m равных отрезков,

Ось Y - на отрезке [1;0] делится на n равных отрезков, а точки пересечения и будут узлами интерполяции.

:=(; i=0,…,m; j=0,…,n;

- узлы сетки, получающиеся при разбиении координатных сторон квадрата.

Пусть f ? C(Q), Задача интерполяции заключается в нахождении такого многочлена p ? , для которого

p( = ; i=0,…,m; j=0,…,n; (1)

Решение задачи (1) дается следующим аналогом формулы Лагранжа. Положим

Тогда многочлен

принадлежит . Тогда для нахождения точности разделим отрезок [0;1] и [1;0] на 1000 (к примеру, можно делить на большее число, чем больше число, тем больше вероятность достигнуть наилучшей точности) равных по длине отрезков. Получим по x и y 1000 новых точек равноудаленных друг от друга. Тогда нахождение точности сводится к формуле

2. Приближение кусочно-полиномиальными функциями

Пусть функция задана на единичном квадрате . Обозначим через р разбиение этого квадрата на прямоугольники, стороны которых параллельны сторонам квадрата. Кроме того, если все прямоугольники равны между собой и длины их сторон в направлениях осей равны и , то такое разбиение будем обозначать . Наконец, в случае (разбиение на будет просто писать ). В дальнейшем, говоря о прямоугольниках из разбиения р, мы будем исключать их верхние и правые границы, если они не совпадают с границей единичного квадрата. Таким образом, прямоугольники из разбиения р не пересекаются, и их объединение дает единичный квадрат.

Введем теперь множество р) кусочно-полиномиальных функций степени (m,n), подчинённых разбиению р. Каждая функция из этого множества на прямоугольнике из разбиения р совпадает с некоторым многочленом p из пространства .

Рассмотрим вопрос о нахождении кусочно-полиномиальной функции g* наилучшего приближения. Такая функция определяется соотношением

Теоретически вопрос решается следующим образом. Нужно на каждом прямоугольнике из разбиения р построить для функции f многочлен наилучшего приближения из пространства . Но так как эта задача является весьма сложной, то в моей работе я использую интерполяционный многочлен Лагранжа для приближения данной функции (построение интерполяционного многочлена рассматривалось ранее в данной работе). Таким образом, если разбиение р заранее задано, то нетрудно построить кусочно-полиномиальную функцию, которая дает приближение почти как наилучшая.

Перейдя к более сложной ситуации, когда разбиение заранее не задано: при этом нужно найти кусочно-полиномиальную функцию, приближающую заданную функцию, c точностью е. Разбиение, которому будет подчинена кусочно-полиномиальная функция, зависит и от функции , и от точности е. Такой процесс приближения называется адаптивным, так как разбиение подстраивается под характер особенностей функции. В частности, если у функции нет особенностей, то разбиение будет состоять из почти равных прямоугольников. Ниже будет рассмотрен один из таких алгоритмов.

Уточним постановку задачи. На квадрате задана непрерывная функция : кроме того, заданы числа и е>0. Нужно построить такое разбиение единичного квадрата р= р(), что

3. Описание алгоритма программы и примеры её реализации

На квадрате построим интерполяционный многочлен из пространства и найдем погрешность приближения. Если погрешность меньше , то искомая функция. В этом случае разбиение р состоит из единственного квадрата . Пусть погрешность приближения (т.е. ) больше . Разделим квадрат на четыре равных квадрата:

[

[

На каждом из этих квадратов построим интерполяционный многочлен (i,j=0,1). Вычислим погрешности:

Возможны две ситуации: и . Если хотя бы один из квадратов удовлетворяет второй ситуации, то все квадраты подвергаются дальнейшему делению на четыре равных квадрата, и весь описанный процесс повторяется. Если все квадраты удовлетворяют первому условию, то процесс достижения точность завершается.

Примеры работы программы:

Здесь приведен пример, когда многочлен , то есть состоит из одних констант. Многочлен здесь красного цвета, а сама функция зеленого. При уменьшении точности количество квадратов будет расти, а соответственно и число многочленов:

Далее рассмотрим пример, когда меняется не точность, а степени многочлена:

При увеличении степеней многочлена видно, что многочлен всё сильнее приближается к исходной функции.

Заключение

Интерполирование функций довольно трудоемкий процесс, в плане количества операций вычислений. В данной работе приведена необходимая информация и изучается проблема, которая связана со сложностью интерполяции функции. Рассматривается область применения теории интерполирования. В работе ставится такая актуальная проблема в математике, а именно, в теории приближения, как приближение заданной функции с помощью более простых.

В данной работе мною было изучено построение интерполяционного многочлена Лагранжа двух переменных x и y, степени не больше m и n соответственно. Реализован алгоритм приближения интерполяционными сплайнами на прямоугольных сетках. Исходя из тестов программы, можно сказать, что при увеличении степеней многочлена и при фиксированной точности, мы достигаем этой точности за меньшее число шагов. При фиксированных степенях полинома и при уменьшении точности, мы достигаем этой точности за большее число шагов, что приводит к более долгому процессу нахождения всех полиномов, т.к. их становится больше.

Список литературы

1. Невский М.В., Иродова И.П. Некоторые вопросы теории приближения функций. Ярославль, 1999.

2. Брудный Ю.А. Теория приближения. Ярославль, 1981.

3. « И.А. Шакиров, “О влиянии выбора узлов лагранжевой интерполяции на точные и приближенные значения констант Лебега”, Сиб. матем. журн., 55:6 (2014), 1404-1423».

4. «И.А. Шакиров, “О тригонометрическом интерполяционном полиноме Лагранжа, имеющем минимальную норму как оператор из C2р в C2р”, Изв. вузов. Матем., 2010, №10, 60-68».

5. «Е.А. Волков, “О применении интерполяционного многочлена Лагранжа при решении методом сеток задачи Дирихле для уравнения Пуассона”, Ж. вычисл. матем. и матем. физ., 4:3 (1964), 466-472».

Приложение

Описание программной среды и языков программирования:

Средой программирования была выбрана Microsoft Visual Studio 2013. такой выбор был сделан в силу ее ориентации под программные продукты, работающие в ОС Windows, которая в свою очередь является самой популярной операционной системой. Языком, на котором написана программа стал C#, с подключенной компонентой Windows Forms. Это взаимодействие позволило представить программу пользователю в дружественном и интуитивно понятном интерфейсе.

Код программы:

CalculateCore.cs

using System;

using System.Collections.Generic;

using System.Linq;

namespace Interpolation

{

class Point3D

{

public double X { get; set; }

public double Y { get; set; }

public double Z { get; set; }

}

class CalculationCore

{

private int _m;

private int _n;

public int M

{

get { return _m - 1; }

set { _m = value + 1; }

}

public int N

{

get { return _n - 1; }

set { _n = value + 1; }

}

public double CalculateDeltaFunctionsNorm(Func<double, double, double> func1, Func<double, double, double> func2,

double x0, double y0, double x1, double y1)

{

var values1 = CalculatePointsForFunctionOnSquare(func1, x0, y0, x1, y1, 10, 10).Select(v => v.Z).ToArray();

var values2 = CalculatePointsForFunctionOnSquare(func2, x0, y0, x1, y1, 10, 10).Select(v => v.Z).ToArray();

return values1.Select((t, i) => Math.Abs(t - values2[i])).Concat(new[] {0.0}).Max();

}

public List<Point3D> CalculatePointsForFunctionOnSquare(Func<double, double, double> function, double x0, double y0,

double x1, double y1, int xPointCount, int yPointCount)

{

var result = new List<Point3D>();

double xStep = (x1 - x0)/xPointCount;

double yStep = (y1 - y0)/yPointCount;

for (int i = 0; i <= xPointCount; i++)

for (int j = 0; j <= yPointCount; j++)

result.Add(new Point3D()

{

X = x0 + i*xStep,

Y = y0 + j*yStep,

Z = function(x0 + i*xStep, y0 + j*yStep)

});

return result;

}

public Func<double, double, double> CalculatePolynomOnSquareByFunction(Func<double, double, double> function, double x0, double y0,

double x1, double y1)

{

double xStep = (x1 - x0) / _m;

double yStep = (y1 - y0) / _n;

var lComponents = new List<Func<double, double>>();

var mComponents = new List<Func<double, double>>();

for (int i = 0; i <= _m; i++)

lComponents.Add(CalculateComponent(i, x0, x1, _m));

for (int j = 0; j <= _n; j++)

mComponents.Add(CalculateComponent(j, y0, y1, _n));

Func<double, double, double> polynom = (x, y) =>

{

double r = 0;

if (M == 0 || N == 0)

r = function((x0 + x1)/2, (y0 + y1)/2);

else

{

for (int i = 0; i <= _m; i++)

for (int j = 0; j <= _n; j++)

r += function(x0 + i*xStep, y0 + j*yStep)*lComponents[i](x)*

mComponents[j](y);

}

return r;

};

return polynom;

}

private Func<double, double> CalculateComponent(int k, double p0, double p1, int count)

{

return x =>

{

double result = 1.0;

var step = (p1 - p0)/count;

for (int i = 0; i <= count; i++)

if (i!= k)

result *= (x - (p0 + i*step))/((k - i)*step);

return result;

};

}

}

}

MainForm.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Threading.Tasks;

using System.Windows.Forms;

using Tao.FreeGlut;

using Tao.OpenGl;

namespace Interpolation

{

public partial class MainForm: Form

{

private readonly Func<double, double, double> _baseFunction = (x, y) => Math.Sin(x*10) + Math.Sin(y);

private double _eps = 0.001;

private int QuadCount;

List<List<Point3D>> _functionPoints;

List<List<Point3D>> _polynomPoints;

public MainForm()

{

InitializeComponent();

OglOutput.InitializeContexts();

InitGlut();

}

private void InitGlut()

{

Glut.glutInit();

Glut.glutInitDisplayMode(Glut.GLUT_RGB | Glut.GLUT_DOUBLE | Glut.GLUT_DEPTH);

Gl.glClearColor(255, 255, 255, 1);

Gl.glViewport(0, 0, OglOutput.Width, OglOutput.Height);

Gl.glMatrixMode(Gl.GL_PROJECTION);

Gl.glLoadIdentity();

Glu.gluPerspective(45, (float)OglOutput.Width / OglOutput.Height, 0.1, 200);

Gl.glMatrixMode(Gl.GL_MODELVIEW);

Gl.glLoadIdentity();

Gl.glEnable(Gl.GL_DEPTH_TEST);

Gl.glPolygonMode(Gl.GL_FRONT_AND_BACK, Gl.GL_FILL);

}

private async void StartQuadsInterpolation()

{

_eps = double.Parse(textBoxEps.Text);

var calculations = new CalculationCore {M = int.Parse(textBoxM.Text), N = int.Parse(textBoxN.Text)};

int quadCount = 0;

double maxDelta;

await Task.Factory.StartNew(() =>

{

do

{

quadCount++;

var quadSize = 1.0/Math.Pow(2, quadCount);

var deltas = new List<double>();

for (int i = 0; i < Math.Pow(2, quadCount); i++)

for (int j = 0; j < Math.Pow(2, quadCount); j++)

{

var polynom = calculations.CalculatePolynomOnSquareByFunction(_baseFunction,

i*quadSize, j*quadSize,

(i + 1)*quadSize, (j + 1)*quadSize);

deltas.Add(calculations.CalculateDeltaFunctionsNorm(_baseFunction, polynom,

i*quadSize, j*quadSize,

(i + 1)*quadSize, (j + 1)*quadSize));

}

maxDelta = deltas.Max();

} while (maxDelta > _eps);

});

quadsCountLabel.Text = 'Number decompositions: ' + (quadCount);

QuadCount = (int)Math.Pow(2, quadCount);

CalculatePoints(calculations);

DrawGraph();

}

private void DrawGraph()

{

Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);

Gl.glLoadIdentity();

Gl.glPushMatrix();

Gl.glTranslated(0, -0.27, -10.0/(zoomBar.Value+1));

Gl.glRotated(90, -1, 0, 0);

Gl.glRotated(xAngleBar.Value*5, 1, 0, 0);

Gl.glRotated(yAngleBar.Value*5, 0, 1, 0);

Gl.glRotated(zAngleBar.Value*5, 0,0, 1);

DrawGrid();

DrawPolygons();

Gl.glPopMatrix();

Gl.glFlush();

OglOutput.Invalidate();

}

private void DrawPolygons()

{

if (checkBoxFunction.Checked)

{

Gl.glColor3f(0.0f, 0.7f, 0.0f);

DrawSurface(_functionPoints);

}

if (checkBoxPolynom.Checked)

{

Gl.glColor3f(0.7f, 0.0f, 0.0f);

DrawSurface(_polynomPoints);

}

}

private void CalculatePoints(CalculationCore calculations)

{

_functionPoints = new List<List<Point3D>>();

_polynomPoints = new List<List<Point3D>>();

var quadSize = 1.0/QuadCount;

for (int i = 0; i < QuadCount; i++)

for (int j = 0; j < QuadCount; j++)

{

_functionPoints.Add(calculations.CalculatePointsForFunctionOnSquare(_baseFunction,

i*quadSize, j*quadSize,

(i + 1)*quadSize, (j + 1)*quadSize, 10, 10));

var polynom = calculations.CalculatePolynomOnSquareByFunction(_baseFunction,

i*quadSize, j*quadSize,

(i + 1)*quadSize, (j + 1)*quadSize);

_polynomPoints.Add(calculations.CalculatePointsForFunctionOnSquare(polynom,

i*quadSize, j*quadSize,

(i + 1)*quadSize, (j + 1)*quadSize, 10, 10));

}

}

private static void DrawSurface(List<List<Point3D>> points)

{

for (int k = 0; k < points.Count; k++)

{

Gl.glBegin(Gl.GL_TRIANGLES);

{

var internalCount = (int) Math.Sqrt(points[k].Count);

for (int i = 0; i < internalCount - 1; i++)

for (int j = 0; j < internalCount - 1; j++)

{

Gl.glVertex3d(points[k][i*internalCount + j].X, points[k][i*internalCount + j].Y,

points[k][i*internalCount + j].Z);

Gl.glVertex3d(points[k][i*internalCount + j + 1].X, points[k][i*internalCount + j + 1].Y,

points[k][i*internalCount + j + 1].Z);

Gl.glVertex3d(points[k][(i + 1) * internalCount + j].X, points[k][(i + 1) * internalCount + j].Y,

points[k][(i + 1) * internalCount + j].Z);

Gl.glVertex3d(points[k][i * internalCount + j + 1].X, points[k][i * internalCount + j + 1].Y,

points[k][i * internalCount + j + 1].Z);

Gl.glVertex3d(points[k][(i + 1) * internalCount + j].X, points[k][(i + 1) * internalCount + j].Y,

points[k][(i + 1) * internalCount + j].Z);

Gl.glVertex3d(points[k][(i + 1) * internalCount + j + 1].X, points[k][(i + 1) * internalCount + j + 1].Y,

points[k][(i + 1) * internalCount + j + 1].Z);

}

}

Gl.glEnd();

}

}

private void DrawGrid()

{

Gl.glBegin(Gl.GL_LINES);

{

Gl.glColor3f(1.0f, 0, 0);

Gl.glVertex3d(0, 0, 0);

Gl.glVertex3d(2, 0, 0);

Gl.glColor3f(0, 1.0f, 0);

Gl.glVertex3d(0, 0, 0);

Gl.glVertex3d(0, 2, 0);

Gl.glColor3f(0, 0, 1.0f);

Gl.glVertex3d(0, 0, 0);

Gl.glVertex3d(0, 0, 2);

Gl.glColor3f(0.5f, 0.5f, 0.5f);

for (int i = 0; i < QuadCount; i++)

{

Gl.glVertex3d((1.0/QuadCount)*(i + 1), 0, 0);

Gl.glVertex3d((1.0/QuadCount)*(i + 1), 1, 0);

Gl.glVertex3d(0, (1.0/QuadCount)*(i + 1), 0);

Gl.glVertex3d(1, (1.0/QuadCount)*(i + 1), 0);

}

}

Gl.glEnd();

}

private void drawButton_Click(object sender, EventArgs e)

{

StartQuadsInterpolation();

}

private void AngleBar_Scroll(object sender, EventArgs e)

{

if (_functionPoints!= null && _polynomPoints!= null)

DrawGraph();

}

}

}

Program.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Threading.Tasks;

using System.Windows.Forms;

namespace Interpolation

{

static class Program

{

/// <summary>

/// The main entry point for the application.

/// </summary>

[STAThread]

static void Main()

{

Application.EnableVisualStyles();

Application.SetCompatibleTextRenderingDefault(false);

Application.Run(new MainForm());

}

}

}

ref.by 2006—2019
contextus@mail.ru