{"id":17841327,"url":"https://github.com/shybovycha/gauss-elimination","last_synced_at":"2025-04-22T20:29:29.128Z","repository":{"id":25391302,"uuid":"28819888","full_name":"shybovycha/gauss-elimination","owner":"shybovycha","description":"Linear equation system solver in Haskell, implementing Gaussian elimination method","archived":false,"fork":false,"pushed_at":"2024-02-12T06:19:17.000Z","size":416,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-29T18:36:32.193Z","etag":null,"topics":["equation-solver","equation-systems","equations","gaussian-elimination-algorithm","haskell","matrix"],"latest_commit_sha":null,"homepage":"","language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/shybovycha.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-01-05T16:02:42.000Z","updated_at":"2024-06-01T23:40:42.000Z","dependencies_parsed_at":"2023-01-14T03:30:21.377Z","dependency_job_id":null,"html_url":"https://github.com/shybovycha/gauss-elimination","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shybovycha%2Fgauss-elimination","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shybovycha%2Fgauss-elimination/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shybovycha%2Fgauss-elimination/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shybovycha%2Fgauss-elimination/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shybovycha","download_url":"https://codeload.github.com/shybovycha/gauss-elimination/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250318314,"owners_count":21410913,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["equation-solver","equation-systems","equations","gaussian-elimination-algorithm","haskell","matrix"],"created_at":"2024-10-27T21:02:43.983Z","updated_at":"2025-04-22T20:29:29.111Z","avatar_url":"https://github.com/shybovycha.png","language":"Haskell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Matrix equation solver\n\n## Summary\n\nThis is an implementation of a rather simple linear equation system solver. It uses Gauss method to solve the equation systems. It is written in 2016 as a coursework for \"Functional Programming\" course in Jagiellonian University.\n\nProject does not have any third-party dependencies.\n\n## Build\n\nThe application uses Cabal build system.\nTo build it run\n\n    cabal build\n\n## Run\n\nRun application with\n\n    cabal run\n\n## Use\n\nThe application is a CLI tool, taking a number of lines as input. The end of input is marked by an empty line.\nEach line is expected to have the following format:\n\n    ((\u003cFraction\u003e ([*]?) \u003cVariable\u003e) (+|-) (\\1))+ = \u003cFraction\u003e\n\nWhere\n\n    \u003cFraction\u003e :: (-)?(\\d+)(\\/(\\d+))?\n    \u003cVariable\u003e :: [a-zA-Z0-9_]\n\nFor instance:\n\n    -3/4 x1 + 11/15x2 - 7*x_3 = 19\n\n## How it works\n\nFirst the input lines are parsed into a matrix form. Then the Gauss reduction method is applied to the matrix to obtain the solution.\n\n### Parsing\n\nThere are two parsers defined in the code - `LegacyEquationParser` and `EquationParser`. The one used is the latter, the former is left for history.\n\n#### Legacy parsing\n\nThe `LegacyEquationParser` module defines a state machine parser. It is not really a Haskell way of doing things, but it gets the job done.\n\nThe state transition diagram is the following:\n\n![state machine graph](https://github.com/shybovycha/gauss-elimination/raw/master/input_parser_grammar.png)\n\nEach line is represented as a tuple `(list of multipliers, list of variable names)`.\n\nThe next step is to iteratively reduce multipliers in each matrix row down to `0` (if there is more than one multiplier in a given row) or `1` (if there is just one multiplier left in a given row). Doing so transforms each equation into the `x_i = y_i` shape, giving the solution of a given equation system.\n\nLast stage is forming the output using the list of variable names and the reduced equations.\n\n#### Monadic parser\n\nThe parser used in the code as default is built from the ground up based on the lectures by [Dave Sands](https://www.youtube.com/watch?v=H7aYfGP76AI) from Chalmers University of Technology.\n\nIt defines the rules which can be combined together to form a grammar definition and a `parse` function which takes a `String` and a grammar as its inputs and eagerly executes all of the grammar rules,\nreturning the results of running the rules and the unparsed portion of a string.\n\nThe `Parser` is defined as a type\n\n    newtype Parser a = P (String -\u003e Maybe (a, String))\n\nIt simply wraps a rule (or a combination of rules, effectively an entire grammar),\nwhich in turn is just a function, taking a `String` and returning a `Maybe` of a parsing result and an unparsed remainder of an input string.\n\nThe `parse` function simply executes the wrapped parser function:\n\n    parse :: Parser a -\u003e String -\u003e Maybe (a, String)\n    parse (P fn) str = fn str\n\nThe module also defines a number of functions to combine parsers:\n\nA parser that always fails\n\n    failure :: Parser a\n    failure = P (\\_ -\u003e Nothing)\n\nA parser that always succeeds (with a set result)\n\n    success :: a -\u003e Parser a\n    success a = P (\\str -\u003e Just (a, str))\n\nA parser that requires one or more characters (any characters)\n\n    item :: Parser Char\n    item = P $ \\str -\u003e case str of\n        \"\" -\u003e Nothing\n        (ch:chs) -\u003e Just (ch, chs)\n\nA parser which takes a predicate (function from character to boolean)\nand succeeds only if that predicate satisfies the first character of a string\n\n    sat :: (Char -\u003e Bool) -\u003e Parser Char\n    sat pred = item \u003e\u003e= (\\str -\u003e if pred str then success str else failure)\n\nA parser which succeeds if it matches a string or not (optional parser)\n\n    zeroOrMore :: Parser a -\u003e Parser [a]\n    zeroOrMore p = oneOrMore p \u003c|\u003e success []\n\nA parser which requires at least one match\n\n    oneOrMore :: Parser a -\u003e Parser [a]\n    oneOrMore p = p \u003e\u003e= (\\a -\u003e fmap (a:) (zeroOrMore p))\n\nA parser which either matches exactly once or does not match at all\n\n    zeroOrOne :: Parser a -\u003e Parser (Maybe a)\n    zeroOrOne p = (p \u003e\u003e= (\\a -\u003e success (Just a))) \u003c|\u003e success Nothing\n\nA parser is a monad, so it defines the `bind` and `\u003e\u003e=` (which allows to chain parsers into \"this and then that\" manner):\n\n    instance Monad Parser where\n        p1 \u003e\u003e= p2 = P $ \\str -\u003e case parse p1 str of\n            Just (a, str') -\u003e parse (p2 a) str'\n            Nothing -\u003e Nothing\n\n        return = pure\n\nAn alternate helper (combining parsers in a \"if not this, try that\" manner)\n\n    instance Alternative Parser where\n        empty = failure\n\n        p1 \u003c|\u003e p2 = P $ \\str -\u003e case parse p1 str of\n            Nothing -\u003e parse p2 str\n            result -\u003e result\n\nAs an the example, the parser rule for an integer number is defined as following:\n\n    digit :: Parser Char\n    digit = sat isDigit\n\n    naturalNumber :: Parser Integer\n    naturalNumber = read \u003c$\u003e (oneOrMore digit)\n\n    negativeInteger :: Parser Integer\n    negativeInteger = do\n        (sat (== '-'))\n        n \u003c- naturalNumber\n        return (-1 * n)\n\n    integerNumber :: Parser Integer\n    integerNumber = naturalNumber \u003c|\u003e negativeInteger\n\nThe parsing is then performed by running the parser combination (e.g. `integerNumber`) with `parse` function:\n\n    parse integerNumber \"-42\"\n    -- Just (-42, \"\")\n\n### Non-solvable cases\n\nThe following systems of equations do not have solutions\n\n#### Example 1\n\n    x  + y  +  z = 5\n    x  + 2y -  z = 6\n    2x + 3y + 0z = 13\n\n#### Example 2\n\n    x + y = 10\n    x + y = 20\n\n#### Example 3\n\n    x + y + z = 10\n    x - y + z = 20\n    2x + 0y + 2z = 50\n\nThe program will handle the above cases by returning the `Inconsistent` result.\n\n### Infinite solutions cases\n\n#### Example 1\n\n    x  + y  +  z = 5\n    x  + 2y -  z = 6\n    2x + 3y + 0z = 11\n\nFor the above system, program will return the `Infinite [values]` result, where `[values]` is one of the possible solutions.\n\n### Simple cases\n\nIn all other cases program will return `Simple [values]` result, denoting the only solution to the system.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshybovycha%2Fgauss-elimination","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshybovycha%2Fgauss-elimination","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshybovycha%2Fgauss-elimination/lists"}