# AMR Logic Converter
[![ci](https://img.shields.io/github/actions/workflow/status/chanind/amr-logic-converter/ci.yaml?branch=main)](https://github.com/chanind/amr-logic-converter)
[![Codecov](https://img.shields.io/codecov/c/github/chanind/amr-logic-converter/main)](https://codecov.io/gh/chanind/amr-logic-converter)
[![PyPI](https://img.shields.io/pypi/v/amr-logic-converter?color=blue)](https://pypi.org/project/amr-logic-converter/)
Convert Abstract Meaning Representation (AMR) to first-order logic statements.
This library is based on the ideas in the paper ["Expressive Power of Abstract Meaning Representations", J. Bos, Computational Linguistics 42(3), 2016](http://www.mitpressjournals.org/doi/pdf/10.1162/COLI_a_00257). Thank you to [@jobos](https://github.com/jobos) for the paper!
## Installation
```
pip install amr-logic-converter
```
## Usage
This library parses an AMR tree into first-order logic statements. An example of this is shown below:
```python
from amr_logic_converter import AmrLogicConverter
converter = AmrLogicConverter()
AMR = """
(x / boy
:ARG0-of (e / giggle-01
:polarity -))
"""
logic = converter.convert(AMR)
print(logic)
# boy(x) ^ ¬(:ARG0(e, x) ^ giggle-01(e))
```
### Programmatic logic manipulation
The output from the `convert` method can be displayed as a string, but it can also be manipulated in Python. For instance, in the example above, we could also write:
```python
converter = AmrLogicConverter()
AMR = """
(x / boy
:ARG0-of (e / giggle-01
:polarity -))
"""
expr = converter.convert(AMR)
type(expr) # <class 'amr_logic_converter.types.And'>
expr.args[0] # Atom(predicate=Predicate(symbol='boy', alignment=None), terms=(Constant(value='x', type='instance', alignment=None),))
```
### Working with alignment markers
This library will parse alignment markers from AMR using the [penman library](https://penman.readthedocs.io/en/latest/), and will include [Alignment](https://penman.readthedocs.io/en/latest/api/penman.surface.html#penman.surface.Alignment) objects from penman in `Predicate` and `Const` objects when available. For example, we can access alignment markers like below:
```python
converter = AmrLogicConverter()
AMR = """
(x / boy~1
:ARG0-of (e / giggle-01~3
:polarity -))
"""
expr = converter.convert(AMR)
expr.args[0].alignment # Alignment((1,))
expr.args[1].body.args[1].alignment # Alignment((3,))
```
### Existentially Quantifying all Instances
In ["Expressive Power of Abstract Meaning Representations"](http://www.mitpressjournals.org/doi/pdf/10.1162/COLI_a_00257), all instances are wrapped by an existence quantifier. By default `AmrLogicConverter` does not include these as it's likely not useful, but if you'd like to include them as in the paper you can pass the option `existentially_quantify_instances=True` when constructing the `AmrLogicConverter` as below:
```python
converter = AmrLogicConverter(existentially_quantify_instances=True)
AMR = """
(x / boy
:ARG0-of (e / giggle-01
:polarity -))
"""
logic = converter.convert(AMR)
print(logic)
# ∃X(boy(X) ^ ¬∃E(:ARG0(E, X) ^ giggle-01(E)))
```
### Coreference Hoisting
When an instance is coreferenced in multiple places in the AMR, it's necessary to hoisting the existential quantification of that variable high enough that it can still wrap all instances of that variable. By default, the existential quantifier will be hoisted to the level of the lowest common ancestor of all nodes in the AMR tree where an instance is coreferenced. However, in ["Expressive Power of Abstract Meaning Representations"](http://www.mitpressjournals.org/doi/pdf/10.1162/COLI_a_00257), these coreferences are instead hoisted to the maximal possible scope, wrapping the entire formula. If you want this behavior, you can specify the option `maximally_hoist_coreferences=True` when creating the `AmrLogicConverter` instance. This is illustrated below:
```python
AMR = """
(b / bad-07
:polarity -
:ARG1 (e / dry-01
:ARG0 (x / person
:named "Mr Krupp")
:ARG1 x))
"""
# default behavior, hoist only to the lowest common ancestor
converter = AmrLogicConverter(
existentially_quantify_instances=True,
)
logic = converter.convert(AMR)
print(logic)
# ¬∃B(bad-07(B) ∧ ∃E(∃X(:ARG1(B, E) ∧ person(X) ∧ :named(X, "Mr Krupp") ∧ dry-01(E) ∧ :ARG0(E, X) ∧ :ARG1(E, X))))
# maximally hoist coferences
converter = AmrLogicConverter(
existentially_quantify_instances=True,
maximally_hoist_coreferences=True,
)
logic = converter.convert(AMR)
print(logic)
# ∃X(¬∃B(bad-07(B) ∧ ∃E(:ARG1(B, E) ∧ dry-01(E) ∧ :ARG0(E, X) ∧ :ARG1(E, X))) ∧ person(X) ∧ :named(X, "Mr Krupp"))
```
### Using Variables for Instances
If you want to use variables for each AMR instance instead of constants, you can pass the option `use_variables_for_instances=True` when creating the AmrLogicConverter instance. When `existentially_quantify_instances` is set, variable will always be used for instances regardless of this setting.
## Misc Options
- By default variables names are capitalized, but you can change this by setting `capitalize_variables=False`.
- By default, relations like `:ARG0-of(X, Y)` have their arguments flipped in logic and turned into `:ARG0(Y, X)`. If you don't want this normalization to occur, you can disable this by setting `invert_relations=False`.
## Contributing
Contributions are welcome! Please leave an issue in the Github repo if you find any bugs, and open a pull request with and fixes or improvements that you'd like to contribute. Ideally please include new test cases to verify any changes or bugfixes if appropriate.
This project uses [poetry](https://python-poetry.org/) for dependency management and packaging, [black](https://black.readthedocs.io/en/stable/) for code formatting, [flake8](https://flake8.pycqa.org/en/latest/) for linting, and [mypy](https://mypy.readthedocs.io/en/stable/) for type checking.
## License
This project is licenced under a MIT license.
## Citation
If you use this software in your work, please cite the following:
```bibtex
@article{chanin2023neuro,
title={Neuro-symbolic Commonsense Social Reasoning},
author={Chanin, David and Hunter, Anthony},
journal={arXiv preprint arXiv:2303.08264},
year={2023}
}
```
Raw data
{
"_id": null,
"home_page": "https://github.com/chanind/amr-logic-converter",
"name": "amr-logic-converter",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.10",
"maintainer_email": null,
"keywords": "amr, logic, first-order-logic, nlp, abstract-meaning-representation",
"author": "David Chanin",
"author_email": "chanindav@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/4c/4b/527569aa7b36ec5f67236e4f575897d1ee2c408fe6af20680b98e1fe901d/amr_logic_converter-0.11.3.tar.gz",
"platform": null,
"description": "# AMR Logic Converter\n\n[![ci](https://img.shields.io/github/actions/workflow/status/chanind/amr-logic-converter/ci.yaml?branch=main)](https://github.com/chanind/amr-logic-converter)\n[![Codecov](https://img.shields.io/codecov/c/github/chanind/amr-logic-converter/main)](https://codecov.io/gh/chanind/amr-logic-converter)\n[![PyPI](https://img.shields.io/pypi/v/amr-logic-converter?color=blue)](https://pypi.org/project/amr-logic-converter/)\n\nConvert Abstract Meaning Representation (AMR) to first-order logic statements.\n\nThis library is based on the ideas in the paper [\"Expressive Power of Abstract Meaning Representations\", J. Bos, Computational Linguistics 42(3), 2016](http://www.mitpressjournals.org/doi/pdf/10.1162/COLI_a_00257). Thank you to [@jobos](https://github.com/jobos) for the paper!\n\n## Installation\n\n```\npip install amr-logic-converter\n```\n\n## Usage\n\nThis library parses an AMR tree into first-order logic statements. An example of this is shown below:\n\n```python\nfrom amr_logic_converter import AmrLogicConverter\n\nconverter = AmrLogicConverter()\n\nAMR = \"\"\"\n(x / boy\n :ARG0-of (e / giggle-01\n :polarity -))\n\"\"\"\n\nlogic = converter.convert(AMR)\nprint(logic)\n# boy(x) ^ \u00ac(:ARG0(e, x) ^ giggle-01(e))\n```\n\n### Programmatic logic manipulation\n\nThe output from the `convert` method can be displayed as a string, but it can also be manipulated in Python. For instance, in the example above, we could also write:\n\n```python\nconverter = AmrLogicConverter()\n\nAMR = \"\"\"\n(x / boy\n :ARG0-of (e / giggle-01\n :polarity -))\n\"\"\"\n\nexpr = converter.convert(AMR)\ntype(expr) # <class 'amr_logic_converter.types.And'>\nexpr.args[0] # Atom(predicate=Predicate(symbol='boy', alignment=None), terms=(Constant(value='x', type='instance', alignment=None),))\n```\n\n### Working with alignment markers\n\nThis library will parse alignment markers from AMR using the [penman library](https://penman.readthedocs.io/en/latest/), and will include [Alignment](https://penman.readthedocs.io/en/latest/api/penman.surface.html#penman.surface.Alignment) objects from penman in `Predicate` and `Const` objects when available. For example, we can access alignment markers like below:\n\n```python\nconverter = AmrLogicConverter()\n\nAMR = \"\"\"\n(x / boy~1\n :ARG0-of (e / giggle-01~3\n :polarity -))\n\"\"\"\n\nexpr = converter.convert(AMR)\nexpr.args[0].alignment # Alignment((1,))\nexpr.args[1].body.args[1].alignment # Alignment((3,))\n```\n\n### Existentially Quantifying all Instances\n\nIn [\"Expressive Power of Abstract Meaning Representations\"](http://www.mitpressjournals.org/doi/pdf/10.1162/COLI_a_00257), all instances are wrapped by an existence quantifier. By default `AmrLogicConverter` does not include these as it's likely not useful, but if you'd like to include them as in the paper you can pass the option `existentially_quantify_instances=True` when constructing the `AmrLogicConverter` as below:\n\n```python\nconverter = AmrLogicConverter(existentially_quantify_instances=True)\n\nAMR = \"\"\"\n(x / boy\n :ARG0-of (e / giggle-01\n :polarity -))\n\"\"\"\n\nlogic = converter.convert(AMR)\nprint(logic)\n# \u2203X(boy(X) ^ \u00ac\u2203E(:ARG0(E, X) ^ giggle-01(E)))\n```\n\n### Coreference Hoisting\n\nWhen an instance is coreferenced in multiple places in the AMR, it's necessary to hoisting the existential quantification of that variable high enough that it can still wrap all instances of that variable. By default, the existential quantifier will be hoisted to the level of the lowest common ancestor of all nodes in the AMR tree where an instance is coreferenced. However, in [\"Expressive Power of Abstract Meaning Representations\"](http://www.mitpressjournals.org/doi/pdf/10.1162/COLI_a_00257), these coreferences are instead hoisted to the maximal possible scope, wrapping the entire formula. If you want this behavior, you can specify the option `maximally_hoist_coreferences=True` when creating the `AmrLogicConverter` instance. This is illustrated below:\n\n```python\nAMR = \"\"\"\n(b / bad-07\n :polarity -\n :ARG1 (e / dry-01\n :ARG0 (x / person\n :named \"Mr Krupp\")\n :ARG1 x))\n\"\"\"\n\n# default behavior, hoist only to the lowest common ancestor\nconverter = AmrLogicConverter(\n existentially_quantify_instances=True,\n)\nlogic = converter.convert(AMR)\nprint(logic)\n# \u00ac\u2203B(bad-07(B) \u2227 \u2203E(\u2203X(:ARG1(B, E) \u2227 person(X) \u2227 :named(X, \"Mr Krupp\") \u2227 dry-01(E) \u2227 :ARG0(E, X) \u2227 :ARG1(E, X))))\n\n# maximally hoist coferences\nconverter = AmrLogicConverter(\n existentially_quantify_instances=True,\n maximally_hoist_coreferences=True,\n)\nlogic = converter.convert(AMR)\nprint(logic)\n# \u2203X(\u00ac\u2203B(bad-07(B) \u2227 \u2203E(:ARG1(B, E) \u2227 dry-01(E) \u2227 :ARG0(E, X) \u2227 :ARG1(E, X))) \u2227 person(X) \u2227 :named(X, \"Mr Krupp\"))\n```\n\n### Using Variables for Instances\n\nIf you want to use variables for each AMR instance instead of constants, you can pass the option `use_variables_for_instances=True` when creating the AmrLogicConverter instance. When `existentially_quantify_instances` is set, variable will always be used for instances regardless of this setting.\n\n## Misc Options\n\n- By default variables names are capitalized, but you can change this by setting `capitalize_variables=False`.\n- By default, relations like `:ARG0-of(X, Y)` have their arguments flipped in logic and turned into `:ARG0(Y, X)`. If you don't want this normalization to occur, you can disable this by setting `invert_relations=False`.\n\n## Contributing\n\nContributions are welcome! Please leave an issue in the Github repo if you find any bugs, and open a pull request with and fixes or improvements that you'd like to contribute. Ideally please include new test cases to verify any changes or bugfixes if appropriate.\n\nThis project uses [poetry](https://python-poetry.org/) for dependency management and packaging, [black](https://black.readthedocs.io/en/stable/) for code formatting, [flake8](https://flake8.pycqa.org/en/latest/) for linting, and [mypy](https://mypy.readthedocs.io/en/stable/) for type checking.\n\n## License\n\nThis project is licenced under a MIT license.\n\n## Citation\nIf you use this software in your work, please cite the following:\n\n```bibtex\n@article{chanin2023neuro,\n title={Neuro-symbolic Commonsense Social Reasoning},\n author={Chanin, David and Hunter, Anthony},\n journal={arXiv preprint arXiv:2303.08264},\n year={2023}\n}\n```\n\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Convert Abstract Meaning Representation (AMR) into first-order logic",
"version": "0.11.3",
"project_urls": {
"Homepage": "https://github.com/chanind/amr-logic-converter",
"Repository": "https://github.com/chanind/amr-logic-converter"
},
"split_keywords": [
"amr",
" logic",
" first-order-logic",
" nlp",
" abstract-meaning-representation"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "3c7b425f1c72b82aa31ac355c86399b007ba3bb1ab2ff312b26da496f74ffc3d",
"md5": "1b3e38820a534fe775f5268933589455",
"sha256": "bfbf0e44cbfa1068c7f0763dc639e92608faec3921c3c6a2e1230405141adb1b"
},
"downloads": -1,
"filename": "amr_logic_converter-0.11.3-py3-none-any.whl",
"has_sig": false,
"md5_digest": "1b3e38820a534fe775f5268933589455",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.10",
"size": 15499,
"upload_time": "2024-08-07T22:42:26",
"upload_time_iso_8601": "2024-08-07T22:42:26.630815Z",
"url": "https://files.pythonhosted.org/packages/3c/7b/425f1c72b82aa31ac355c86399b007ba3bb1ab2ff312b26da496f74ffc3d/amr_logic_converter-0.11.3-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "4c4b527569aa7b36ec5f67236e4f575897d1ee2c408fe6af20680b98e1fe901d",
"md5": "98a4b01f3c66843be107d66c46957d16",
"sha256": "4637c1bf07fb2922a2f740322824744d9be794a3479a40d8634de2c1d6b24404"
},
"downloads": -1,
"filename": "amr_logic_converter-0.11.3.tar.gz",
"has_sig": false,
"md5_digest": "98a4b01f3c66843be107d66c46957d16",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.10",
"size": 13535,
"upload_time": "2024-08-07T22:42:28",
"upload_time_iso_8601": "2024-08-07T22:42:28.140723Z",
"url": "https://files.pythonhosted.org/packages/4c/4b/527569aa7b36ec5f67236e4f575897d1ee2c408fe6af20680b98e1fe901d/amr_logic_converter-0.11.3.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-08-07 22:42:28",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "chanind",
"github_project": "amr-logic-converter",
"travis_ci": false,
"coveralls": true,
"github_actions": true,
"lcname": "amr-logic-converter"
}