7

I am trying to read in a Fuzzy plain text rule and pass the parameters to a SciKit-Fuzzy function call to create fuzzy rules. For example, if I read in this text rule:

IF service IS poor OR food IS rancid THEN tip IS cheap

Then the function call will be:

ctrl.Rule(service ['poor'] | food ['rancid '], tip ['cheap'])

If text rule is:

IF service IS good THEN tip IS average; 

Then the function call will be:

ctrl.Rule(service ['good '] , tip ['average'])

Since each rule can have unlimited number of input variables, e.g. the user can also say:

IF service IS good AND food IS good AND mood IS happy THEN tip IS high

which contains 3 inputs variables service['good'],food['good'],and mood['happy'], and 1 output variable tip['high']. I can't think of a way to automatically read in the text rule and convert it to a function call, do you have any idea or suggestion to achieve this goal? Any help will be appreciated. Thanks.

GHWHG
  • 73
  • 5
  • Does this answer your question? [Mini-languages in Python](https://stackoverflow.com/questions/1547782/mini-languages-in-python) – Samwise Aug 16 '20 at 20:57

2 Answers2

4

In python, we can pass an unknown amount of arguments into the function using asterisk notation.

Let's try to create a function sum_up() with an unknown number of arguments.

def sum_up(*args):
    s = 0
    for i in args:
        s += i
    return s

As you see, an argument with an asterisk before will collect all arguments given to this function inside a tuple called args.

We can call this function that way:

sum_up(5, 4, 6)  # Gives 15

But if we want to sum up elements of a list and we need to pass it into the function as arguments...

We can try the following:

l = [5, 4, 6]
sum_up(l)

This won't give an effect we need: args of sum_up will look like ([5, 4, 6],). To do what we want, we need to put an asterisk before the argument we're passing:

sum_up(*l)  # Becomes sum_up(5, 4, 6)

All you need to do is collect all arguments you want to pass in a list and then put an asterisk before this list passed as an argument inside a call:

args = [service ['good '] , tip ['average']]
ctrl.Rule(*args)
10 Rep
  • 2,217
  • 7
  • 19
  • 33
AlanTheKnight
  • 76
  • 1
  • 7
0

You could try something like this:

string_input = "IF service IS poor OR food IS rancid THEN tip IS cheap"
string_input = string_input.replace(" THEN ", '"], ').replace(' IS ', '["').strip("IF ").replace(" OR ", '"] | ') +'"]'
eval('ctrl.Rule({})'.format(string_input))

But be warned you need to be very very careful with eval. It is a security risk because user can execute code this way!!! Before using this you might to do research on how to prevent this security issue.

10 Rep
  • 2,217
  • 7
  • 19
  • 33
Andreas
  • 8,694
  • 3
  • 14
  • 38
  • This `eval()` function can solve my problem perfectly. Thanks – GHWHG Aug 17 '20 at 18:42
  • Glad I could help, but as mentioned be aware of potential safety issues if you are considering that user will write that input! Happy Coding! – Andreas Aug 17 '20 at 18:47