{"id":51778136,"url":"https://github.com/sha0coder/eqhunt","last_synced_at":"2026-07-20T08:01:44.887Z","repository":{"id":358844833,"uuid":"1243381566","full_name":"sha0coder/eqhunt","owner":"sha0coder","description":"Genetic Algorithm to learn ecuations from data","archived":false,"fork":false,"pushed_at":"2026-05-19T09:42:36.000Z","size":15,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-19T11:33:24.799Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C++","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/sha0coder.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-19T09:38:19.000Z","updated_at":"2026-05-19T09:42:40.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/sha0coder/eqhunt","commit_stats":null,"previous_names":["sha0coder/eqhunt"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/sha0coder/eqhunt","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sha0coder%2Feqhunt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sha0coder%2Feqhunt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sha0coder%2Feqhunt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sha0coder%2Feqhunt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sha0coder","download_url":"https://codeload.github.com/sha0coder/eqhunt/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sha0coder%2Feqhunt/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35678471,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-07-20T02:08:10.276Z","status":"ssl_error","status_checked_at":"2026-07-20T02:08:09.736Z","response_time":111,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":[],"created_at":"2026-07-20T08:01:44.205Z","updated_at":"2026-07-20T08:01:44.881Z","avatar_url":"https://github.com/sha0coder.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# eqhunt\n\npip install eqhunt\n\nSymbolic regression by genetic programming. C++ engine, Python bindings via [nanobind](https://github.com/wjakob/nanobind).\n\nGive it a table of `(inputs, target)` pairs; it returns a human-readable formula\nthat approximates the relationship. No neural network, no black box — just an\nalgebraic expression you can read, paste into a calculator, or hand-tune.\n\n```python\nimport eqhunt\n\nX = [[1, 1], [2, 3], [4, 5], [7, 2], [9, 9]]\ny = [2, 5, 9, 9, 18]\n\nmodel = eqhunt.fit(X, y)\nprint(model.formula)        # e.g.  f(x,y) = (x+y)\nprint(model.error)          # e.g   0.0\nprint(model.predict([6, 7])) # -\u003e 13.0\n```\n\n## Install\n\n```bash\npip install eqhunt\n```\n\nPrebuilt wheels are published for Linux, macOS and Windows on common Python\nversions. If pip falls back to building from source you'll need a C++17 compiler.\n\n## Two ways to use it\n\n### Ultra-simple\n\n```python\nimport eqhunt\n\nmodel = eqhunt.fit(X, y, generations=5000)\nprint(model.formula)\nmodel.predict([1, 2])         # single row\nmodel.predict([[1, 2], [3, 4]])  # batch\n```\n\n`fit()` accepts any `Config` field as a keyword argument:\n\n```python\neqhunt.fit(X, y, pop=800, trig_penalty=2.0, bloat_penalty=0.3)\n```\n\n### Fully configurable\n\n```python\nimport eqhunt\n\ncfg = eqhunt.Config()\ncfg.pop               = 800\ncfg.gen               = 50000\ncfg.tournament_size   = 5\ncfg.initial_depth     = 5\ncfg.bloat_penalty     = 0.3\ncfg.trig_penalty      = 1.5\ncfg.accepted_error    = 0.01\n\n# Re-weight individual operators (higher = more likely to appear)\ncfg.op_weights.sin = 1.0      # boost sine\ncfg.op_weights.cos = 1.0\ncfg.op_weights.exp = 0.0      # disable exp entirely\ncfg.pi_prob = 0.10            # 'pi' more frequent in terminals\n\nmodel = eqhunt.Model(cfg).fit(X, y)\nprint(model.formula)\n```\n\nYou can also train from a CSV file (one row per sample, last column = target,\nlines starting with `#` are comments):\n\n```python\neqhunt.Model().fit_csv(\"nivel_embase.csv\")\n```\n\n## Operators available\n\n| Category   | Operators                        |\n|------------|----------------------------------|\n| Arithmetic | `+  -  *  /  -x`                 |\n| Powers     | `sqrt  **`                       |\n| Conditional| `if(cond, then, else)` (cond \u003e 0)|\n| Trig       | `sin  cos  tan`                  |\n| Exp / log  | `exp  log`                       |\n| Constants  | numeric literals, `pi`           |\n\nTrigonometric, log and exp nodes have **low default weights** so they only\nappear after enough mutation pressure — useful for cyclic / physical data,\nignored otherwise. Adjust via `Config.op_weights`.\n\n## How error and validity are handled\n\n* Per-sample error is `|prediction - target|`; total error is the sum.\n* Invalid evaluations (`/0`, `sqrt(\u003c0)`, `log(\u003c=0)`, `exp(huge)`) get a soft\n  per-sample penalty rather than killing the whole formula — a single\n  out-of-domain sample no longer disqualifies an otherwise good candidate.\n  If more than 25% of samples fail, the formula is rejected.\n\n## Stopping early\n\n`Config.accepted_error` stops the search as soon as total error drops below\nthe threshold. You can also call `model.stop()` from another thread (or a\nsignal handler) to ask the loop to wrap up after the current generation.\n\n## Saving and reloading a formula\n\nA trained model is just a string — you can persist it, ship it, paste it,\ndiff it. To reuse a formula in a new process without retraining, parse it\nback into a `Model`:\n\n```python\nimport eqhunt\n\n# train and save\nm = eqhunt.fit(X, y)\nprint(m.formula)          # e.g.  f(x,y) = ((x*x) - (y*y))\nm.save(\"model.txt\")       # one-liner persisted\n\n# later, in a fresh process — no training needed\nm2 = eqhunt.Model.load_file(\"model.txt\")\nm2.predict([6, 7])        # -13.0\nm2.predict([[1, 2], [3, 4]])\n```\n\nYou can also go through strings directly:\n\n```python\nformula_str = m.formula                   # or any equivalent expression\nm3 = eqhunt.Model.from_formula(formula_str)\nm3.predict([12, 5])\n```\n\nOr mutate an existing model in place:\n\n```python\nm.load_formula(\"(x*x + y*y)\")             # replaces the current tree\n```\n\nAccepted syntax: anything the engine itself emits via `get_formula()` —\narithmetic (`+ - * / **`), unary minus, `sqrt sin cos tan log exp if`,\nvariables `x y z w v u x6 x7 …`, numeric literals (int / float / `1e5`),\nand `pi`. Both the bare expression (`\"(x+y)\"`) and the full prefixed form\n(`\"f(x,y) = (x+y)\"`) are accepted; the parser strips everything up to and\nincluding the first `=`. Parse errors raise `RuntimeError`.\n\nThe number of input variables is inferred from the highest variable index\nin the formula, so `m2.num_vars` is set correctly without needing to know\nit in advance.\n\n## Config reference\n\n| Field                | Default | Meaning                                              |\n|----------------------|---------|------------------------------------------------------|\n| `pop`                | 400     | Population size                                      |\n| `gen`                | 15000   | Max generations                                      |\n| `tournament_size`    | 4       | Tournament selection pool                            |\n| `crossover_prob`     | 0.7     | Crossover probability per pair                       |\n| `mutation_prob`      | 0.25    | Mutation probability per offspring                   |\n| `initial_depth`      | 4       | Depth used to seed the initial population            |\n| `mutation_depth`     | 3       | Depth for mutation-generated subtrees                |\n| `const_min/max`      | -9, 9   | Range for random numeric terminals                   |\n| `pi_prob`            | 0.01    | Probability a terminal is `pi`                       |\n| `bloat_penalty`      | 0.1     | Per-node penalty (favours smaller trees)             |\n| `trig_penalty`       | 0.5     | Extra penalty per `sin/cos/tan/log/exp` node         |\n| `immigrant_rate`     | 0.05    | Fraction of population replaced by random each gen   |\n| `weak_parent_rate`   | 0.2     | Prob. 2nd parent is random (not tournament)          |\n| `accepted_error`     | 0.5     | Stop training once total error \u003c this value          |\n| `verbose`            | False*  | Print best-so-far per improvement                    |\n| `simplify`           | True    | Run algebraic simplification on the final tree       |\n| `simplify_interval`  | 500     | Periodically simplify top-N members during training  |\n| `simplify_top_n`     | 10      | How many to simplify periodically                    |\n\n*C++ default is `True`; the Python `fit()` helper defaults to `False`.\n\n## Building from source\n\n```bash\ngit clone https://github.com/sha0coder/eqhunt\ncd eqhunt\npip install -e .\npytest\n```\n\nRequires Python 3.8+, a C++17 compiler, CMake 3.15+.\n\n## License\n\nMIT.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsha0coder%2Feqhunt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsha0coder%2Feqhunt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsha0coder%2Feqhunt/lists"}