{"id":50803792,"url":"https://github.com/robotane/rati","last_synced_at":"2026-06-12T23:04:00.164Z","repository":{"id":364009830,"uuid":"1264111027","full_name":"robotane/rati","owner":"robotane","description":"Ranking-based termination inference for integer transition systems in the KoAT/KITTeL format.","archived":false,"fork":false,"pushed_at":"2026-06-11T08:09:42.000Z","size":598,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-11T10:09:17.074Z","etag":null,"topics":["formal-methods","integer-transition-systems","koat","program-analysis","ranking-functions","static-analysis","termination"],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/robotane.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"NOTICE","maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-09T15:12:06.000Z","updated_at":"2026-06-11T08:12:57.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/robotane/rati","commit_stats":null,"previous_names":["robotane/rati"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/robotane/rati","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robotane%2Frati","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robotane%2Frati/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robotane%2Frati/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robotane%2Frati/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/robotane","download_url":"https://codeload.github.com/robotane/rati/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robotane%2Frati/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34265499,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-12T02:00:06.859Z","response_time":109,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["formal-methods","integer-transition-systems","koat","program-analysis","ranking-functions","static-analysis","termination"],"created_at":"2026-06-12T23:03:58.083Z","updated_at":"2026-06-12T23:04:00.158Z","avatar_url":"https://github.com/robotane.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# RaTI\n\n**RaTI** (Ranking-based Termination Inference) is a **termination and\nnon-termination prover for integer transition systems (ITS)**: it reads a system\nin the [KoAT](https://github.com/aprove-developers/KoAT2-Releases) / KITTeL text\nformat and answers `TERMINATES` (with a ranking-function certificate),\n`NONTERMINATES` (with a recurrent-set witness) or `UNKNOWN`.\n\nThe engine is language-agnostic — it only consumes an ITS, so any front-end that\ncan emit KoAT (bytecode, EVM/Wasm, hand-written models) can be proved terminating\nwith it.\n\n## What it does\n\nGiven an ITS — locations with integer variables, and guarded transitions\n`src(x⃗) -\u003e tgt(e⃗) :|: guard` — `RaTI` proves every reachable loop (SCC)\nwell-founded by searching, in order:\n\n1. **Lexicographic linear ranking** (Alias–Darte–Feautrier–Gonnord, SAS 2010):\n   Farkas-encoded bounded/decrease implications, maximal-strict peeling, in exact\n   rational arithmetic.\n2. **Polyhedral invariants** (Apron, widening + narrowing) injected as extra\n   premises — the boundedness facts per-transition guards lack.\n3. **Cut-point loop summarisation** (exact relational composition) for\n   diamonds / nested loops.\n4. **Multiphase ranking** (MΦRF, Ben-Amram–Genaim, CAV 2017).\n5. **Disjunctive termination** (transition invariants, Podelski–Rybalchenko,\n   LICS 2004) as a last resort.\n\nAn SCC no ranking technique covers is then attacked from the other side —\n**non-termination by recurrent sets** (Gupta et al., POPL 2008):\n\n6. the SCC's simple cycles are **determinised** (update variables solved exactly\n   from the guard equalities; leftover nondeterminism fixed — a sound\n   under-approximation) and composed into explicit self-loops;\n7. a candidate set `G` — the loop guard (Frohn–Giesl, FMCAD 2019), strengthened\n   by the bounded descending iteration `G ← G ∧ G∘s` (closed recurrence,\n   Chen et al., TACAS 2014) and/or the polyhedral invariant — is checked\n   **inductive by Farkas' lemma in exact rational arithmetic**;\n8. a **concrete integer entry state** reaching `G` is synthesised (LP + rounding)\n   and **re-verified by `BigInteger` substitution**: only then is `NONTERMINATES`\n   answered, with the recurrent set, the cycle, the path and the witness state.\n\nA found ranking is a sound proof, a verified recurrent set a sound disproof; an\nundecided loop yields `UNKNOWN` (never a false verdict either way). Strict guards\nare tightened to their exact integer form (`e \u003e 0 ⇒ e − 1 ≥ 0`) on the\nnon-termination side — never relaxed. Note that `NONTERMINATES` is a statement\nabout the ITS *as given*: a front-end whose ITS over-approximates a program may\npropagate `TERMINATES` to that program, but never `NONTERMINATES`.\n\n## Build\n\nApron (the polyhedra library, JNI) is not on Maven Central, so its jars ship in\n`lib-repo/` (a project-local Maven repository) and its native libraries in `lib/`\n— `mvn package` works out of the box, no setup step:\n\n```bash\nmvn package                # runs tests, builds target/rati.jar\n```\n\nRequirements: JDK 8+ and Maven. The native libs in `lib/` are Linux x86-64\n(`libjapron.so`, `libjgmp.so`); on another platform, drop in matching Apron/GMP\nnative builds.\n\n## Usage\n\n```bash\n# Apron is JNI → point java.library.path at the native libs in lib/\nLD_LIBRARY_PATH=lib java -Djava.library.path=lib -jar target/rati.jar \u003cfile.koat\u003e [--entry F] [--quiet]\n```\n\n- `--entry \u003cfunctor\u003e` — start location (default: the `(STARTTERM …)` in the file);\n- `--quiet` — print only the verdict (no certificate);\n- exit code `0` = TERMINATES, `1` = UNKNOWN, `2` = usage / I/O error,\n  `3` = NONTERMINATES.\n\nA handy alias:\n\n```bash\nalias rati='LD_LIBRARY_PATH=lib java -Djava.library.path=lib -jar target/rati.jar'\nrati examples/nested_loops.koat\n```\n\n### Example\n\n```\n$ rati examples/nested_loops.koat\nTERMINATES\ncertificate:\n  SCC [b_nested_2, b_nested_3, b_nested_4, b_nested_5, b_nested_6]: lexicographic linear (ADFG, loop summary)\n    lexicographic component 1:\n      rho(b_nested_5) = 2*LI0 - 2*LI2 - 2\n      rho(b_nested_6) = 2*LI0 - 2*LI2 - 3\n    lexicographic component 2:\n      rho(b_nested_5) = LI1 - LI3 - 1\n      rho(b_nested_6) = 0\n```\n\nThe certificate lists, per loop SCC, the technique used and — for the\nlexicographic-linear path — the synthesised ranking function ρ at each location,\none component per peeling round (here a 2-component lexicographic order: the outer\ncounter, then the inner).\n\nA non-termination certificate is a replayable witness:\n\n```\n$ rati examples/nonterminating.koat\nNONTERMINATES\ncertificate (non-termination):\n  location: b_main_count_sub_neg_2\n  recurrent set: { LI0 \u003e= 0, LI3 - 1 \u003e= 0 }\n  cycle: b_main_count_sub_neg_2 -\u003e b_main_count_sub_neg_3 -\u003e b_main_count_sub_neg_2\n  determinised step: LI0' = LI0, LI1' = LI1, LI2' = LI2 + LI3, LI3' = LI3 + 1, LI4' = 0, LI5' = 0, SI0' = 0, SI1' = 0\n  path: koat_init -\u003e b_main_count_sub_neg_1 -\u003e b_main_count_sub_neg_2\n  entry state: LI0 = 0, LI1 = 0, LI2 = 0, LI3 = 0, LI4 = 0, LI5 = 0, SI0 = 0, SI1 = 0\n  state entering the loop: LI0 = 0, LI1 = -1, LI2 = 0, LI3 = 10, LI4 = 0, LI5 = 0, SI0 = 0, SI1 = 0\n```\n\n— from the entry state, the path reaches the loop head inside the recurrent set,\nwhich one cycle iteration provably never leaves.\n\n`examples/` holds a few ready inputs (`nested_loops`, `upcounter_bounded`\nterminating; `nonterminating` disproved).\n\n## Input format\n\nThe KoAT / KITTeL ITS format (the one `KoatPrinter` emits and that KoAT /\niRankFinder read):\n\n```\n(GOAL COMPLEXITY)\n(STARTTERM (FUNCTIONSYMBOLS koat_init))\n(VAR LI0 LI1 SI0)\n(RULES\n  koat_init(LI0, LI1, SI0) -\u003e b_loop(LI0, LI1, SI0)\n  b_loop(LI0, LI1, SI0) -\u003e b_loop(LI0 - 1, LI1, SI0) :|: LI0 - 1 \u003e= 0\n)\n```\n\nThe `(VAR …)` names are every location's formal arguments; a rule's right-hand\narguments are the update expressions and the `:|:` part the guard\n(`lhs OP 0`, `OP ∈ {=, \u003e=, \u003e}`). Update variables not in `(VAR …)` are\nnondeterministic — the relational step a path-length / abstract-domain relation\nneeds.\n\n## Library use\n\n```java\nIntegerTransitionSystem its = KoatParser.parse(text).its;\nFarkasRanking.Certificate c = FarkasRanking.proveWithCertificate(its, \"koat_init\");\n// c.verdict ∈ {TERMINATES, NONTERMINATES, UNKNOWN};\n// c.sccs = per-SCC ranking certificate; c.nonTermination = recurrent-set witness\n```\n\n## Layout\n\n```\nsrc/main/java/fr/univreunion/rati/\n  its/        ITS data model (IntegerTransitionSystem, ItsLocation, ItsTransition,\n              ItsLinearConstraint, ItsLinearExpression, KoatPrinter)\n  ranking/    the prover: FarkasRanking, LinearProgram, Rational, ItsInvariants,\n              LoopSummary, MultiphaseRanking, DisjunctiveTermination, NonTermination\n  rank/       CLI: KoatParser, RankMain\nlib/          Apron/GMP native libraries (JNI)\nlib-repo/     Apron/GMP jars as a project-local Maven repository\nexamples/     sample .koat inputs\n```\n\n`DecouplingArchitectureTest` enforces that the engine never depends on any\nbytecode-analysis code, keeping it front-end-agnostic.\n\n## References\n\n- Alias, Darte, Feautrier, Gonnord — *Multi-dimensional Rankings, Program\n  Termination, and Complexity Bounds of Flowchart Programs*, SAS 2010.\n- Ben-Amram, Genaim — *Multiphase-Linear Ranking Functions and their Relation to\n  Recurrent Sets*, CAV 2017.\n- Podelski, Rybalchenko — *Transition Invariants*, LICS 2004.\n- Gupta, Henzinger, Majumdar, Rybalchenko, Xu — *Proving Non-Termination*,\n  POPL 2008.\n- Chen, Cook, Fuhs, Nimkar, O'Hearn — *Proving Nontermination via Safety*,\n  TACAS 2014.\n- Frohn, Giesl — *Proving Non-Termination via Loop Acceleration*, FMCAD 2019.\n- Apron — \u003chttps://antoinemine.github.io/Apron/doc/\u003e (LGPL).\n\n## Licence\n\nRaTI's own source is under the Apache License 2.0 (see `LICENSE` / `NOTICE`).\nApron / GMP (bundled native libs and jars) are LGPL — see their upstream licences.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobotane%2Frati","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frobotane%2Frati","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobotane%2Frati/lists"}