{"id":30117198,"url":"https://github.com/pabrod/dualdiff","last_synced_at":"2026-06-13T16:32:51.107Z","repository":{"id":206473807,"uuid":"674138042","full_name":"PabRod/dualdiff","owner":"PabRod","description":"Dual numbers for automatic differentiation","archived":false,"fork":false,"pushed_at":"2023-08-03T08:51:34.000Z","size":21,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-04-25T05:04:30.074Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","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/PabRod.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}},"created_at":"2023-08-03T08:21:33.000Z","updated_at":"2023-12-01T10:36:22.000Z","dependencies_parsed_at":"2023-11-10T14:10:59.328Z","dependency_job_id":"62883f9f-1f83-4f4e-a577-7fa24ef36511","html_url":"https://github.com/PabRod/dualdiff","commit_stats":null,"previous_names":["pabrod/dualdiff"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/PabRod/dualdiff","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PabRod%2Fdualdiff","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PabRod%2Fdualdiff/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PabRod%2Fdualdiff/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PabRod%2Fdualdiff/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PabRod","download_url":"https://codeload.github.com/PabRod/dualdiff/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PabRod%2Fdualdiff/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":269712747,"owners_count":24463210,"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","status":"online","status_checked_at":"2025-08-10T02:00:08.965Z","response_time":71,"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":[],"created_at":"2025-08-10T10:38:19.697Z","updated_at":"2025-10-30T13:36:43.738Z","avatar_url":"https://github.com/PabRod.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Dualdiff\n\n(Forward) automatic differentiation from scratch\n\n## Description\n\nThe purpose of this project is learning about automatic differentiation.\nThere are many Python libraries about this topic which certainly are more efficient and professional than this one.\nNevertheless, I wanted to implement it from scratch in order to get a deep understanding of it.\nAnd boy! The mathematics behind it are beautiful!\n\n## Dual numbers\n\nForward automatic differentiation is made possible by [dual numbers](https://en.wikipedia.org/wiki/Dual_number).\nDual numbers are similar to two-dimensional vectors:\n\n$$\nz \\equiv (u, u')\n$$\n\nand the idea is that $u$ represents the value of a function at a given point $f(x_0)$ and $u'$ the derivative at the same point $f'(x_0)$\n\nDual numbers can be summed, subtracted and multipliced by a scalar following the usual linearity rules:\n\n$$\n\\alpha (u, u') + \\beta (v, v') \\equiv (\\alpha u + \\beta v, \\alpha u' + \\beta v')\n$$\n\nBut they have special rules for multiplication and division.\nMultiplication, for instance, looks like:\n\n$$\n(u, u') \\cdot (v, v') \\equiv (u v, u'v + u v')\n$$\n\nLooks familiar?\nThe first \"coordinate\" just implements a regular multiplication.\nWhile the second \"coordinate\" describes the rule of product for derivatives.\n\nRegarding divison, the idea is the same:\n\n$$\n\\frac{(u, u')}{(v, v')} \\equiv (\\frac{u}{v}, \\frac{u'v - uv'}{v^2})\n$$\n\nIt is also quite useful to define the power of a dual number and a real number as:\n\n$$\n(u, u')^n = (u^n, n \\cdot u^{n-1} \\cdot u')\n$$\n\nDual numbers defined like this have an extraordinary property:\n\n\u003e If $q(x)$ is **any** algebraic function[^1]\n\u003e\n\u003e then\n\u003e\n\u003e $q((x_0, 1)) = (q(x_0), q'(x_0))$\n\nThis means that just evaluating the function with $(x_0, 1)$ instead of $x_0$ returns the derivative!\n\nI implemented these basic properties (and others) in the class `Dual`.\n\n---\n\nBut hey, what about non-algebraic functions[^2]?\nJust as we'll do with an undergraduate math student, we can teach our dual numbers the derivative of some basic functions.\nRemember those tables you had to learn in high school?\n\nFor instance, if we define:\n\n$$\n\\sin (u, u') \\equiv (\\sin u, \\cos u \\cdot u')\n$$\n\nnow our dual numbers can also deal with functions involving sines.\n\nI've implemented some of these derivatives in `dualdiff/primitives.py`.\nThe list can be easily extended in case of need.\n\n## How to use\n\nImagine you want to differentiate the function:\n\n```python\nfrom numpy import sin\n\ndef f(x):\n    return sin(x ** 2)\n```\n\nAll you have to do is to use the `@autodifferentiable` decorator:\n\n```python\nfrom dualdiff.primitives import *\nfrom dualdiff.decorators import autodifferentiable\n\n@autodifferentiable\ndef f(x):\n    return sin(x ** 2) + x\n```\n\nDecorated this way, by evaluating $f$ we get its value and it's derivative:\n\n```python\nx0 = 3\nf(x0)\n\n\u003e Dual(3.4121184852417565, # f(x_0)\n       -4.466781571308061) # f'(x_0)\n```\n\n[^1]: that is, a function only involving sums, subtractions, multiplications, divisons and powers.\n\n[^2]: such as, for instance, anything involving a cosine.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpabrod%2Fdualdiff","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpabrod%2Fdualdiff","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpabrod%2Fdualdiff/lists"}