DAS_2024_1/kuzarin_maxim_lab_6/DeterminantCalculation/Program.cs

184 lines
5.8 KiB
C#
Raw Normal View History

using System.Diagnostics;
internal class Program
{
private static string[] _resTableColumnsNames = new string[] { "m*m", "1 t", "2 t", "3 t", "4 t", "5 t", "6 t"};
private static void Main(string[] args)
{
Console.WriteLine(string.Join("\t", _resTableColumnsNames));
for (int i = 8; i < 13; i++)
{
var e = CreateMatrix(i, i);
List<long> times = new() { i };
for (int j = 1; j <= 6; j++)
{
var sw = new Stopwatch();
sw.Start();
CalculateDeterminant(e, j);
sw.Stop();
times.Add(sw.ElapsedMilliseconds);
}
Console.WriteLine(string.Join("\t", times));
}
}
private static int[,] CreateMatrix(int x, int y)
{
var rnd = new Random();
var res = new int[y, x];
for (int i = 0; i < y; i++)
{
for (int j = 0; j < x; j++)
{
res[i, j] = rnd.Next(0, 100);
}
}
return res;
}
private static void PritMatrix(int[,] mx)
{
for (int i = 0; i < mx.GetLength(0); i++)
{
for (int j = 0; j < mx.GetLength(1); j++)
{
Console.Write($"{mx[i, j].ToString("000")}\t");
}
Console.WriteLine();
}
}
public static long CalculateDeterminant(int[,] matrix, int maxThreads)
=> CalculateDeterminantParalel(
matrix,
Enumerable.Range(0, matrix.GetLength(0)).ToArray(),
Enumerable.Range(0, matrix.GetLength(1)).ToArray(),
maxThreads
);
private static long CalculateDeterminant(int[,] matrix, int[] rows, int[] columns)
{
if (rows.Length <= 3)
return GetSimpleDeterminant(matrix, rows.ToList(), columns.ToList());
(int fixIndex, bool isFixRow) = GetTheBestRowColumn(matrix, rows, columns);
long res = 0;
int row = isFixRow ? rows[fixIndex] : -1;
int column = isFixRow ? -1 : columns[fixIndex];
for (int index = 0; index < rows.Length; index++)
{
if (isFixRow)
column = columns[index];
else
row = rows[index];
res += ((index + fixIndex) % 2 != 0 ? -1 : 1) * matrix[column, row] *
CalculateDeterminant(matrix, rows.Where(x => x != row).ToArray(), columns.Where(x => x != column).ToArray());
}
return res;
}
private static long CalculateDeterminantParalel(int[,] matrix, int[] rows, int[] columns, int maxThread)
{
if (rows.Length <= 3)
return GetSimpleDeterminant(matrix, rows.ToList(), columns.ToList());
(int fixIndex, bool isFixRow) = GetTheBestRowColumn(matrix, rows, columns);
long res = 0;
int row = isFixRow ? rows[fixIndex] : -1;
int column = isFixRow ? -1 : columns[fixIndex];
var semaphore = new SemaphoreSlim(maxThread, maxThread);
for (int index = 0; index < rows.Length; index++)
{
if (isFixRow)
column = columns[index];
else
row = rows[index];
var c_column = column;
var c_row = row;
var c_index = fixIndex + index;
semaphore.Wait();
Task.Run(() =>
{
try
{
res += (c_index % 2 != 0 ? -1 : 1) * matrix[c_column, c_row] *
CalculateDeterminant(
matrix,
rows.Where(x => x != c_row).ToArray(),
columns.Where(x => x != c_column).ToArray()
);
}
finally { semaphore.Release(); }
});
}
semaphore.Wait(maxThread);
return res;
}
private static (int fixIndex, bool isFixRow) GetTheBestRowColumn(int[,] matrix, int[] rows, int[] columns)
{
Dictionary<int, int> zerosCount = rows.Select(x => x + 1).Union(columns.Select(x => -x - 1)).ToDictionary(x => x, x => 0);
foreach (var r in rows)
{
foreach (var c in columns)
{
if (matrix[r, c] == 0)
{
zerosCount[r + 1] += 1;
zerosCount[-c - 1] += 1;
}
}
}
var best = zerosCount.ToList().OrderByDescending(x => x.Value).FirstOrDefault().Key;
if (best > 0)
{
return (Array.IndexOf(rows, best - 1), true);
}
else
{
return (Array.IndexOf(columns, -best + 1), false);
}
}
private static long GetSimpleDeterminant(int[,] matrix, List<int> rows, List<int> columns)
{
if (rows.Count == 1)
{
return matrix[columns[0], rows[0]];
}
else if (rows.Count == 2)
{
return matrix[columns[0], rows[0]] * matrix[columns[1], rows[1]] - matrix[columns[0], rows[1]] * matrix[columns[1], rows[0]];
}
else if (columns.Count == 3)
{
return matrix[columns[0], rows[0]] * matrix[columns[1], rows[1]] * matrix[columns[2], rows[2]] +
matrix[columns[0], rows[1]] * matrix[columns[1], rows[2]] * matrix[columns[2], rows[0]] +
matrix[columns[0], rows[2]] * matrix[columns[1], rows[0]] * matrix[columns[2], rows[1]] -
matrix[columns[0], rows[2]] * matrix[columns[1], rows[1]] * matrix[columns[2], rows[0]] -
matrix[columns[1], rows[0]] * matrix[columns[0], rows[1]] * matrix[columns[2], rows[2]] -
matrix[columns[0], rows[0]] * matrix[columns[1], rows[2]] * matrix[columns[2], rows[1]];
}
throw new Exception();
}
}