Skip to content
This repository has been archived by the owner on Dec 30, 2022. It is now read-only.

Commit

Permalink
more docs
Browse files Browse the repository at this point in the history
  • Loading branch information
akprasad committed Feb 26, 2022
1 parent a00ed8f commit fd266ac
Show file tree
Hide file tree
Showing 5 changed files with 268 additions and 1 deletion.
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

# -- Project information -----------------------------------------------------

project = "padmini"
project = "Padmini"
copyright = "2021, Arun Prasad"
author = "Arun Prasad"

Expand Down
2 changes: 2 additions & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ User's Guide
introduction
setup
quickstart
system-design



Expand All @@ -52,3 +53,4 @@ Appendices

.. toctree::
slp1-transliteration
prior-work
70 changes: 70 additions & 0 deletions docs/prior-work.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
Prior Work
----------

There have been many attempts to model the Ashtadhyayi in code, but Padmini is
especially influenced by SanskritVerb and Vyakarana.

Padmini owes an immense debt to SanskritVerb for providing a solid reference
implementation, which we used for debugging. Even knowing that a solid
implementation was possible and feasible was a great source of encouragement
during the more difficult parts of the implementation work.

In terms of technical design, Padmini is a direct successor to our older
Vyakarana_ project and adopts many of the same concepts and philosophies.

.. _Vyakarana: https://vyakarana.readthedocs.io
.. _SanskritVerb: https://github.com/drdhaval2785/SanskritVerb

The major difference between Vyakarana and Padmini is that Vyakarana explicitly
models rule selection using traditional mechanisms. In order to enable this,
Vyakarana wraps most of its code in classes and first-order functions and
introduces a quasi-DSL for transforming and combining these rules. For example,
two filters could be combined with Vyakarana's ``&`` operator to create a
boolean *and*. This allows easier inspection on the filters and operators
involved in each rule, which in turns allows ranking in a priority queue.

In comparison, Padmini does not model rule selection and instead uses a fixed
rule order that turns the Ashtadhyayi into a normal iterative program. While
this decision is less true to the spirit of the Ashtadhyayi, it creates a
program that is substantially easier to read and maintain.

To illustrate the effect this has on ordinary code, here is how Vyakarana would
model a rule where we apply vr̥ddhi if the term starts with a consonant and ends
with a vowel:

.. code-block:: python
class adi(AlFilter):
def body(self, term):
return term.adi in self.domain
class antya(AlFilter):
def body(self, term):
return term.antya in self.domain
@Operator.no_params
def vrddhi(state, index, locus=None):
...
RULES = [
('some_rule', None, adi('hal') & antya ('ac'), None, vrddhi)
]
And how Padmini would do it:

.. code-block:: python
from padmini.sounds import s
def vrddhi(term):
...
def run(p: Prakriya, i):
c = p.terms[i]
if c.adi in s('hal') and c.antya in s('ac'):
vrddhi(c)
While the Vyakarana code has interesting properties that the Padmini code does
not, the Padmini code is substantially more readable and accessible.
120 changes: 120 additions & 0 deletions docs/quickstart.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
Quickstart
==========

This quickstart doc will show you how to generate words with Padmini. We first
show how Padmini produces basic derivations. We then show how Padmini generates
optional derivations if multiple prakriyās could be produced from the same
initial conditions.

.. note::
As a reminder, Padmini uses SLP1 transliteration internally. For details,
see the :doc:`slp1-transliteration` doc.

.. currentmodule:: padmini.ashtadhyayi


tiṅanta
-------

A **tiṅanta** is a verb. All tiṅantas are generated by the :func:`tinanta`
function, which you can see below:

.. code-block:: python
from padmini.ashtadhyayi import tinanta
from padmini.constants import Tag as T
prakriya = tinanta('BU', '01.0001', 'la~w', tags=[T.PRATHAMA, T.EKAVACANA])
print(prakriya.text)
for result, rule in prakriya.history:
print(f" {result} ({rule})")
In order, the arguments to :func:`tinanta` are:

1. the dhātu in its upadeśa form, including accent marks
2. the dhātu's gaṇa and order within the Dhātupāṭha
3. the specific lakāra to use with this dhātu
4. the derivation context, here referring to prathama-puruṣa and ekavacana

:func:`tinanta` returns a :class:`~padmini.prakriya.Prakriya` object, which
contains our final words. For example, the script above will produce the
following output:

.. code-block:: text
Bavati
BU (start)
BU (1.3.1)
BU la~w (3.3.123)
BU la~w (1.3.2)
BU la~w (1.3.4)
BU l (1.3.9)
BU l (1.3.78)
BU tip (3.4.78)
BU tip (1.3.4)
BU ti (1.3.9)
BU ti (3.4.113)
BU Sap ti (3.1.68)
BU Sap ti (1.3.4)
BU Sap ti (1.3.8)
BU a ti (1.3.9)
BU a ti (3.4.113)
Bo a ti (7.3.84)
Bav a ti (6.1.78)
.. currentmodule:: padmini.prakriya

Each step modifies the :class:`Prakriya` in some way. For example, rule 1.3.1
(bhūvādayo dhātavaḥ) adds the tag `Tag.DHATU` to the first :class:`Term`.


subanta
-------

.. currentmodule:: padmini.ashtadhyayi

A **subanta** is usually a nominal, but this category also includes uninflected
words. All subantas are generated by the :func:`subanta` function, which you
can see below:


.. code-block:: python
from padmini.ashtadhyayi import subanta
from padmini.constants import Tag
prakriya = subanta('nara', Tag.PUM, [Tag.V6, Tag.EKAVACANA])
print(prakriya.text)
for result, rule in prakriya.history:
print(f" {result} ({rule})")
In order, the arguments to :func:`tinanta` are:

1. the prātipadika to use
2. the liṅga (gender) to use
3. the derivation context, here referring to ṣaṣṭhī-vibhakti and ekavacana

:func:`subanta` returns a :class:`~padmini.prakriya.Prakriya` object, which
contains our final word. For example, the script above will produce the
following output:

.. code-block:: text
narasya
nara (start)
nara (1.2.45)
nara Nas (4.1.2)
nara Nas (1.3.8)
nara as (1.3.9)
nara sya (7.1.12)
Optional prakriyās
------------------

For now, optional prakriyās are supported only in test code. See
`test/utils.py` for an example, particularly the `run_all_permutations`
function.
75 changes: 75 additions & 0 deletions docs/system-design.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
System Design
=============

Philosophy
----------

Padmini follows the principles of the tradition as much as possible, but we
break with the traditional model of rule selection, since doing so greatly
simplifies the program.


Data Types
----------

Padmini stores its data in three main data structures:

- an ordinary :class:`str`, which denotes a sequence of sounds in SLP1
transliteration. We use SLP1 because it represents each sound with exactly
one character, which greatly simplifies the code. (For example, a string's
last sound is just ``s[-1]``.)

- a :class:`Term`, which is a :class:`str` with extra metadata. Metadata
includes any saṁjñās associated with the string, the string's substitution
history, and other minor information.

- a :class:`Prakriya`, which is a list of :class:`~Term` and extra metadata.
Metadata includes the derivation history, saṁjñās that apply to the prakriyā
as a whole, and other minor information.


Filters and Operators
---------------------

.. currentmodule: padmini.prakriya
We model a rule as having two parts: a **filter** that checks if the rule can
apply, and an **operation** that makes the necessary change. Filters and
operations are allowed to work on :class:`Prakriya` directly, but usually they
work on :class:`Term` instead:

.. code-block:: python
if filter(term):
op(term)
Filters might be actual Python functions, but they are usually simple
expressions that take advantage of :class:`Term`'s rich API:

.. code-block:: python
if term.antya == 'a':
op(prakriya)
Operations, meanwhile, are usually standardized functions from the
:mod:`~padmini.operations` module. By centralizing operator code in one place,
we make it easy to make implementation or bookkeeping changes to the system as
a whole.

Here is an example of a simple rule from Padmini. This rule creates verbs like
*tasthau* and *jagau*:

.. code-block:: Python
if prev.antya == "A" and tin.u == "Ral":
op.upadesha("7.1.34", p, tin, "O")
Here the rule uses :func:`~padmini.operations.upadesha` to replace the upadeśa
value of the final tiṅ suffix.


Creating a Prakriyā
-------------------

.. note::
Coming soon.

0 comments on commit fd266ac

Please sign in to comment.