Mapytex/pymath/calculus/random_expression.py

189 lines
5.2 KiB
Python
Raw Normal View History

2014-01-15 22:18:55 +00:00
#!/usr/bin/env python
# encoding: utf-8
from random import randint
import re
2014-11-23 09:45:13 +00:00
import pyparsing
from .generic import flatten_list
2014-01-15 22:18:55 +00:00
from .arithmetic import gcd
2016-02-13 04:04:08 +00:00
def random_str(form, conditions=[], val_min=-10, val_max=10):
2014-12-27 15:32:44 +00:00
""" Create a random string using RdExpression class """
random_str_generator = RdExpression(form, conditions)
return random_str_generator(val_min, val_max)
2016-02-13 04:04:08 +00:00
2014-01-15 22:18:55 +00:00
class RdExpression(object):
"""
A generator of random expression builder
"""
2016-02-13 04:04:08 +00:00
def __init__(self, form, conditions=[]):
2014-01-15 22:18:55 +00:00
"""Initiate the generator
:param form: the form of the expression (/!\ variables need to be in brackets {})
:param conditions: condition on variables (/!\ variables need to be in brackets {})
"""
2016-01-17 14:51:12 +00:00
self._form = self.mod_underscores(form)
2014-01-15 22:18:55 +00:00
self._conditions = conditions
2014-01-15 22:18:55 +00:00
self._letters = self.get_letters()
self._gene_varia = {}
2014-12-19 16:17:25 +00:00
self._gene_2replaced = {}
2014-01-17 11:28:59 +00:00
def get_2replaced(self):
"""Get elements of self._form which will have to be replaced
:returns: set for elements which have to be replaced
"""
2016-02-13 04:04:08 +00:00
# pattern = "\{(.*?)\}" #select inside {} non greedy way
2014-11-23 09:45:13 +00:00
#varia_form = re.findall(pattern, self._form)
2014-01-17 11:28:59 +00:00
2014-11-23 09:45:13 +00:00
# TODO: Bug with varia with spaces |dim. nov. 23 10:44:34 CET 2014
2016-02-13 04:04:08 +00:00
varia_form = flatten_list([eval(str(i[0])) for i in pyparsing.nestedExpr(
'{', '}').searchString(self._form)])
varia_form = set(varia_form)
varia_cond = set()
for c in self._conditions:
2016-02-13 04:04:08 +00:00
c_varia_cond = flatten_list(
[eval(str(i[0])) for i in pyparsing.nestedExpr('{', '}').searchString(c)])
2014-11-23 09:45:13 +00:00
varia_cond = varia_cond | set(c_varia_cond)
2016-02-13 03:29:26 +00:00
self._2replaced = varia_cond | varia_form
return self._2replaced
2016-02-13 03:29:26 +00:00
2014-01-15 22:18:55 +00:00
def get_letters(self):
"""Find letters in the form
:returns: list of letters
"""
2014-01-17 11:28:59 +00:00
v2replaced = self.get_2replaced()
varia = set()
pattern = "([a-zA-Z]+)"
for v in v2replaced:
lvar = set(re.findall(pattern, v))
varia = varia | lvar
return varia
2016-01-17 14:51:12 +00:00
def mod_underscores(self, form):
""" Transform underscores of string to {...} forme with capital letters
:param form: the form string with _ to replace
:returns: the string with _ replaced
"""
i = 64
new_form = form
while "_" in new_form:
i += 1
2016-02-13 04:04:08 +00:00
new_form = new_form.replace("_", "{" + chr(i) + "}", 1)
2016-01-17 14:51:12 +00:00
return new_form
2014-01-15 22:18:55 +00:00
2016-02-13 04:04:08 +00:00
def __call__(self, val_min=-10, val_max=10):
2014-01-15 22:18:55 +00:00
"""RdExpression once it is initiate act like a function which create random expressions.
:param val_min: minimum value random generation
:param val_max: maximum value random generation
2016-02-13 03:29:26 +00:00
:returns: an formated random expression
"""
return self.raw_str(val_min, val_max)
2016-02-13 04:04:08 +00:00
def raw_str(self, val_min=-10, val_max=10):
2014-01-30 08:26:48 +00:00
"""Return raw string (don't use Expression for rendering or parsing)
:param val_min: minimum value random generation
:param val_max: maximum value random generation
:returns: an random Expression object
2014-01-15 22:18:55 +00:00
"""
self.gene_varia(val_min, val_max)
while not(self.val_conditions()):
self.gene_varia(val_min, val_max)
exp = self._form.format(**self._gene_2replaced)
2014-01-30 08:26:48 +00:00
return exp
2016-02-13 04:04:08 +00:00
def gene_varia(self, val_min=-10, val_max=10):
"""Randomly generates variables/letters
Varia can't be equal to 0
2014-01-15 22:18:55 +00:00
"""
for l in self._letters:
self._gene_varia[l] = randint(val_min, val_max)
2014-01-28 22:21:37 +00:00
while self._gene_varia[l] == 0:
self._gene_varia[l] = randint(val_min, val_max)
2014-01-15 22:18:55 +00:00
2014-01-17 11:28:59 +00:00
for e in self._2replaced:
self._gene_2replaced[e] = eval(e, globals(), self._gene_varia)
2014-01-15 22:18:55 +00:00
def val_conditions(self):
"""Tells whether or not conditions are validates
:returns: boolean
"""
2014-01-17 10:19:28 +00:00
if self._conditions != []:
2016-02-13 04:04:08 +00:00
return eval(
" and ".join(
self._conditions).format(
**self._gene_2replaced))
2014-01-17 10:19:28 +00:00
else:
return True
2014-01-15 22:18:55 +00:00
2016-02-13 04:04:08 +00:00
2014-01-17 11:28:59 +00:00
def desc_rdExp(rdExp):
print("--------------------")
2016-02-13 04:04:08 +00:00
print("form: ", rdExp._form)
print("Conditions: ", rdExp._conditions)
2014-01-17 11:28:59 +00:00
print("Letters: ", rdExp._letters)
print("2replaced: ", rdExp._2replaced)
print("Call : ", rdExp())
2016-02-13 04:04:08 +00:00
print("type: ", type(rdExp()))
2014-01-17 11:28:59 +00:00
print("Gene varia: ", rdExp._gene_varia)
print("Gene 2replaced: ", rdExp._gene_2replaced)
print('')
2014-01-15 22:18:55 +00:00
if __name__ == '__main__':
2014-12-27 15:32:44 +00:00
form = "({a};{b})"
cond = []
print(random_str(form, cond))
form = "{a+a*10}*4 + {a} + 2*{b}"
2016-02-13 04:04:08 +00:00
cond = [
"{a} + {b} in [1, 2, 3, 4, 5]",
"abs({a}) not in [1]",
"{b} not in [1]",
"gcd({a},{b}) == 1"]
2014-12-27 15:32:44 +00:00
print(random_str(form, cond))
2014-12-03 14:52:08 +00:00
form = "{a+a*10}*4 + {a} + 2*{b}"
2016-02-13 04:04:08 +00:00
cond = [
"{a-b} + {b} in list(range(20))",
"abs({a}) not in [1]",
"{b} not in [1]",
"gcd({a},{b}) == 1"]
2014-12-27 15:32:44 +00:00
print(random_str(form, cond))
2014-01-15 22:18:55 +00:00
2014-12-03 14:52:08 +00:00
import doctest
doctest.testmod()
2014-01-15 22:18:55 +00:00
# -----------------------------
# Reglages pour 'vim'
# vim:set autoindent expandtab tabstop=4 shiftwidth=4:
2016-02-13 03:29:26 +00:00
# cursor: 16 del