Core API

This section of the documentation covers all of Padmini’s core interfaces. In order, we cover:

  • the main user-facing API

  • Padmini’s core data structures

  • the internal APIs that modify these data structures

For the implementation of specific rules, see the Prakaraṇa API.

High-level API

padmini.ashtadhyayi.tinanta(dhatu: str, dhatu_code: str, la: str, tags=None, options=None) padmini.prakriya.Prakriya

Generate a tinanta (verb).

Parameters
  • dhatu – the dhātu to use. dhatu must include any relevant accent marks. See dhatupatha.tsv for examples.

  • dhatu_code – the number in the Dhatupatha. This help distinguish between identical roots in separate ganas.

  • la – the lakāra to use. This must use a nasal vowel; use "la~w", not "law".

  • tags – extra tags to add to the derivation. For details, see Tag.

  • options – enables or disables various optional rules in the Ashtadhyayi. For details, see the comments in Prakriya.

Returns

the complete prakriyā.

padmini.ashtadhyayi.subanta(pratipadika: str, linga: str, tags=None, options=None) padmini.prakriya.Prakriya

Generate a subanta (nominal).

Parameters
  • pratipadika – the prAtipadika to use.

  • tags – extra tags to add to the derivation. For details, see Tag.

  • options – enables or disables various optional rules in the Ashtadhyayi. For details, see the comments in Prakriya.

Returns

the complete prakriyā.

Data Structures

Padmini stores its data in three main data structures:

  • an ordinary 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 Term, which is a str with extra metadata. Metadata includes any saṁjñās associated with the string, the string’s substitution history, and other minor information.

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

class padmini.prakriya.Term(u: str, text: str, tags: Set[str], gana: Optional[int], number: Optional[int])

A term is a generalized version of an upadesha. In addition to upadeshas, the term concept includes abhyāsas and any group of sounds that is not aupadeśika.

Parameters
  • u – The upadesha form of the term. If this is empty or missing, the term is not treated as an upadesha.

  • text – The “visible” text of the term. At the end of the derivation, we join the text of all terms together to create our final word.

  • tags – Any metadata associated with the term. Usually, this includes various samjnas. But it can also include past versions of the term (pratyayalope pratyayalakṣaṇam).

  • gana – For dhātus, this is the gana. Since a given dhātu can appear in multiple ganas, we use this parameter to disambiguate.

class padmini.prakriya.Prakriya(terms: List[padmini.prakriya.Term], tags: Set[str], history: List[Tuple[str, str]], options_override: Dict[str, bool], options_seen: List[Tuple[str, bool]])

A prakriya is a derivation within the Paninian system. It adds, removes, and modifies various terms until the result is a valid Sanskrit word or expression.

The Prakriya object manages all of the state associated with a prakriya. When the prakriya is complete, the final result can be accessed through the text attribute.

In addition, Prakriya manages all of the state related to optional rules (rules declared with vA, vibhASA, anyatarasyAm, or in the opinion of some vaiyAkaraNa). This state makes it easy for calling code to try different permutations of options and generate all of the possible forms for some given input.

Parameters
  • terms – the derivation state. The program modifies this list and its members during execution. If you want to preserve the initial state, provide a deep copy instead.

  • tags – any meta information that applies to the prakriya overall. This mainly contains semantic information (purusha, vacana) or sets the derivation context (chandasi). It is also used to manage “global” state that we cannot easily define on Tag objects.

  • history – the derivation history. This is a list of 2-tuples, where the first member is the current result and the second member is the rule we applied to get that result. If you want to log different information in the history, you can override the step method of this class.

  • options_override – maps a rule code to whether the rule can be used or not. This mapping has meaning only for optional rules and is ignored for mandatory rules.

  • options_seen – optional rules seen during the derivation. This is a list of 2-tuples, where the first member is the rule and the second is whether the rule was accepted or not.

Constants

class padmini.constants.Tag

Tag combines two concepts: saṃjñā and semantic conditions. These tags are then attached to a Term or Prakriya.

In addition to the tags below, a Term or Prakriya might also contain various it letters.

Views

class padmini.term_views.TermView(terms)

A view groups multiple terms into a convenient unit so that they can be used together in rules. For example, consider the partial derivation below:

dviz + (luk) yAs + s + t

If dviz is the anga, we may wish to condition on the following sound from yAs; on the presence or absence of luk; on the semantics of t; or on various other properties. So we generalize this behavior into a single TermView:

dviz + [(luk) yAs + s + t]

A TermView and a Term offer similar APIs. But whereas a Term can be freely modified, a TermView is generally read-only.

If needed, we can always access its terms attribute to modify the specific terms. But if you want to add or remove terms, create a new TermView instead.

Sounds

Sounds in the Ashtadhyayi have two main functions:

  • They condition operations by their presence or absence.

  • They transform according specific rules.

To handle these two use cases, this module exposes two primary functions:

padmini.sounds.s(terms: str) padmini.sounds.OrderedSet[str]

Create an ordered set of Sanskrit sounds.

The function understands the following sounds:

  • bare vowels (“a i u”)

  • udit (“ku~”)

  • pratyāhāras (“ac hal”)

For convenience, all arguments can be passed in one string.

The return value is a set so that membership checks are constant-time, and it is an OrderedSet per yathāsaṁkhyam anudeśaḥ samānām (i.e. list substitution is done in 1:1 correspondence).

Example usage:

ik = s("ik")
cavarga = s("cu~")
kanthya = s("a ku~ h H")

To use the second R of the pratyāhāra, use the following syntax:

first_n = s("iR")
second_n = s("iR2")
Parameters

terms – a string of upadeshas.

Returns

an OrderedSet of sounds

padmini.sounds.map_sounds(left: padmini.sounds.OrderedSet, right: padmini.sounds.OrderedSet) Dict[str, str]

Map one sound group to another.

Every Sanskrit sound has various properties, e.g.:

  • sthāna (point of articulation)

  • prayatna (articulatory effort)

  • ghoṣa (voicing)

  • prāṇa (aspiration),

This function maps the sounds in left to their closest counterpart in right, per rule 1.1.50:

1.1.50 sthāne’ntaratamaḥ

Parameters
  • left – the “input” side of the mapping.

  • right – the “output” side of the mapping.

Returns

a mapping from each sound in left to its closest sound in right.

Filters

Before we apply a rule, we must first test if it meets the necessary conditions. Many conditions are simple or adhoc (e.g. t.antya in s('ac') to test if a term ends in a vowel). More complex conditions are specified below:

padmini.filters.is_aprkta(t: padmini.prakriya.Term) bool

True iff t is apr̥kta (a single-sound pratyaya).

padmini.filters.is_guru(t: padmini.prakriya.Term) bool

True iff the last syllable of t is guru.

padmini.filters.is_hrasva(t: padmini.prakriya.Term) bool

True iff the last sound of t is a short vowel.

padmini.filters.is_it_agama(t: padmini.prakriya.Term) bool

True iff t is the iṭ-āgama.

padmini.filters.is_laghu(t: padmini.prakriya.Term) bool

True iff the last syllable of t is or could be laghu.

padmini.filters.samyogadi(t: padmini.prakriya.Term) bool

True iff t starts with multiple consonants.

padmini.filters.samyoganta(t: padmini.prakriya.Term) bool

True iff t ends in multiple consonants.

Operations

The Ashtadhyayi modifies the derivation state with three types of rules:

  • vidhi (transformation), which change the sounds in a prakriyā.

  • saṃjñā (designation), which adds new saṁjñās to a prakriyā.

  • atideśa (analogy), which usually extends an it-saṁjñā to a prakriyā.

More abstractly, all of these rule types modify the prakriyā by changing its sounds and designations. We call this abstract category the operation.

As much as possible, any changes to the Prakriya are applied through this module (as opposed to ad-hoc logic). By doing so, we keep the code DRY and concise.

Most operations apply to a single term and have this basic structure:

def some_operation(rule: str, p: Prakriya, t: Term, *args):
    # Modify the term in some way
    t.text = [...]
    # Record which rule was applied
    p.step(rule)
padmini.operations.adi(rule: Optional[str], p: padmini.prakriya.Prakriya, u: padmini.prakriya.Term, sub: str)

Replace the first sound.

padmini.operations.antya(rule: str, p: padmini.prakriya.Prakriya, u: padmini.prakriya.Term, sub: str)

Replace the last sound.

padmini.operations.antya_yatha(base: str, before, after) str

Legacy function. Replace from the last sound on.

padmini.operations.insert_after(rule: Optional[str], p: padmini.prakriya.Prakriya, needle: padmini.prakriya.Term, new_term: padmini.prakriya.Term)

Insert after the given term.

padmini.operations.insert_before(rule: str, p: padmini.prakriya.Prakriya, needle: padmini.prakriya.Term, new_term: padmini.prakriya.Term)

Insert before the given term.

padmini.operations.lopa(rule: str, p: padmini.prakriya.Prakriya, u: padmini.prakriya.Term)

Delete the given term.

padmini.operations.luk(rule: str, p: padmini.prakriya.Prakriya, u: padmini.prakriya.Term)

Delete the given term with luk.

padmini.operations.mit(rule: str, p: padmini.prakriya.Prakriya, u: padmini.prakriya.Term, sub: str)

Insert after the last vowel.

padmini.operations.optional(func, rule: str, p: padmini.prakriya.Prakriya, *args) bool

Wrapper that defines an optional operation.

If the original operation has this syntax:

func(rule, p, *args)

Then we can make the operation optional with:

optional(func, rule, p, *args)
Parameters
  • func – the operation function to apply

  • rule – the rule ID

  • p – the prakriya

  • args – the args to pass to func

Returns

True iff the option was accepted.

padmini.operations.samjna(rule: str, p: padmini.prakriya.Prakriya, u: padmini.prakriya.Term, *tags: List[str])

Add new tags to u.

padmini.operations.slu(rule: str, p: padmini.prakriya.Prakriya, u: padmini.prakriya.Term)

Delete the given term with Slu.

padmini.operations.tag(rule: str, p: padmini.prakriya.Prakriya, u: padmini.prakriya.Term, *tags: List[str])

Add new tags to u.

padmini.operations.text(rule: str, p: padmini.prakriya.Prakriya, u: padmini.prakriya.Term, sub: str)

Replace Term.text.

padmini.operations.ti(rule: str, p: padmini.prakriya.Prakriya, u: padmini.prakriya.Term, sub: str)

Replace from the last vowel on.

padmini.operations.upadesha(rule: str, p: padmini.prakriya.Prakriya, u: padmini.prakriya.Term, sub: str)

Replace Term.upadesha and apply it_samjna.run.

padmini.operations.upadesha_no_it(rule: str, p: padmini.prakriya.Prakriya, u: padmini.prakriya.Term, sub: str)

Replace Term.upadesha with no follow_up, in case we need to apply lopa.

padmini.operations.upadha(rule_code: str, p: padmini.prakriya.Prakriya, u: padmini.prakriya.Term, sub: str)

Replace the penultimate sound.

padmini.operations.yatha(text: str, before, after)

Legacy function. Replace in 1:1 correspondence.