C# Generowanie ciągu macierzy podobnych do macierzy stowarzyszonej

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

C# Generowanie ciągu macierzy podobnych do macierzy stowarzyszonej

Post autor: Mariusz M »

Próbowałem napisać program do generowania macierzy na których można by było przećwiczyć znajdowanie wartości własnych lub wektorów własnych
Ze względów numerycznych ograniczyłem się do liczb całkowitych

Co program powinien robić

1. Wylosować n liczb całkowitych z wybranego przedziału
2. Wygenerować wielomiany symetryczne podstawowe na podstawie liczb wylosowanych w punkcie 1.
(Funkcja tworząca wielomianów symetrycznych podstawowych to \(\displaystyle{ \prod_{k=1}^{n}\left( 1+x_{k}t\right) }\))
Mając wielomiany symetrycznych podstawowe z wzorów Vieta możemy zapisać współczynniki wielomianu charakterystycznego
3. Zapisać macierz stowarzyszoną (tzw macierz Frobeniusa)
4. Zastosować ciąg operacji zachowujących podobieństwo macierzy

Kod: Zaznacz cały

using System;
using System.IO;
namespace NamespaceName
{
	public static class ExtensionClass
	{
		public static void PrintMatrix(this StreamWriter sw,int[,] A)
		{
			int m = A.GetLength(0);
			int n = A.GetLength(1);
			for(int i = 0; i < m;i++)
			{
				for(int j = 0; j < n;j++)
					sw.Write("{0} ",A[i,j]);
				sw.WriteLine();
			}
		}
	}
	public class ClassName
	{
		public static void PrintMatrix(int[,] A)
		{
			int m = A.GetLength(0);
			int n = A.GetLength(1);
			for(int i = 0; i < m;i++)
			{
				for(int j = 0; j < n;j++)
					Console.Write("{0} ",A[i,j]);
				Console.WriteLine();
			}
		}
		public static void Transpose(int[,] A)
		{
			int m = A.GetLength(0);
			int n = A.GetLength(1);
			int temp;
			if(n == m)
			{
				for(int i = 0;i < n;i++)
					for(int j = i + 1; j < n; j++)
					{
						temp = A[i,j];
						A[i,j] = A[j,i];
						A[j,i] = temp;
					}
			}
		}
		public static void ElemSymPolys(int[] x,int[] c)
		{
			int n = x.Length;
			int i,j;
			c[0] = 1;
			for(i = 1;i <= n;i++)
				c[i] = 0;
			for(i = 1;i <= n;i++)
				for(j = i;j>=1;j--)
					c[j] += c[j-1]*x[i-1];
			Array.Reverse(c);
				
		}
		public static void AddRows(int i,int j,int m,int[,] A)
		{
			int rowCount = A.GetLength(0);
			for(int k = 0;k < rowCount;k++)
				A[i,k] += m*A[j,k];
		}
		public static void AddCols(int i,int j,int m,int[,] A)
		{
			int colCount = A.GetLength(1);
			for(int k = 0;k < colCount;k++)
				A[k,i] += m*A[k,j];
		}
		public static void SwapRows(int i,int j,int[,] A)
		{
			int rowCount = A.GetLength(0);
			int temp;
			for(int k = 0;k < rowCount;k++)
			{
				temp = A[i,k];
				A[i,k] = A[j,k];
				A[j,k] = temp;
			}
		}
		public static void SwapCols(int i,int j,int[,] A)
		{
			int colCount = A.GetLength(1);
			int temp;
			for(int k = 0;k < colCount;k++)
			{
				temp = A[k,i];
				A[k,i] = A[k,j];
				A[k,j] = temp;
			}
		}
		public static void Main(string[] args)
		{
			char esc;
			int i,j,n,w,m;
			int d;
			int[,] A;
			int[] x;
			int[] c;
			Random r = new Random();
			string path = "wartosciwlasneprzyklady.txt";
			using(StreamWriter sw = new StreamWriter(path,true))
			{
			do
			{
				Console.WriteLine("Podaj stopien macierzy kwadratowej jaką chcesz wygenerowac");
				int.TryParse(Console.ReadLine(),out n);
				A = new int[n,n];
				x = new int[n];
				c = new int[n+1];
				for(int k = 0;k < n;k++)
					x[k] = -10+r.Next(21);
				ElemSymPolys(x,c);
				d = -1;	
				for(int k = 1;k <= n;k++)
				{
					A[k-1,n-1] = -d*c[k-1];
					d = -d;
				}
				for(i = 0;i < n;i++)
				   for(j = 0;j < n-1;j++)
				     A[i,j] = (j+1 == i ?1:0);
				do
				{
					Console.WriteLine("0. Wyjscie");
					Console.WriteLine("1. Transpozycja macierzy");
					Console.WriteLine("2. Zamiana wierszy i kolumn");
					Console.WriteLine("3. Dodawanie wierszy i kolumn");
					Console.WriteLine("4. Wyswietlenie macierzy");
					Console.WriteLine("5. Zapisanie macierzy do pliku");
					int.TryParse(Console.ReadLine(),out w);
					switch(w)
					{
						case 0:
						{
							break;
						}
						case 1:
						{
							Transpose(A);
							break;
						}
						case 2:
						{
							Console.WriteLine("Podaj numery wierszy i kolumn ktore chcesz zamienic");
							int.TryParse(Console.ReadLine(),out i);
							int.TryParse(Console.ReadLine(),out j);
							i--;j--;
							SwapRows(i,j,A);
							SwapCols(i,j,A);
							break;
						}
						case 3:
						{
							Console.WriteLine("Podaj numery wierszy i kolumn ktore chcesz dodac");
							int.TryParse(Console.ReadLine(),out i);
							int.TryParse(Console.ReadLine(),out j);
							Console.WriteLine("Podaj mnoznik");
							int.TryParse(Console.ReadLine(),out m);
							i--;j--;
							AddRows(i,j,-m,A);
							AddCols(j,i,m,A);
							break;
						}
						case 4:
						{
							PrintMatrix(A);
							break;
						}
						case 5:
						{
							sw.PrintMatrix(A);
							break;
						}
						default: 
						{
							Console.WriteLine("Brak operacji");
							break;
						}
					}
			}
			while(w != 0);	
				esc = (char)Console.ReadKey().Key;
			}
			while(esc != (char)ConsoleKey.Escape);
		}
		}
	}
}

Gdzieś chyba jednak popełniłem błąd , chyba przy zapisywaniu tej macierzy stowarzyszonej

Dodano po 3 godzinach 48 minutach 20 sekundach:
Chyba w pętli z linii 118,tam gdzie jest przypisywanie wartości do ostatniej kolumny , należy dać wsteczną iterację

Dodano po 16 godzinach 33 minutach 38 sekundach:
Zmieniłem

Kod: Zaznacz cały

d = -1;	
for(int k = 1;k <= n;k++)
na

Kod: Zaznacz cały

d = -1;	
for(int k = n;k >= 1;k--)
i chyba jest dobrze

Oczywiście można by wylosować kilka operacji zachowujących podobieństwo macierzy
i zmienić typ zmiennych tablicy przechowującej elementy macierzy na BigInteger aby uniknąć przekroczenia zakresu typu int
ODPOWIEDZ