Skip to content
Snippets Groups Projects
Select Git revision
  • main
1 result

.DS_Store

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    MatrixMarketReader.cs 5.54 KiB
    using Antlr4.Runtime;
    using SparseTransform.DataStructures;
    using SparseTransform.Convert;
    
    namespace SparseTransform.Convert
    {
        /// <summary>
        /// Provides an IReader implementation to read a MatrixMarket string.
        /// </summary>
        public class MatrixMarketReader : IReader
        {
            public IGraph ReadGraph(String matrix)
            {
                String[] lines = matrix.Split(
                new String[] { "\r\n", "\r", "\n" },
                StringSplitOptions.None
                );
    
                checkComments(lines);
    
                if (checkHeader(lines[0]))
                {
                    BipartiteGraph graph = new BipartiteGraph();
                    ReadContent(lines, (i, j, value) => {
                        graph.AddEdge(i, j);
                    });
                    return graph;
                }
                else
                {
                    AdjacencyGraph graph = new AdjacencyGraph();
                    ReadContent(lines, (i, j, value) => {
                        graph.AddEdge(i, j);
                    });
                    return graph;
                }
            }
    
            public DoubleMatrix ReadMatrix(String matrix)
            {
                String[] lines = matrix.Split(
                new String[] { "\r\n", "\r", "\n" },
                StringSplitOptions.None
                );
    
                checkComments(lines);
    
                String dimLine = lines[getFirstDataLine(lines)];
                String[] dimensions = dimLine.Split(" ");
                DoubleMatrix mat = new DoubleMatrix(Int32.Parse(dimensions[0]), Int32.Parse(dimensions[1]));
                ReadContent(lines, (i, j, value) =>
                {
                    mat[i - 1, j - 1] = value;
                });
                return mat;
            }
    
            /// <summary>
            /// checks with ANTLR4.0 whether the header is a valid instance. The header grammar can be found in the file MMFHeader.g4 
            /// </summary>
            /// <param name="header">header of the MMF-input</param>
            /// <returns>true if matrix is not symmetric</returns>
            private bool checkHeader(String header)
            {
                AntlrInputStream stream = new AntlrInputStream(header);
                MMFHeaderLexer lexer = new MMFHeaderLexer(stream);
                CommonTokenStream commonTokenStream = new CommonTokenStream(lexer);
                MMFHeaderParser speakParser = new MMFHeaderParser(commonTokenStream);
                EListener errorHandler = new EListener();
                speakParser.AddErrorListener(errorHandler);
                VisitorHeader visitor = new VisitorHeader();
                return visitor.Visit(speakParser.header());
            }
    
           /// <summary>
           /// checks whether the comment-section is valid.
           /// </summary>
           /// <param name="lines">entire input split by newlines</param>
           /// <exception cref="FormatException"></exception>
            private void checkComments(String[] lines)
            {
                bool leftComments = false;
                foreach (String line in lines)
                {
                    if (line != "")
                    {
                        if (leftComments && line.StartsWith('%'))
                        {
                            throw new FormatException("Syntax Error in MatrixMarket file: Encountered more comments in between data lines.");
                        }
                        else
                        {
                            if (!line.StartsWith('%'))
                            {
                                leftComments = true;
                            }
                        }
                    }
                    else
                    {
                        leftComments = true;
                    }
                }
            }
    
            /// <summary>
            /// creates a graph from the data-section of the MMF-input and meanwhile checks whether the data-section is valid
            /// </summary>
            /// <param name="matrix"></param>
            /// <param name="graph"></param>
            /// <returns></returns>
            /// <exception cref="Exception"></exception>
            public void ReadContent(String[] matrix, Action<int, int, double> processor)
            {
                String[] values;
                int lineCount = getFirstDataLine(matrix);
                matrix[lineCount] = "% " + matrix[lineCount];
                foreach (String line in matrix)
                {
                    if (line != "")
                    {
                        if (!line.StartsWith('%'))
                        {
    
                            values = line.Split(" ");
                            if (values.Length != 3)
                            {
                                throw new ArgumentException("Syntax Error in MatrixMarket file: Data line did not contain three elements.");
                            }
                            int i = Int32.Parse(values[0]);
                            int j = Int32.Parse(values[1]);
                            processor(i, j, Double.Parse(values[2]));
                        }
                    }
                }
            }
    
            /// <summary>
            /// computes the first data-line in the MMF-input 
            /// </summary>
            /// <param name="lines"></param>
            /// <returns></returns>
            private int getFirstDataLine(String[] lines)
            {
                int firstDataLine = 0;
                foreach (String line in lines)
                {
                    if (line != "")
                    {
                        if (line[0] != '%')
                        {
                            break;
                        }
                        else
                        {
                            firstDataLine++;
                        }
                    }
                    else
                    {
                        firstDataLine++;
                    }
                }
                return firstDataLine;
            }
        }
    }