none
пожалуйста,помогите исправить код))) RRS feed

  • Вопрос

  • мне нужно,используя классы решить СЛАУ, я попытался что-то написать)) у меня ничего не  работает(( мне нужно составить класс Matrix,решить методом Гаусса,вывести в новый файл,заранее большое спасибо))

    using System;

    using System.Collections.Generic;

    using System.Linq;
    using System.Text;
    using System.Data;

    namespace WindowsFormsApplication1
    {

        class  Slau
        {   int m; // количество уравнений
            int n; // количество переменных
            Matrix a; // матрица коэффициентов
            Matrix b; // вектор правой части
            Matrix x; // вектор решений
            bool isSolved; // признак совместности
            int[] reoder; // перестановка переменных, 
            // полученная в методе Жордана-Гаусса
            int rang; // ранг матрицы коэффициентов

            // конструктор
            public Slau(int m1, int n1)
          {
              m = m1;  // инициализация количества уравнений
              n = n1;  // инициализация количества переменных
              // выделение памяти под матрицу коэффициентов
              a = new Matrix(m1, n1);
              // выделение памяти под вектор свободных членов
              b = new Matrix(1, m1);
              // выделение памяти под вектор-решение
              x = new Matrix(1, n1);
              // выделение памяти и заполнение массива 
              // для хранения перестановки переменных
              reoder = new int[n];
              for (int i = 0; i < n; i++)
                  reoder[i] = i;
          }
            // метод чтения системы уравнения из файла
            public void Input()
          {

              List<string> Lst = new List<string>();
              using (StreamReader sr = new StreamReader("input.txt"))
              {
                  string line;
                  while ((line = sr.ReadLine()) != null)
                  {
                      Lst.Add(line);
                  }
              }
          }
            // метод вывода в фаил решённую систему уравнения       
            public void Print()
          {


          }
             public void JordanGauss () // метод Жордана-Гаусса
          {  
                 // создание копий матрицы коэффициентов и свободных 
              // членов для последующих преобразований
             Matrix A = a.Copy();
             Matrix B = b.Copy();
             int count_null_cols = 0;
             // проведение исключений по формулам Жордана-Гаусса
             for(int i = 0; i < m; i++)
             {
             // исключение по i-ой строке
              // проверка возможности исключения 
             // по значению ведущего элемента
                if(A[i, i] != 0)
               {
                // исключение во всех строках, кроме ведущей
                  for(int k = 0; k < m; k++)
                 {
                    if(k == i) 
                       continue;
                    double d = A[k, i] / A[i, i];
                    for(int j = i; j < n; j++)
                       A[k, j] = A[k, j] - d * A[i, j];
                       B[0, k] = B[0, k] - d * B[0, i];
                 }
                 // преобразование ведущей строки
                 for(int j = i + 1; j < n; j++)
                    A[i, j] /= A[i, i];
                 // преобразование i-ого свободного члена
                B[0, i] /= A[i, i];
                A[i, i] = 1;
               }
               else
               {       
                // элемент главной диагонали 
               // в i-ой строке равен нулю
                  int k;
                  // поиск ненулевого элемента ниже
                 // в i-ом столбце
                  for(k = i + 1; k < m; k++)
                     if(A[k, i] != 0) 
                        break;
                  if(k == m)
                 {
                    // все элементы столбца нулевые
                    if(i == n - 1 - count_null_cols)
                   {
                    // элементов, которые могут быть
                   // ведущими, больше нет 
                      count_null_cols++;
                      break;
                   } 
                    // меняем местами столбцы - текущий и 
                    // последний из непросмотренных
                   for(int j = 0; j < m; j++)
                  {
                     double t = A[j, i]; 
                     A[j, i] = A[j, n-count_null_cols-1];
                     A[j, n-count_null_cols-1] = t; 
                  }
                   // отражаем смену столбцов в перестановке
                  int te = reoder[i]; 
                  reoder[i] = reoder[n-count_null_cols-1];
                  reoder[n-count_null_cols-1] = te;
                  count_null_cols++;
                  // далее пытаемся провести исключения 
                 // с той же строкой
                  i--;
               }
               else
               {
                  // нашли в столбце элемент, который может 
                  // быть ведущим - меняем местами строки
                  for(int l=0; l<n; l++)
                 {
                    double t = A[i, l]; 
                    A[i, l] = A[k, l]; 
                    A[k, l] = t;
                 }    
                  double p = B[0, i]; 
                  B[0, i] = B[0, k]; 
                  B[0, k] = p;
                  // далее пытаемся провести исключения 
                  // с той же строкой
                  i--;
               }
           }
        }
         // вычисление ранга матрицы после проведения исключения
        rang = m < n-count_null_cols ? m : n-count_null_cols;
         // подсчет количества нулевых строк матрицы
        int null_rows = m - rang;
        // проверка на несовместность системы –
        // если в нулевой строке 
        // свободный член не равен нулю
        for(int i = rang; i < m; i++)
          if(B[0, i] != 0)
          {
             isSolved = false;
             return;
          }
         // формирование общего решения для совместной СЛАУ
         // путем переноса свободных переменных в правую часть
        Matrix res = new Matrix(rang, 1 + n - rang);
        for(int i = 0; i < rang; i++)
        {
           res[i,0] = B[0, i];
           for(int j = rang; j < n; j++)
              res[i, j - rang + 1] = -A[i, j];
        }
        x = res;
        isSolved = true;
    }
       }

    }

                      
    • Изменен тип ЖукMVP, Moderator 7 апреля 2015 г. 15:47 вопрос он и есть вопрос
    18 ноября 2012 г. 11:42

Ответы

  • Вот метод Гаусса

    using System;
    using System.Collections.Generic;
    using System.Linq;
    
    namespace LabWork_1
    {
        public class GaussMethodSolver
        {
            private readonly double[][] _sourceA;
            private readonly double[] _sourceB;
            protected readonly double[][] MatrixA;
            private readonly double[] _vectorB;
            private double[] _vectorX;
    
            protected int RowCount { get; set; }
            protected int CellCount { get; set; }
    
            private int _decimals;
            private double _tolerance;
            public int Decimals
            {
                get { return _decimals; }
                set
                {
                    if(value < 0)
                    {
                        throw new ArgumentException("Decimal must be greather or equal to zero.", "value");
                    }
    
                    _decimals = value;
                    _tolerance = 1 / Math.Pow(10, _decimals);
                }
            }
    
            public IReadOnlyCollection<double> LastSolveResult
            {
                get { return _vectorX; }
            }
    
            public GaussMethodSolver(double[][] matrixA, double[] vectorB)
            {
                if(!IsSquareMatrix(matrixA))
                {
                    throw new ArgumentException("Matrix A has to be square.");
                }
                if(matrixA.Length != vectorB.Length)
                {
                    throw new ArgumentException("Rank matrix A must be equal to vector B length.");
                }
                _sourceA = matrixA;
                MatrixA = matrixA;
                _sourceB = vectorB;
                _vectorB = vectorB;
                Initialise();
            }
    
            private bool IsSquareMatrix(double[][] matrix)
            {
                if(matrix == null)
                {
                    throw new ArgumentNullException("matrix");
                }
    
                if(matrix.All(r => r.Length == matrix.Length))
                {
                    return true;
                }
    
                return false;
            }
    
            private void Initialise()
            {
                RowCount = MatrixA.Length;
                CellCount = MatrixA[0].Length;
                _vectorX = new double[CellCount];
                Decimals = 4;
            }
    
            protected struct PositionInMatrix
            {
                public int Cell { get; set; }
                public int Row { get; set; }
    
                public override string ToString()
                {
                    return string.Format("Row: {0}, Cell: {1}", Row, Cell);
                }
            }
            public bool TrySolve()
            {
                try
                {
                    Solve();
                }
                catch(InvalidOperationException)
                {
                    return false;
                }
    
                return true;
            }
            public void Solve()
            {
                ForwardStroke();
                RevereseStroke();
                _sourceA.CopyTo(MatrixA, 0);
                _sourceB.CopyTo(_vectorB, 0);
            }
    
    
            protected virtual void ForwardStroke()
            {
                int currentCell = 0;
    
                for(int i = 0; i < RowCount - 1; i++)
                {
                    if(IsElementEqualToZero(i, currentCell))
                    {
                        int rowToSwapNum = i;
                        while(IsElementEqualToZero(rowToSwapNum, currentCell) && rowToSwapNum < RowCount)
                        {
                            rowToSwapNum++;
                        }
    
                        if(rowToSwapNum == RowCount)
                        {
                            IfNoSolution();
                            throw new InvalidOperationException("No Solution");
                        }
    
                        SwapTwoRows(i, rowToSwapNum);
                    }
    
                    SubtractCurrentRowFromTheLower(i, currentCell);
    
                    currentCell++;
                }
            }
    
            protected bool IsElementEqualToZero(int row, int cell)
            {
                return Math.Abs(MatrixA[row][cell]) < _tolerance;
            }
    
            protected void IfNoSolution()
            {
                for(int i = 0; i < _vectorX.Length; i++)
                {
                    _vectorX[i] = double.NaN;
                }
            }
    
            protected void SwapTwoRows(int row1, int row2)
            {
                if(row1 == row2)
                {
                    return;
                }
    
                double[] bufferArray = MatrixA[row1];
                MatrixA[row1] = MatrixA[row2];
                MatrixA[row2] = bufferArray;
    
                double buffer = _vectorB[row1];
                _vectorB[row1] = _vectorB[row2];
                _vectorB[row2] = buffer;
            }
    
            protected void SubtractCurrentRowFromTheLower(int row, int cell)
            {
                for(int i = row + 1; i < RowCount; i++)
                {
                    var q = FindQForTwoRows(i, row, cell);
    
                    for(int j = cell; j < CellCount; j++)
                    {
                        MatrixA[i][j] = Math.Round(MatrixA[i][j] - Math.Round(MatrixA[row][j] * q, Decimals),
                            Decimals);
                    }
    
                    _vectorB[i] = Math.Round(_vectorB[i] - Math.Round(_vectorB[row] * q, Decimals), Decimals);
                }
            }
    
            private double FindQForTwoRows(int dividendRow, int row2, int cell)
            {
                double q = Math.Round(MatrixA[dividendRow][cell] / MatrixA[row2][cell], Decimals);
    
                return q;
            }
    
            private void RevereseStroke()
            {
                for(int i = RowCount - 1; i >= 0; i--)
                {
                    double temp = _vectorB[i];
    
                    int j = CellCount - 1;
                    for(; j > i; j--)
                    {
                        temp = Math.Round(temp - Math.Round(MatrixA[i][j] * _vectorX[j], Decimals), Decimals);
                    }
    
                    _vectorX[i] = Math.Round(temp / MatrixA[i][j], Decimals);
                }
            }
        }
    }
    

    А вот класс матрицы

    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Globalization;
    using System.IO;
    using System.Linq;
    using System.Text;
    
    namespace LabWork_1
    {
        public class SquareMatrix
        {
            private readonly double[][] _matrix;
    
            public int Rank { get; private set; }        
    
            public double this[int row, int cell]
            {
                get
                {
                    if (!IsInRange(row, cell))
                    {
                        throw new IndexOutOfRangeException();
                    }
    
                    return _matrix[row][cell];
                }
                set
                {
                    if(!IsInRange(row, cell))
                    {
                        throw new IndexOutOfRangeException();
                    }
    
                    _matrix[row][cell] = value;
                }
            }
    
            private bool IsInRange(int row, int cell)
            {
                return row >= 0 && row < Rank && cell >= 0 && cell < Rank;
            }
            public IReadOnlyCollection<IReadOnlyCollection<double>> Matrix
            {
                get
                {
                    return new ReadOnlyCollection<IReadOnlyCollection<double>>(_matrix);
                }
            }
            
            public SquareMatrix(double[][] matrix)
            {
                if (!IsSquareMatrix(matrix))
                {
                    throw new ArgumentException("Matrix has to be square.");
                }
                _matrix = matrix;
                Rank = _matrix.Length;
            }
    
            public SquareMatrix(int rank)
            {
                if (rank < 0)
                {
                    throw new ArgumentException("Rank must be greather than zero.");
                }
    
                _matrix = new double[rank][];
                for (int i = 0; i < rank; i++)
                {
                    _matrix[i] = new double[rank];
                }
    
                Rank = _matrix.Length;
            }
    
            private bool IsSquareMatrix(double[][] matrix)
            {
                if (matrix == null)
                {
                    throw new ArgumentNullException("matrix");
                }
    
                if (matrix.All(r => r.Length == matrix.Length))
                {
                    return true;
                }
    
                return false;
            }
    
            public static SquareMatrix ReadFromFile(string path)
            {
                try
                {
                    var lines = File.ReadLines(path).ToList();
                    double[][] matrix = new double[lines.Count()][];
                    int row = 0;
                    lines.ForEach(l =>
                    {
                        matrix[row] =
                            l.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries).Select(double.Parse).ToArray();
                        row++;
                    });
    
                    return new SquareMatrix(matrix);
                }
                catch (Exception e)
                {
                    throw new InvalidOperationException("There was a mistake. Look on iner exception.", e);
                }
            }
    
            public static bool IsJointMatrix(SquareMatrix a, SquareMatrix b)
            {
                return a.Rank == b.Rank;
            }
            public static SquareMatrix operator +(SquareMatrix a, SquareMatrix b)
            {
                if (!IsJointMatrix(a,b))
                {
                    throw new InvalidOperationException("Matrix are not joint");
                }
    
                var result = new SquareMatrix(a.Rank);
                for (int i = 0; i < a.Rank; i++)
                {
                    for (int j = 0; j < a.Rank; j++)
                    {
                        result[i, j] = a[i, j] + b[i, j];
                    }
                }
    
                return result;
            }
    
            public static SquareMatrix operator -(SquareMatrix a, SquareMatrix b)
            {
                return a + (b*(-1));
            }
    
            public static SquareMatrix operator *(SquareMatrix a, double b)
            {
                var result = new SquareMatrix(a.Rank);
                for(int i = 0; i < a.Rank; i++)
                {
                    for(int j = 0; j < a.Rank; j++)
                    {
                        result[i, j] = b * a[i, j];
                    }
                }
    
                return result;
            }
    
            public static SquareMatrix operator /(SquareMatrix a, double b)
            {
                return a*(1/b);
            }
    
            public void PrintMatrix()
            {
                var lines = new List<StringBuilder>(Rank);
                for (int i = 0; i < Rank; i++)
                {
                    lines.Add(new StringBuilder());
                }
    
                for (int i = 0; i < Rank; i++)
                {
                    var currentCell = _matrix.Select(l => l.Where((item, pos) => pos == i).FirstOrDefault()).Select(item => item.ToString(CultureInfo.InvariantCulture)).ToList();
                    var maxLength = currentCell.Max(item => item.Length);
    
                    var alignedItems = currentCell.Select(item => item + new string(' ', maxLength - item.Length) + "    ").ToList();
    
                    for (int j = 0; j < Rank; j++)
                    {
                        lines[j].Append(alignedItems[j]);
                    }
                }
                
    
                lines.ForEach(Console.WriteLine);
            }
    
            public double[][] ToRaggedArray()
            {
                var result = new double[Rank][];
                for (int i = 0; i < Rank; i++)
                {
                    result[i] = new double[Rank];
                    _matrix[i].CopyTo(result[i], 0);
                }
    
                return result;
            }
        }
    }

    Попробуйте использовать нагет-пакет 

    Math.NET Numerics

     

    3.6.0 - отличные реализации матриц и векторов.

    Надеюсь помог.

    • Помечено в качестве ответа ЖукMVP, Moderator 21 апреля 2015 г. 4:27
    6 апреля 2015 г. 7:55