experta icon indicating copy to clipboard operation
experta copied to clipboard

Use engine as function or generator

Open nilp0inter opened this issue 6 years ago • 5 comments

Introduce a new engine feature to allow returning values from the RHS.

This has been requested many times, last time here: https://github.com/buguroo/pyknow/issues/47

nilp0inter avatar Aug 13 '19 09:08 nilp0inter

@nilp0inter Happy to offer some help if I can :)

8ball030 avatar Aug 16 '19 14:08 8ball030

My hacky workaround is not optimal!

8ball030 avatar Aug 16 '19 14:08 8ball030

Hi! Thank you for the help, it is very welcome.

As you mentioned in your original post, this can be accomplished in several ways. I think the best way to decide is to enumerate the options to better compare them (and maybe code a proof of concept to test them)

For example it can be done by:

  1. Add a method in the KnowledgeEngine to store the return value internally and then return it with the run() call return value.
  2. A subclass of KnowledgeEngine as you mentioned.
  3. Convert run() into a generator and let the RHSs of the engine yield/return values to be yielded from the run(). This is similar to (1).
  4. Use an special exception to raise the value to the run() method, capture it there and return it.
  5. Don't use the return value of run() but a special attribute to store the value.
  6. Create a wrapper function to reset and run the given knowledge engine combined with (4) or (5)

I'll be coding some of this ideas in Gists and linking them here. You can do the same if you think of any alternatives not mentioned here.

nilp0inter avatar Aug 19 '19 09:08 nilp0inter

This is the first proof of concept. Implementing ideas from (3). It has some drawbacks, though:

  1. You can mix yield/return RHS with unexpected results from the user perspective.
  2. The user have to decide if she wants to consume a generator or not.
  3. Can't return None.

Note: The method _run_activations is a copy of the original run() method with some minor changes. The amount of modifications in the library would be pretty small.

nilp0inter avatar Aug 19 '19 19:08 nilp0inter

Hi! I need some help, I've been reading this post for a while but I don't know how to implement this in my code.

I need to return resultadoPublicaciones value in order to use it in other method, but I don't know how to do it. Could someone help me?

class EvaluacionPublicacionesCE(KnowledgeEngine):

@Rule(Publicaciones(publicaciones = P(lambda x: x >= 12)))
def publicaciones_max(self):
    print('resultado = 35')
@Rule(Publicaciones(publicaciones = P(lambda x: 8 <= x <= 11)))
def publicaciones_med(self):
    publicaciones = self.facts[1]['publicaciones']
    factor = self.facts[2]['factor']
    medio = self.facts[3]['medio']
    cuartil = self.facts[4]['cuartil']
    numeroAutores = self.facts[5]['numeroAutores']
    tiempoDesdeLectura = self.facts[6]['tiempoDesdeLectura']
    continua = self.facts[7]['continua']
    resultadoPublicaciones = 16
    
    cuartiles12 = 0
    cuartiles34 = 0
    for i in cuartil:
        if i == "Q1" or i == "Q2":
            cuartiles12 += 1
        elif i =="Q3" or i == "Q4":
            cuartiles34 += 1
    
    if cuartiles12 >= 8:
        resultadoPublicaciones = resultadoPublicaciones + 6
    elif (4 <= cuartiles12 <= 7):
        resultadoPublicaciones = resultadoPublicaciones + 4
    elif (2 <= cuartiles12 < 4):
        resultadoPublicaciones = resultadoPublicaciones + 2
    elif (cuartiles12 == 1):
        resultadoPublicaciones = resultadoPublicaciones + 1
    
    if cuartiles34 >= 8: 
        resultadoPublicaciones = resultadoPublicaciones + 3
    elif (4 <= cuartiles34 <= 7):
        resultadoPublicaciones = resultadoPublicaciones + 2
    elif (2 <= cuartiles34 < 4):
        resultadoPublicaciones = resultadoPublicaciones + 1
    
    
    factorAlto = 0
    factorMedio = 0
    factorBajo = 0
    for i in factor:
        if i == "alto":
            factorAlto += 1
        elif i == "medio":
            factorMedio += 1
    
    if factorAlto > 5:
        resultadoPublicaciones = resultadoPublicaciones + 3
    elif (3 <= factorAlto <= 5):
        resultadoPublicaciones = resultadoPublicaciones + 2
    
    if factorMedio >= 6:
        resultadoPublicaciones = resultadoPublicaciones + 1

    if ((factorMedio < 6) and (factorAlto < 3)):
        if ((factorMedio + factorAlto) > 3):
            resultadoPublicaciones = resultadoPublicaciones + 1
    
    cuentaContinua = 0
    for i in continua:
        if i == "Si":
            cuentaContinua += 1
        else:
            continue
    if (cuentaContinua > 7):
        resultadoPublicaciones = resultadoPublicaciones + 3
    elif (5 < cuentaContinua <= 7):
        resultadoPublicaciones = resultadoPublicaciones + 2
    elif (2 <= cuentaContinua <= 5):
        resultadoPublicaciones = resultadoPublicaciones + 1
    
    print("resultado = " + str(resultadoPublicaciones))

@Rule(Publicaciones(publicaciones = P(lambda x: 0 < x <= 7)))
def publicaciones_min(self):
        
    publicaciones = self.facts[1]['publicaciones']
    factor = self.facts[2]['factor']
    medio = self.facts[3]['medio']
    cuartil = self.facts[4]['cuartil']
    numeroAutores = self.facts[5]['numeroAutores']
    tiempoDesdeLectura = self.facts[6]['tiempoDesdeLectura']
    continua = self.facts[7]['continua']

    resultadoPublicaciones = 2 * publicaciones
    if (resultadoPublicaciones > 12):
        resultadoPublicaciones = 12

    cuartiles12 = 0
    cuartiles34 = 0
    for i in cuartil:
        if i == 'Q1' or i == 'Q2':
            cuartiles12 += 1
        elif i == 'Q3' or i =='Q4':
            cuartiles34 += 1
    
    if cuartiles12 >= 5:
        resultadoPublicaciones = resultadoPublicaciones + 3
    elif (2 <= cuartiles12 <= 4):
        resultadoPublicaciones = resultadoPublicaciones + 2
    elif cuartiles12 == 1:
        resultadoPublicaciones = resulresultadoPublicacionestado + 1

    if cuartiles34 >= 5:
        resultadoPublicaciones = resultadoPublicaciones + 2
    elif (2 <= cuartiles34 <= 4):
        resultadoPublicaciones = resultadoPublicaciones + 1 
    
    factorAlto = 0
    factorMedio = 0
    for i in factor:
        if i == "alto":
            factorAlto += 1
        elif i == "medio":
            factorMedio += 1
    if factorAlto >= 4:
        resultadoPublicaciones = resultadoPublicaciones + 2
    elif (2 <= factorAlto <= 3):
        resultadoPublicaciones = resultadoPublicaciones + 1
    
    if factorMedio >= 4:
        resultadoPublicaciones = resultadoPublicaciones + 1
    
    if ((factorAlto == 1) and (factorMedio < 4)):
        if ((factorAlto + factorMedio) >= 3):
            resultadoPublicaciones = resultadoPublicaciones + 1
    
    cuentaContinua = 0
    for i in continua:
        if i == "Si":
            cuentaContinua += 1
        else:
            continue
    if cuentaContinua >= 4:
        resultadoPublicaciones = resultadoPublicaciones + 2
    elif (2 <= cuentaContinua <= 3):
        resultadoPublicaciones = resultadoPublicaciones + 1

    print('resultado = ' + str(resultadoPublicaciones))

IMolini avatar Apr 06 '20 09:04 IMolini