forked from Alexey/DAS_2024_1
184 lines
5.8 KiB
C#
184 lines
5.8 KiB
C#
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 < 14; 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();
|
|
}
|
|
} |