Ortogonalizacja

Przestrzenie wektorowe, bazy, liniowa niezależność, macierze.... Formy kwadratowe, twierdzenia o klasyfikacji...
Awatar użytkownika
Mariusz M
Użytkownik
Użytkownik
Posty: 6909
Rejestracja: 25 wrz 2007, o 01:03
Płeć: Mężczyzna
Lokalizacja: 53°02'N 18°35'E
Podziękował: 2 razy
Pomógł: 1246 razy

Ortogonalizacja

Post autor: Mariusz M »

Przypuśćmy że chciałbym ortogonalizować bazę wielomianów \(\displaystyle{ \left\{ 1,x,x^2,_\cdots,x^n\right\} }\)
iloczynem skalarnym \(\displaystyle{ \left\langle p,q\right\rangle = \int_{-1}^{1}p\left( x\right)q\left(x \right)\frac{1}{ \sqrt{1-x^2} }\mbox{d}x }\)
Ten iloczyn skalarny można rozpisać w następujący sposób

Niech \(\displaystyle{ p\left( x\right)q\left( x\right)= \sum_{k=0}^{m+n}a_{k}x^{k}}\)
wówczas \(\displaystyle{ \left\langle p\left( x\right),q\left( x\right) \right\rangle = \sum_{k=0}^{\lfloor\frac{m+n}{2}\rfloor}a_{2k} \cdot \frac{1}{2^{2k}} \cdot {2k \choose k} \cdot \pi }\)

Napisałem nawet program w C# ale użyłem w nim ortogonalizacji Grama - Schmidta

Kod: Zaznacz cały

using System;
using System.Globalization;
namespace NamespaceName
{
	public class ClassName
	{
		
		public static void Main(string[] args)
		{
			int n;
			double[,] Q;
			double sum;
			char esc; 
			do
			{
				Console.WriteLine("Podaj stopień macierzy");
				int.TryParse(Console.ReadLine(),out n);
				Q = new double[n+1,n+1];
				ModifiedGramSchmidt(n,Q);
				for(int i=0;i<=n;i++)
				{
					sum = 0;
					for(int j=0; j<=n;j++)
						sum += Q[j,i];
					for(int j=0; j<=n;j++)
						Q[j,i] /= (double)sum;
				}
				PrintMatrix(Q);
				esc = (char)Console.ReadKey().Key;
			}
			while(esc != (char)ConsoleKey.Escape);
		}
		public static void PrintMatrix(double[,] A)
		{
			NumberFormatInfo nfi = new NumberFormatInfo();
			nfi.NumberDecimalDigits = 12;
			nfi.NumberGroupSeparator = "";
			for(int i=0;i<A.GetLength(0);i++)
			{
				for(int j=0;j<A.GetLength(1);j++)
				{
					Console.Write("{0} , ",A[i,j].ToString("N",nfi));
				}
				Console.WriteLine();
			}
			Console.WriteLine();
		}
		public static double InnerProduct(int m, int n,double[] P,double[] Q)
		{
			double sum = 0.0;
			double prod = 1.0;
			double[] C = new double[n + m + 1];
			Array.Clear(C,0,C.Length);
			for(int i = 0;i <= m;i++)
			{
				for(int j = 0; j <= n;j++)
				{
					C[i + j] += P[i]*Q[j];	
				}
			}
			for(int k = 0;k <= m + n;k += 2)
			{
				sum += C[k] * prod;
				prod *= (double)(k + 1)/(k + 2);
			}
		    return sum * Math.PI; 
		}
		public static double[] GetColumn(double[,] A,int j)
		{
			double[] temp = new double[A.GetLength(1)];
			for(int k = 0;k < A.GetLength(1);k++)
			{
				temp[k] = A[k,j];
			}
			return temp;
		}
		public static void ModifiedGramSchmidt(int n, double[,] Q)
		{
			/*
			    for j = 1:n
			       v_{j} = x_{j};
			    end for
			    for j = 1:n
			        q_{j} = v_{j} / ||v_{j}||_{2}
			      for k = j + 1:n
			          v_{k} = v_{k} - (q_{j}^{T}v_{k})*q_{j}
			      end for
			    end for   
			 */
			 double[,] V = new double[n + 1,n + 1];
			 for(int i=0;i<=n;i++)
				for(int j=0;j<=n;j++)
					V[i,j] = (i==j?1:0);
			for(int j = 0;j <= n;j++)
			{
				double invnorm = 1.0/Math.Sqrt(InnerProduct(j,j,GetColumn(V,j),GetColumn(V,j)));
				for(int i=j;i>=0;i--)
					Q[i,j] = invnorm*V[i,j]; 
				for(int k = j+1;k <= n;k++)
				{
					double w = InnerProduct(j,k,GetColumn(Q,j),GetColumn(V,k));
					for(int i = k;i >= 0;i--)
					{
						V[i,k] -= w*Q[i,j] ; 
					}
				}
			}
			
		} 
	}
}
I teraz chciałbym zastąpić metodę Grama - Schmidta odbiciami Householdera
tylko jak efektywnie mnożyć macierz przez macierze odbić Householdera ?

Można by też napisać klasę liczb wymiernych na bazie BigInteger z System.Numerics
a także zmodyfikować ten iloczyn skalarny i wtedy pozbyć się problemów z dokładnością
ODPOWIEDZ