Feat: Rewrite doc for calculus and random generation

This commit is contained in:
Bertrand Benjamin 2019-07-01 11:24:44 +02:00
parent b5f45c97d0
commit 116c1fac29
1 changed files with 122 additions and 186 deletions

View File

@ -10,101 +10,154 @@ Une de mes motivations principales pour développer cet outil est de pouvoir cr
Calculs et explications
-----------------------
Les calculs peuvent être déclarés à partir d'une chaine de caractères.
.. code-block:: python
>>> from pymath import Expression
>>> priorite = Expression.from_str("2 + 3*(4+5*6)")
>>> print(priorite)
2 + 3(4 + 5 \times 6)
>>> ajout_fractions = Expression.from_str("2 / 5 + 2 / 3")
>>> print(ajout_fractions)
\frac{ 2 }{ 5 } + \frac{ 2 }{ 3 }
>>> doubledev = Expression.from_str("(x+2)(3x-4)")
>>> print(doubledev)
(x+2)(3x-4)
La simplification des expressions est basée sur la méthode **.simplify()**
.. code-block:: python
>>> from pymath import Expression
>>> priorite = Expression.from_str("2 + 3*(4+5*6)")
>>> resultat = priorite.simplify()
>>> print(resultat)
104
>>> ajout_fractions = Expression.from_str("2 / 5 + 2 / 3")
>>> resultat = ajout_fractions.simplify()
>>> print(resultat)
\frac{ 16 }{ 15 }
>>> doubledev = Expression.from_str("(x+2)(3x-4)")
>>> resultat = doubledev.simplify()
>>> print(resultat)
3x^2 - 8 + 2x
Pour avoir l'explication et le détail des calculs, il va falloir faire une boucle sur les étapes générées par la méthode **.explain()**
.. code-block:: python
>>> from pymath import Expression
>>> priorite = Expression.from_str("2 + 3*(4+5*6)")
>>> resultat = priorite.simplify()
>>> for s in resultat.explain():
... print(s)
2 + 3(4 + 5 \times 6)
2 + 3(4 + 30)
2 + 3 \times 34
2 + 102
104
>>> ajout_fractions = Expression.from_str("2 / 5 + 2 / 3")
>>> resultat = ajout_fractions.simplify()
>>> for s in resultat.explain():
... print(s)
\frac{2}{5} + \frac{2}{3}
\frac{2 \times 3}{5 \times 3} + \frac{2 \times 5}{3 \times 5}
\frac{6}{15} + \frac{10}{15}
\frac{6 + 10}{15}
\frac{16}{15}
>>> doubledev = Expression.from_str("(x+2)(3x-4)")
>>> resultat = doubledev.simplify()
>>> for s in resultat.explain():
... print(s)
(x + 2)(3x - 4)
x \times 3x + x \times - 4 + 2 \times 3x + 2 \times - 4
2 \times 3 \times x - 8 + 3x^2 - 4x
6x - 8 + 3x^2 - 4x
3x^2 + 6x - 4x - 8
3x^2 + (6 - 4) \times x - 8
3x^2 - 8 + 2x
Types de données manipulables
-----------------------------
Génération aléatoire d'expressions
----------------------------------
Autres
------
- *Calculer comme un collégien*: Pour faire de la correction automatisé
d'exercice, un logiciel de calcul formel ne suffit pas. Si les étapes
de calculs ne sont pas présentes, l'élève ne pourra pas analyser ses
erreurs ou s'inspirer de la correction.
Les expressions peuvent être générées aléatoirement avec la méthode **.random()**. Pour cela, on va utiliser un *template* ou modèle dans lequel, les valeurs à générées seront entre accolades {}.
.. code-block:: python
>>> from pymath import Expression
>>> ajout_fractions = Expression("2 / 5 + 2 / 3")
>>> resultat = ajout_fractions.simplify()
>>> print(resultat)
\frac{ 16 }{ 15 }
>>> for i in resultat.explain():
... print(i)
...
\frac{ 2 }{ 5 } + \frac{ 2 }{ 3 }
\frac{ 2 \times 3 }{ 5 \times 3 } + \frac{ 2 \times 5 }{ 3 \times 5 }
\frac{ 6 }{ 15 } + \frac{ 10 }{ 15 }
\frac{ 6 + 10 }{ 15 }
\frac{ 16 }{ 15 }
>>> priorite = Expression.random("{a} + {b} * 5")
>>> print(priorite)
2 + 3 \times 5
>>> priorite = Expression.random("{a} + {b} * 5")
>>> print(priorite)
9 - 3 \times 5
- *Créer des exercices aléatoirement*: Pour faire des devoirs
personnels, des fiches de révisions ou des exercices en classe, un
générateur d'expressions est inclus.
Les valeurs générées peuvent dépendre les unes des autres.
.. code-block:: python
>>> from pymath import Expression
>>> ajout_fraction = Expression.random("{a} + {b} / {c}")
>>> print(ajout_fraction)
2 + \frac{ 3 }{ 5 }
>>> priorite = Expression.random("{a} + {2*a} * 5")
>>> print(priorite)
-1 - 2 \times 5
>>> add_frac = Expression.random("{a} / {b} + {c} / {b*2}")
>>> print(add_frac)
\frac{- 2}{- 2} + \frac{2}{- 4}
- *Gérer différents type de données*: Pour le moment, Mapytex est
capable de gérer les entiers naturels, les rationnels (sous forme de
fractions) et les polynômes. L'utilisation des nombres à virgules et
des racines devraient être ajoutés dans les prochaines versions.
Par défaut, les valeurs sont choisies aléatoirement entre -10 et 10 en évitant 0. On peut modifier ce comportement au niveau de toutes les variables en paramétrant *rejected* (valeurs à éviter) et *min_max* (bornes où choisir les valeurs). On peut aussi définir ces paramètres pour chaque variables avec *variables_scope*.
.. code-block:: python
>>> from pymath import Fraction
>>> une_fraction = Fraction(1,2)
>>> print(une_fraction)
1 / 2
>>> from pymath import Polynom
>>> un_polynom = Polynom([1,2,3])
>>> print(un_polynom)
3 x^{ 2 } + 2 x + 1
>>> from pymath import Expression
>>> priorite = Expression.random("{a} + {2*a} * 5", rejected=[1, 2], min_max=(0, 3))
>>> print(priorite)
0 + 0 \times 5
>>> priorite = Expression.random("{a} + {b} * 5",
rejected=[1, 2], min_max=(0, 3),
variables_scope={'a':{'min_max':(2, 5)}}
)
>>> print(priorite)
5 + 3 \times 5
- *Afficher avec deux types de rendus*: Un en mode texte pour
l'affichage dans une console. Un deuxième spécialement pour écrire
des documents latex.
Enfin, il est possible de définir des conditions sur les valeurs générées en paramétrant *conditions*.
.. code-block:: python
>>> from pymath import Expression
>>> ajout_fractions = Expression("2 / 5 + 2 / 3")
>>> for i in ajout_fractions.simpliy().explain():
... print(i)
...
\frac{ 2 }{ 5 } + \frac{ 2 }{ 3 }
\frac{ 2 \times 3 }{ 5 \times 3 } + \frac{ 2 \times 5 }{ 3 \times 5 }
\frac{ 6 }{ 15 } + \frac{ 10 }{ 15 }
\frac{ 6 + 10 }{ 15 }
\frac{ 16 }{ 15 }
>>> from pymath import txt
>>> with Expression.tmp_render(txt):
... for i in ajout_fractions.simpliy().explain():
... print(i)
...
2 / 5 + 2 / 3
( 2 * 3 ) / ( 5 * 3 ) + ( 2 * 5 ) / ( 3 * 5 )
6 / 15 + 10 / 15
( 6 + 10 ) / 15
16 / 15
>>> from pymath import Expression
>>> add_frac = Expression.random("{a} / {b} + {c} / {d}",
conditions = ['b%d==0', 'a!=b', 'c!=d']
)
>>> print(add_frac)
\frac{10}{4} + \farc{- 7}{2}
Le rendu latex permet ensuite d'être directement compiler et par exemple d'avoir le rendu suivant
Par contre, rien n'est fait qui permettrait de savoir si un ensemble de conditions permet de générée les valeurs demandées. Comme la génération des variables se fait avec la méthode par rejet, si les conditions ne permettent pas générer des valeurs convenables, le programme moulinera dans le vide...
.. math::
:nowrap:
Il est prévu d'ajouter l'option *suffle* qui permettra de mélanger les termes des expressions.
\frac{ 2 }{ 5 } + \frac{ 2 }{ 3 } \\
\frac{ 2 \times 3 }{ 5 \times 3 } + \frac{ 2 \times 5 }{ 3 \times 5 } \\
\frac{ 6 }{ 15 } + \frac{ 10 }{ 15 } \\
\frac{ 6 + 10 }{ 15 } \\
\frac{ 16 }{ 15 }
-----------------------------------
@ -113,123 +166,6 @@ d'exercices et leurs correction. Il a pour but d'être le plus simple
possible d'utilisation afin que tout le monde avec un minimum de
connaissance en programmation puisse créer librement des exercices.
Calculer comme un collégien.
----------------------------
Actuellement le module principal pour faire calculer python comme un
collégien est *pymath.expression*.
.. code-block:: python
>>> from pymath import Expression
Déclarer une expression
~~~~~~~~~~~~~~~~~~~~~~~
Un expression peut être initialisée de deux façons différentes: à partir
d'une chaine de caractères ou à partir de la liste des termes (en
postfix - cette méthode est essentiellement utilisée pour programmer les
modules, elle ne sera pas détaillée ici).
.. code-block:: python
>>> un_calcul = Expression("1 + 2 * 3")
>>> print(un_calcul)
1 + 2 \times 3
>>> ajout_fractions = Expression("2 / 5 + 2 / 3")
>>> print(ajout_fractions)
\frac{ 2 }{ 5 } + \frac{ 2 }{ 3 }
Et si l'on souhaite un rendu plus adapté à la console:
.. code-block:: python
>>> from pymath import txt
>>> Expression.set_render(txt)
>>> print(un_calcul)
1 + 2 * 3
>>> print(ajout_fractions)
2 / 5 + 2 / 3
Simplification des expressions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Une fois les expressions créées, elles peuvent se réduire en expliquant
les étapes et en respectant les règles de priorités. Ces étapes de
calcul sont stockés dans l'objet résultat du calcul et sont accéssibles
à travers la méthode *explain*. Les exemples suivants seront données
avec un rendu texte.
.. code-block:: python
>>> from pymath import Expression
>>> from pymath import txt
>>> Expression.set_render(txt)
>>> exp = Expression("1 + 2 * 3")
>>> exp_simplifiee = exp.simplify()
>>> print(exp_simplifiee)
7
>>> for i in exp_simplifiee.explain():
... print(i)
...
1 + 2 * 3
1 + 6
7
Les opérations autorisées sont les opérations "classique": + - * / ^.
L'utilisation des parenthèses est aussi gérée.
.. code-block:: python
>>> exp = Expression("1 + 2 / 5")
>>> for i in exp.simplify().explain():
... print(i)
...
1 + 2 / 5
( 1 * 5 ) / ( 1 * 5 ) + ( 2 * 1 ) / ( 5 * 1 )
( 5 + 2 ) / 5
7 / 5
>>> exp = Expression("(2 + 4)(3 - 4 * 2)")
>>> for i in exp.simplify().explain():
... print(i)
...
( 2 + 4 ) ( 3 - ( 4 * 2 ) )
6 * ( 3 - 8 )
6 * ( -5 )
-30
Type de variables et opérations
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
On peut vouloir créer directement des objets (fractions ou polynômes)
sans passer par le module expression (voir `fraction <fraction>`__
et `polynom <polynom>`__ pour plus de details)
.. code-block:: python
>>> from pymath import Fraction
>>> fraction1 = Fraction(1,2)
>>> fraction2 = Fraction(2,3)
>>> print(fraction1)
1 / 2
>>> from pymath import Polynom
>>> p = Polynom([1,2,3])
>>> print(p)
3 x ^ 2 + 2 x + 1
>>> q = Polynom([0,0,1])
x ^ 2
On peut effectuer des opérations entre les Expressions.
.. code-block:: python
>>> fraction_expression = Expression("2 / 3")
>>> autre_fraction_expression = Expression("4 / 9")
>>> print(fraction_expression + autre_fraction_expression)
2 / 3 + 4 / 9
On remarque qu'un opération sur des expressions, ne fait pas de calculs.
Elle ne fait que "concaténer" les listes des tokens.