{"id":19437881,"url":"https://github.com/wenkokke/amethyst","last_synced_at":"2026-02-04T15:06:59.269Z","repository":{"id":56491951,"uuid":"290187301","full_name":"wenkokke/amethyst","owner":"wenkokke","description":"Agda library for verifying neural networks.","archived":false,"fork":false,"pushed_at":"2020-11-26T10:35:08.000Z","size":4845,"stargazers_count":7,"open_issues_count":1,"forks_count":0,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-02-25T07:15:47.576Z","etag":null,"topics":["agda","neural-networks","smt-solver"],"latest_commit_sha":null,"homepage":"https://wenkokke.github.io/amethyst/","language":"Agda","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wenkokke.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}},"created_at":"2020-08-25T10:42:19.000Z","updated_at":"2023-02-07T21:03:50.000Z","dependencies_parsed_at":"2022-08-15T19:50:14.040Z","dependency_job_id":null,"html_url":"https://github.com/wenkokke/amethyst","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/wenkokke/amethyst","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wenkokke%2Famethyst","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wenkokke%2Famethyst/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wenkokke%2Famethyst/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wenkokke%2Famethyst/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wenkokke","download_url":"https://codeload.github.com/wenkokke/amethyst/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wenkokke%2Famethyst/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262166322,"owners_count":23269024,"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":["agda","neural-networks","smt-solver"],"created_at":"2024-11-10T15:16:10.487Z","updated_at":"2026-02-04T15:06:59.217Z","avatar_url":"https://github.com/wenkokke.png","language":"Agda","funding_links":[],"categories":[],"sub_categories":[],"readme":"Amethyst: Neural Network Verification in Agda\n---------------------------------------------------------------------------------\n\n[![Build Status](https://travis-ci.org/wenkokke/amethyst.svg?branch=master)](https://travis-ci.org/wenkokke/amethyst)\n[![Agda][agda-version]][agda]\n[![agda-stdlib][agda-stdlib-version]][agda-stdlib]\n[![agdarsec][agdarsec-version]][agdarsec]\n[![schmitty][schmitty-version]][schmitty]\n\nWhat is Amethyst?\n=================================================================================\n\nAmethyst is a library for lightweight neural network verification in Agda, using\nvarious solvers as backends. \nLet’s look at an example—seen [here][AND-Gate-2-Sigmoid-1] in glorious,\nclickable HTML. Our example is a neural network which emulates the logical\nAND-gate. We define our model as follows:\n\n```agda\nlayer0 : Layer Float 2 1\nlayer0 = record\n  { weights    = [ 5.0e1 ] ∷ [ 5.0e1 ] ∷ []\n  ; biases     = [ -7.5e1 ]\n  ; activation = sigmoid\n  }\n\nmodel : Network Float 2 1 1\nmodel = layer0 ∷ []\n```\n\nWe can then check properties of the model by specifying constraints that Amethyst\nthen automatically converts into SMT assertions. Let’s write\nsome constraints which check if our model correctly implements the AND gate:\n\n```agda\nexactConstraints : NetworkConstraints 2 1\nexactConstraints (i₀ ∷ i₁ ∷ []) (o₀ ∷ []) =\n  (i₀ == 0·0f ∧ i₁ == 0·0f ⇒ o₀ == 0·0f) ∷\n  (i₀ == 0·0f ∧ i₁ == 1·0f ⇒ o₀ == 0·0f) ∷\n  (i₀ == 1·0f ∧ i₁ == 0·0f ⇒ o₀ == 0·0f) ∷\n  (i₀ == 1·0f ∧ i₁ == 1·0f ⇒ o₀ == 1·0f) ∷\n  []\n```\n\nWe then combine the model and the constraints to generate a script for Z3. \nNote that in order to verify that the constraints hold for the model, \nwe need to negate the constraints and then check that the corresponding problem is unsatisfiable, \ni.e. that there exists no assignment to the inputs and outputs that violate the constraints. \n\nThe `query` function automatically handles the negation and the script generation for us. \nTherefore all that's left for us to do is to feed it into `z3` and check that the answer is `unsat`:\n\n```agda\n_ : z3 (query model exactConstraints) ≡ unsat ∷ []\n_ = refl\n```\n\nWoo! Turns out our network is correct! Of course, we could’ve checked this by\njust running the network in Agda:\n\n```agda\n_ : evalNetwork model (0.0 ∷ 0.0 ∷ []) ≡ (0.0 ∷ [])\n_ = refl\n_ : evalNetwork model (0.0 ∷ 1.0 ∷ []) ≡ (0.0 ∷ [])\n_ = refl\n_ : evalNetwork model (1.0 ∷ 0.0 ∷ []) ≡ (0.0 ∷ [])\n_ = refl\n_ : evalNetwork model (1.0 ∷ 1.0 ∷ []) ≡ (1.0 ∷ [])\n_ = refl\n```\n\nYeah, that was easier… However, the SMT solver also allows us to run universally\nand existentially quantified expressions. For example we might want to the network\nmodels the AND gate correctly for any values sufficiently close to 0.0 and 1.0.\nThis can be done by defining some new predicates `truthy` and `falsey`:\n\n```agda\nε : ∀ {Γ} → Term Γ REAL\nε = toReal 0.2\n\ntruthy : ∀ {Γ} → Term Γ REAL → Term Γ BOOL\ntruthy x = ∣ 1·0f - x ∣ ≤ ε\n\nfalsey : ∀ {Γ} → Term Γ REAL → Term Γ BOOL\nfalsey x = ∣ 0·0f - x ∣ ≤ ε\n```\n\nWe can then rewrite our constraints to use these fuzzy values:\n\n```agda\nfuzzyConstraints : NetworkConstraints 2 1\nfuzzyConstraints (i₀ ∷ i₁ ∷ []) (o₀ ∷ []) =\n  (falsey i₀ ∧ falsey i₁ ⇒ falsey o₀) ∷\n  (falsey i₀ ∧ truthy i₁ ⇒ falsey o₀) ∷\n  (truthy i₀ ∧ falsey i₁ ⇒ falsey o₀) ∷\n  (truthy i₀ ∧ truthy i₁ ⇒ truthy o₀) ∷\n  []\n```\n\nand then rerun the query:\n\n```agda\n_ : z3 (query model fuzzyConstraints) ≡ unsat ∷ []\n_ = refl\n```\n\nWhoa, that’s very cool! Now we know our network is robust around both truthy and\nfalsey inputs!\n\nGetting Started\n=================================================================================\n\nAmethyst requires Agda and several Agda libraries to work:\n\n- agda ([master][agda])\n- agda-stdlib ([experimental][agda-stdlib])\n- agdarsec ([master][agdarsec)\n- schmitty ([latest][schmitty])\n\nFurthermore, Amethyst requires you to install any external solver you’d like to\nuse, e.g., [Z3][Z3], [CVC4][CVC4], [Marabou][Marabou], etc…\n\nFinally, you’ll have to setup the libraries you want to use in `.agda/libraries`,\nand the external solvers in `.agda/executables`:\n```sh\n# .agda/libraries:\n/path/to/standard-library.agda-lib\n/path/to/agdarsec/agdarsec.agda-lib\n/path/to/schmitty/schmitty.agda-lib\n```\n```sh\n# .agda/executables:\n/path/to/z3\n/path/to/cvc4\n/path/to/marabou\n```\n\nWe realise this is quite a lot! Unfortunately, Amethyst required the revision of the floating-point primitives in Agda, which explains why it requires patches to its dependencies. The dependencies will stabilise a bit with the release of Agda v2.6.2. To make matters easier, for now, we provide a [Dockerfile](Dockerfile)!\n\nRelated Work\n=================================================================================\n\nAmethyst follows the same principles as [Lazuli][Lazuli] for Liquid Haskell,\n[Sapphire][Sapphire] for Python with Z3, and [StarChild][StarChild] for F*. \n\nUnlike Lazuli and StarChild, the integration between Amethyst and various\nsolvers is written in pure Agda, and is highly customisable. Consequently,\nAmethyst is able to generate far more concise SMT queries, tailored to the\nneural network domain. Furthermore, it offers integration with other solvers,\nspecific to the neural network domain, such as [Marabou][Marabou] (pending).\n\nUnlike Sapphire, Amethyst is implemented in a dependently-typed language, and is\nable to offer a far more seamless integration than would be possible in Python\nusing the Z3 API.\n\n[Lazuli]: https://github.com/wenkokke/lazuli\n[Marabou]: https://github.com/NeuralNetworkVerification/Marabou\n[Sapphire]: https://github.com/wenkokke/sapphire\n[StarChild]: https://github.com/wenkokke/starchild\n[AND-Gate-2-Sigmoid-1]: https://wenkokke.github.io/amethyst/AND-Gate-2-Sigmoid-1.html\n[agda]: https://github.com/agda/agda/\n[agda-version]: https://img.shields.io/badge/Agda-PR%20%234885-blue\n[agda-stdlib]: https://github.com/agda/agda-stdlib/tree/experimental\n[agda-stdlib-version]: https://img.shields.io/badge/agdastdlib-experimental-blue\n[agdarsec]: https://github.com/gallais/agdarsec\n[agdarsec-version]: https://img.shields.io/badge/agdarsec-master-blue\n[schmitty]: https://github.com/wenkokke/schmitty\n[schmitty-version]: https://img.shields.io/badge/schmitty-latest-blue\n[Z3]: https://github.com/Z3Prover/z3\n[CVC4]: https://github.com/CVC4/CVC4\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwenkokke%2Famethyst","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwenkokke%2Famethyst","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwenkokke%2Famethyst/lists"}