public static Sign[,] GetCanonicalForm(Sign[,] matrix)
        {
            List<Sign> distinctSigns = new List<Sign>();
            foreach (Sign s in matrix)
                if (!distinctSigns.Contains(s))
                    distinctSigns.Add(s);

            //Get sorted array of distinct signs
            Sign[] distinctSignsArray = distinctSigns.ToArray();
            SortLexicoGraphic(distinctSignsArray);

            //Calculate frequency vectors
            int[][] frequencyVectors = new int[matrix.GetLength(0)][];
            for(int i = 0; i < matrix.GetLength(0); i++)
            {
                Sign[] currentRow = new Sign[matrix.GetLength(0)];
                for(int j = 0; j < currentRow.Length; j++)
                    currentRow[j] = matrix[i, j];
                frequencyVectors[i] = GetSignFrequencyVector(currentRow, distinctSignsArray);
            }

            string[] frequencyVectorStrings = new string[frequencyVectors.Length];
            string[] frequencyVectorBackup = new string[frequencyVectors.Length]; //for comparison
            for (int i = 0; i < frequencyVectors.Length; i++)
                frequencyVectorStrings[i] = GetFrequencyVectorString(frequencyVectors[i]);

            Sign[,] canonical = (Sign[,])matrix.Clone();
            SortLexicoGraphic(frequencyVectorStrings);
            for (int i = 0; i < frequencyVectorStrings.Length; i++ )
            {
                //column j=>i; row j=>i
                int j = frequencyVectorBackup.ToList().IndexOf(frequencyVectorStrings[i]);
                frequencyVectorBackup[j] = null;
                SwitchRows(ref canonical, j, i);
                SwitchColumns(ref canonical, j, i);
            }
            return canonical;
        }