java 如何确定要计算的逻辑表达式最小值

java how to determine logical expression minimum values to evauate

我有一个表达式(例子)

(value1<15 AND value2>25) OR ((value3>0 and vaue4<5) OR (value5<6 and value7>8))

问题是值 1-7 是对外部服务的调用,这很昂贵。而且我们需要降低成本,因此我们需要进行最少次数的调用来评估此表达式。例如,如果我们有

(value1<15 AND value2>25)

评估为真,我们不需要评估正确的部分,所以我们不需要对外部服务进行无用的调用。如何在 java 中(或者可能只是在数学中)确定我们何时需要停止,并且进一步的评估不会产生任何影响?

更新

我有 5 个工作人员在 5 个不同的服务器上工作。

第一个工人:

    accept(expression)
    value1=calculateValue1()
    setValueToExpression(expression, 0, value1)
    enough=expression.checkIsItEnough()
    if(!enough){
      determineNextWorker(expression)
      sendToNExtWorker()
    }
    else return expression.evaluate()

第二个工人

    accept(expression)
    value2=calculateValue2()
    setValueToExpression(expression, 1, value2)
    enough=expression.checkIsItEnough()
    if(!enough){
     determineNextWorker(expression)
     sendToNextWorker()
    }
    else return expression.evaluate()

.......

正如我在评论中所说,我清楚地理解如果我们可以写

 evaluator.evaluate("(value1<5 and value2>6) or (value3>5 and value4>7)")

评价大家都知道,但是我因为很多原因没有这个能力。我也不能让它调用 value1()<15... 它是同步发生的,一个接一个,但甚至在不同的服务器上,有点离线评估。希望清楚

标准条件将以这种方式工作(短路),因为它只会在必要时评估表达式(如果 || 条件的第一部分为真,则不会评估其余部分):

if ((value1() < 15 && value2() > 25) || (value3() > 0 && vaue4() < 5) ...)

请注意,我已通过方法调用替换值 - 如果您预先计算每个值,当然它不会起作用...

示例:

  • 如果您的条件 value1() < 15 returns 为假,那么 value2() 将不会被调用
  • 如果第一个条件 value1() < 15 && value2() > 25 为真,则不会计算 value3()value4()

参考文献:

参见 JLS #15.23(强调我的):

The conditional-and operator && is like &, but evaluates its right-hand operand only if the value of its left-hand operand is true.

JLS #15.24类似:

The conditional-or operator || operator is like |, but evaluates its right-hand operand only if the value of its left-hand operand is false.

条件逻辑默认评估获得评估结果所需​​的最少条件。这不是 Java 特有的。这就是事情的运作方式。此外,分组括号在您的情况下是完全可选的。

根据您的用例,您可能希望在条件内推进最有可能为真的表达式。如果适用,也许可以考虑将某些结果缓存一定时间。

考虑正常的短路中间代码:

(value1<15 AND value2>25) OR ((value3>0 and value4<5) OR (value5<6 and value7>8))

if value1<15 goto value2_test else goto value3_test
value2_test:
if value2>25 goto success else goto value3_test
value3_test:
if value3>0 goto value4_test else goto value5_test
value4_test:
if value4<5 goto success else goto value5_test
value5_test:
if value5<6 goto value7_test else goto fail
value7_test:
if value7>8 goto success else goto fail

您可以通过用树表示表达式并传递由树表示的子表达式而不是整个表达式来大大简化事情。

例如,第一个工人将有两个子表达式:value2>25(value3>0 and value4<5) OR (value5<6 and value7>8)。 Select测试成功第一个,失败第二个

value2>25 worker 将有两个子表达式:"success" 和 (value3>0 and value4<5) OR (value5<6 and value7>8)

我不知道有任何库可以进行转换。如果它存在,它将在编译器构造的范围内。

我会非常努力地将其更改为一个工人可以组织工作,并简单地呼吁其他工人评估一个关系条件。

============================================= =========================== 更多细节,因为这似乎是 OP 正在寻找的答案:

术语:

  • "term" -> 比较或布尔变量,例如 value2>25
  • "product" -> 一些布尔表达式的 AND
  • "sum" -> 的或 一些布尔表达式。

只考虑乘积表达式,例如(value1<15 AND value2>25) OR ((value3>0 and value4<5) OR (value5<6 and value7>8))。这不是一个非常重要的限制。数字逻辑设计中使用的许多优化和简化都依赖于将任意逻辑表达式转换为乘积和。

在每一步,都会调用表达式前导项的工作器。根据表达式及其测试结果,它可以声明成功、声明失败或计算必须传递给 worker 的新表达式作为其前导任期。

   if this worker's condition is true
     if more terms in current product
       remove the leading term from the current product
       pass the new expression to the worker for the next term
    else
       declare success
  else
    if there is another product
      remove the leading product from the expression
      pass the new expression to the worker for the new leading product's leading term
    else
      declare failure