.. py:currentmodule:: vidyut.prakriya Generating words with `vidyut.prakriya` ======================================= `vidyut.prakriya` generates Sanskrit words with their prakriyās (derivations) according to the rules of Paninian grammar. This powerful word generator is useful both for creating Sanskrit words and for understanding how words are derived. .. note:: All inputs to `vidyut.prakriya` should use the `SLP1`_ encoding scheme, and output is likewise encoded in SLP1. You can convert to and from SLP1 by using `vidyut.lipi` or your favorite transliterator. .. _SLP1: https://en.wikipedia.org/wiki/SLP1 Sanskrit grammatical terms -------------------------- `vidyut.prakriya` closely follows the rules of the *Aṣṭādhyāyī*, the core text of the Sanskrit grammatical tradition. Here are the most important terms to know: .. csv-table:: Sanskrit terms with English equivalents :header: "Sanskrit", "English" *aupadeśika*, the "instructional" or technical form of some term *antargaṇa*, verb subclass *avyaya*, uninflected word *upasarga*, verb prefix *kṛt*, verb suffix *gaṇa*, verb class *taddhita*, nominal suffix *tiṅanta*, verb *dhātu*, verb root *pada*, word *puruṣa*, person *prayoga*, voice *prakriyā*, derivation (of a word) *prātipadika*, nominal stem *lakāra*, tense-mood *liṅga*, gender *vacana*, number *vibhakti*, case *sanādi*, derived root suffix *samāsa*, compound *subanta*, nominal Quickstart ---------- All usage of `vidyut.prakriya` follows a basic flow: 1. We create a new :class:`Vyakarana` object, which is our main interface to the grammar. When we create :class:`Vyakarana`, we can also fine-tune the rules and settings the system will use. Creating this object is fast and lightweight. 2. We pass various arguments to :class:`Vyakarana` to define our derivation. 3. We receive a list of :class:`Prakriya` objects. Each :class:`Prakriya` contains a final result and the rules that produced it. To illustrate, let's derive the simple verb ``Bavati``: .. testcode:: from vidyut.prakriya import ( Vyakarana, Dhatu, Gana, Pada, Prayoga, Purusha, Vacana, Lakara ) # 1. Create a new `Vyakarana` object. v = Vyakarana() # 2. Define and run our derivation. prakriyas = v.derive(Pada.Tinanta( # `aupadeshika` should includes svaras as necessary. If you don't # want to add this yourself, see "Working with data files" below. dhatu=Dhatu.mula(aupadeshika="BU", gana=Gana.Bhvadi), prayoga=Prayoga.Kartari, lakara=Lakara.Lat, purusha=Purusha.Prathama, vacana=Vacana.Eka, )) # 3. Receive a list of prakriyas. for prakriya in prakriyas: print(prakriya.text) print('===================') for step in prakriya.history: result = ' + '.join(term.text for term in step.result) print("{:<10}: {}".format(step.code, result)) This produces the following output: .. testoutput:: Bavati =================== 1.3.1 : BU 3.2.123 : BU + la~w 1.3.2 : BU + la~w 1.3.3 : BU + la~w 1.3.9 : BU + l 1.3.78 : BU + l 3.4.78 : BU + tip 1.3.3 : BU + tip 1.3.9 : BU + ti 3.4.113 : BU + ti 3.1.68 : BU + Sap + ti 1.3.3 : BU + Sap + ti 1.3.8 : BU + Sap + ti 1.3.9 : BU + a + ti 3.4.113 : BU + a + ti 1.4.13 : BU + a + ti 7.3.84 : Bo + a + ti 1.4.14 : Bo + a + ti 6.1.78 : Bav + a + ti 8.4.68 : Bav + a + ti Basic methods ------------- .. py:currentmodule:: vidyut.prakriya.Vyakarana :meth:`Vyakarana.derive` is the main method for creating derivations. It accepts several kinds of input arguments and returns a list of :class:`~Prakriya` objects according to the the arguments provided. To derive tinantas, use :meth:`Pada.Tinanta`: .. testcode:: from vidyut.prakriya import * v = Vyakarana() bhu = Dhatu.mula(aupadeshika="BU", gana=Gana.Bhvadi) prakriyas = v.derive(Pada.Tinanta( dhatu=bhu, prayoga=Prayoga.Kartari, lakara=Lakara.Lat, purusha=Purusha.Prathama, vacana=Vacana.Eka, )) assert len(prakriyas) == 1 assert prakriyas[0].text == "Bavati" To derive subantas, use :meth:`Pada.Subanta`: .. testcode:: deva = Pratipadika.basic("deva") prakriyas = v.derive(Pada.Subanta( pratipadika=deva, linga=Linga.Pum, vibhakti=Vibhakti.Prathama, vacana=Vacana.Eka, )) assert len(prakriyas) == 1 assert prakriyas[0].text == "devaH" To derive pratipadikas, use :class:`~Pratipadika`: .. testcode:: v = Vyakarana() # Krdanta # NOTE: all values on `Krt` are written in SLP1. See the API docs for a # full list of supported values. abhibhu = Dhatu.mula(aupadeshika="BU", gana=Gana.Bhvadi).with_prefixes(["aBi"]) abhibhavaka = Pratipadika.krdanta(abhibhu, Krt.Rvul) prakriyas = v.derive(abhibhavaka) assert prakriyas[0].text == "aBiBAvaka" # Taddhitanta # NOTE: all values on `Taddhita` are written in SLP1. See the API docs for a # full list of supported values. guru = Pratipadika.basic("guru") gaurava = Pratipadika.taddhitanta(guru, Taddhita.aR) prakriyas = v.derive(gaurava) assert prakriyas[0].text == "gOrava" To derive dhatus, use :class:`~Dhatu`: .. testcode:: v = Vyakarana() upa_r = Dhatu.mula(aupadeshika="f\\", gana=Gana.Bhvadi).with_prefixes(["upa"]) prakriyas = v.derive(upa_r) assert len(prakriyas) == 1 assert prakriyas[0].text == "upAr" Specifying arguments -------------------- .. py:currentmodule:: vidyut.prakriya The real expressive power in this library comes from expressing different kinds of arguments. For example, we can modify a :class:`Dhatu` to use one or more prefixes: .. testcode:: bhu = Dhatu.mula("BU", Gana.Bhvadi) abhibhu = Dhatu.mula("BU", Gana.Bhvadi, prefixes=["abhi"]) # Or, use the shorthand method `with_prefixes`: paribhu = bhu.with_prefixes(["abhi"]) Or one or more :class:`Sanadi` suffixes: .. testcode:: bhu = Dhatu.mula("BU", Gana.Bhvadi) bhavaya = Dhatu.mula("BU", Gana.Bhvadi, sanadi=[Sanadi.Ric]) # Or, use the shorthand method `with_sanadi`. bubhusha = bhu.with_sanadi([Sanadi.san]) # These can be combined with prefixes. abhibubhusha = bhu.with_prefixes(["aBi"]).with_sanadi([Sanadi.san]) These dhatus can be used to create more complex forms: .. testcode:: prakriyas = v.derive(Pada.Tinanta( dhatu=abhibubhusha, prayoga=Prayoga.Kartari, lakara=Lakara.Lat, purusha=Purusha.Prathama, vacana=Vacana.Eka, )) assert prakriyas[0].text == 'aBibuBUzati' Likewise, we can declare that a :class:`Pratipadika` is a *krdanta*: .. testcode:: bhu = Dhatu.mula(aupadeshika="BU", gana=Gana.Bhvadi) bhavat = Pratipadika.krdanta(bhu, Krt.Satf) Or a *taddhitanta*: .. testcode:: guru = Pratipadika.basic("guru") gaurava = Pratipadika.taddhitanta(guru, Taddhita.aR) These pratipadikas can likewise be used to create more complex forms: .. testcode:: prakriyas = v.derive(Pada.Subanta( pratipadika=bhavat, linga=Linga.Pum, vibhakti=Vibhakti.Prathama, vacana=Vacana.Dvi, )) assert prakriyas[0].text == 'BavantO' Working with data files ----------------------- `vidyut.prakriya` is more interesting when used with the side data provided in Vidyut's official data download. We expose this data through the :class:`Data` object, whose main methods are :meth:`~Data.load_dhatu_entries` and :meth:`~Data.load_sutras`. :meth:`~Data.load_dhatu_entries` loads all dhatus from the Dhatupatha along with their meanings:: from vidyut.prakriya import * data = Data("/path/to/dhatupatha.tsv") dhatus = [e.dhatu for e in data.load_dhatu_entries()] v = Vyakarana(log_steps=False) for dhatu in dhatus: prakriyas = v.derive(Pada.Subanta( dhatu=dhatu, prayoga=Prayoga.Kartari, lakara=Lakara.Lat, purusha=Purusha.Prathama, vacana=Vacana.Eka, )) for prakriya in prakriyas: print(prakriya.text) The Dhatupatha we provide is essentially identical to the one used on `ashtadhyayi.com`_. .. _ashtadhyayi.com: https://ashtadhyayi.com :meth:`~Data.load_sutras`, meanwhile, loads all sutras used as part of a derivation: .. testsetup:: class MockData: def load_sutras(self): assert hasattr(Data, "load_sutras") return [Sutra(source=Source.Ashtadhyayi, code="1.1.1", text="vfdDirAdEc")] data = MockData() .. testcode:: sutras = data.load_sutras() ashtadhyayi = [s for s in sutras if s.source == Source.Ashtadhyayi] assert ashtadhyayi[0].source == Source.Ashtadhyayi assert ashtadhyayi[0].code == "1.1.1" assert ashtadhyayi[0].text == "vfdDirAdEc" :meth:`~Data.load_sutras` includes data from the Ashtadhyayi, the Unadipatha, ganasutras from the Dhatupatha, various vārttikas, and other smaller sources. Recipes ------- This section contains various recipes that show how to use `vidyut.prakriya` for different tasks. Generate a single prakriya with its sutras ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :: from vidyut.prakriya import * data = Data("/path/to/prakriya/data") code_to_sutra = {(s.source, s.code): s.text for s in data.load_sutras()} v = Vyakarana() prakriyas = v.derive(Pada.Tinanta( dhatu=Dhatu.mula(aupadeshika="BU", gana=Gana.Bhvadi), prayoga=Prayoga.Kartari, lakara=Lakara.Lat, purusha=Purusha.Prathama, vacana=Vacana.Eka, )) for prakriya in prakriyas: print(prakriya.text) print('===================') for step in prakriya.history: result = ' + '.join(step.result) key = (step.source, step.code) # WARNING: use `get` to avoid a KeyError. While 99.9% of sutras are defined in # `code_to_sutras`, there might still be some sutras we have missed. sutra = code_to_sutra.get(key, "(missing)") print("{:<10}: {:<15} {}".format(step.code, result, sutra)) Output: .. code-block:: text Bavati =================== 1.3.1 : BU BUvAdayo DAtavaH 3.2.123 : BU + la~w vartamAne law 1.3.2 : BU + la~w upadeSe'janunAsika it 1.3.3 : BU + la~w halantyam 1.3.9 : BU + l tasya lopaH 1.3.78 : BU + l SezAt kartari parasmEpadam 3.4.78 : BU + tip tiptasJisipTasTamibvasmas tAtAMJaTAsATAMDvamiqvahimahiN 1.3.3 : BU + tip halantyam 1.3.9 : BU + ti tasya lopaH 3.4.113 : BU + ti tiNSitsArvaDAtukam 3.1.68 : BU + Sap + ti kartari Sap 1.3.3 : BU + Sap + ti halantyam 1.3.8 : BU + Sap + ti laSakvatadDite 1.3.9 : BU + a + ti tasya lopaH 3.4.113 : BU + a + ti tiNSitsArvaDAtukam 1.4.13 : BU + a + ti yasmAt pratyayaviDistadAdi pratyaye'Ngam 7.3.84 : Bo + a + ti sArvaDAtukArDaDAtukayoH 1.4.14 : Bo + a + ti suptiNantaM padam 6.1.78 : Bav + a + ti eco'yavAyAvaH 8.4.68 : Bav + a + ti a a Generate all tinantas for some dhatu and prayoga ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. testcode:: from vidyut.prakriya import * v = Vyakarana(log_steps=False) bhu = Dhatu.mula("BU", Gana.Bhvadi) for lakara in Lakara.choices(): for purusha in Purusha.choices(): for vacana in Vacana.choices(): prakriyas = v.derive(Pada.Tinanta( dhatu=bhu, prayoga=Prayoga.Kartari, lakara=lakara, purusha=purusha, vacana=vacana, )) for p in prakriyas: print(p.text) .. testoutput:: :hide: :options: +IGNORE_RESULT Generate tinantas from the Dhatupatha ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: python from vidyut.prakriya import * data = Data("/path/to/prakriya") dhatus = [e.dhatu for e in data.load_dhatu_entries()] v = Vyakarana(log_steps=False) prayoga = Prayoga.Kartari for dhatu in dhatus: for lakara in Lakara.choices(): for purusha in Purusha.choices(): for vacana in Vacana.choices(): prakriyas = v.derive(Pada.Tinanta( dhatu=dhatu, prayoga=prayoga, lakara=lakara, purusha=purusha, vacana=vacana, )) for p in prakriyas: print(p.text) Generate all subantas for some pratipadika ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. testcode:: from vidyut.prakriya import * v = Vyakarana(log_steps=False) nara = Pratipadika.basic("nara") for vibhakti in Vibhakti.choices(): for vacana in Vacana.choices(): prakriyas = v.derive(Pada.Subanta( pratipadika=nara, linga=Linga.Pum, vibhakti=vibhakti, vacana=vacana, )) for p in prakriyas: print(vibhakti, vacana, p.text) .. testoutput:: :hide: :options: +IGNORE_RESULT Generate all krdantas for some dhatu ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. testcode:: from vidyut.prakriya import * v = Vyakarana() bhu = Dhatu.mula("BU", Gana.Bhvadi) for krt in Krt.choices(): anga = Pratipadika.krdanta(bhu, krt) prakriyas = v.derive(anga) for p in prakriyas: print(krt, p.text) else: print(f"- (no results for BU + {krt})") .. testoutput:: :hide: :options: +IGNORE_RESULT Generate all taddhitantas for some pratipadika ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. testcode:: from vidyut.prakriya import * v = Vyakarana() guru = Pratipadika.basic("guru") for taddhita in Taddhita.choices(): anga = Pratipadika.taddhitanta(guru, taddhita) prakriyas = v.derive(anga) for p in prakriyas: print(taddhita, p.text) else: print(f"- (no results for guru + {taddhita})") .. testoutput:: :hide: :options: +IGNORE_RESULT Find all rules used by a dhatu's tinantas ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. testcode:: from vidyut.prakriya import * v = Vyakarana() bhu = Dhatu.mula("BU", Gana.Bhvadi) rules = set() for prayoga in Prayoga.choices(): for lakara in Lakara.choices(): for purusha in Purusha.choices(): for vacana in Vacana.choices(): prakriyas = v.derive(Pada.Tinanta( dhatu=bhu, prayoga=prayoga, lakara=lakara, purusha=purusha, vacana=vacana, )) for p in prakriyas: for step in p.history: rules.add(step.code) .. testoutput:: :hide: :options: +IGNORE_RESULT