计算最小比较次数以确保1和仅1个值集

时间:2015-06-12 01:00:17

标签: optimization

这是一个软件限制的数学问题。

我被迫使用一个非常不灵活的工具,必须检查5个字段,每个字段可以是4个值之一(或未设置),以确保1个且仅1个字段设置为4个值中的任何一个。我无法直接比较两个字段,也无法将字段与null / 0 / unset进行比较。界面是一个可怕的基于Web的页面,只允许通过下拉菜单逐行输入极其简单的逻辑。

我可以使用的唯一伪逻辑如下:

if <field> <equals/not equals> <val> [<and/or>] 
if <field> <equals/not equals> <val> [<and/or>]
...

Where:
<field> is limited to field1, field2, ..., field5
<val> is limited to val1, val2, val3, val4
[<and/or>] is optional and would lead in to the following line

每一行&#34;如果&#34;声明是一个条目。我对后端知之甚少,但我从测试中得到的是&#34;和#34;似乎比&#34;或&#34;更高优先级。在行数上也有一个任意限制(我不知道它是什么),因此行越少越好。

这个&#34;规则集&#34;基本上是一个巨人&#34;如果&#34;将贯穿的语句,并最终返回true或false。真或假的操作是在此规则集之外确定的,因此我需要关注的唯一事情是确保1和只有1个字段具有值集的最小步骤数,以及计算有多少条目的方法给定具有Y值的X字段的单个规则集是必需的。我的目标是计算所有这些,所以我可以在数学上证明这样做是浪费时间,后端需要修复。我必须制作数十个这样的规则集,所有规则集都有不同数量的字段和值。

在我看来,使用这种逻辑的唯一方法是检查:

if field1 = val1 and 
if field2 = val1 or
if field1 = val1 and 
if field2 = val2 or
...
if field1 = val1 and
if field2 = val4 or
if field1 = val2 and
if field2 = val1 or
...

这是遍历所有字段和值以检查是否有任何两对字段都设置了某些值。当整个规则集返回true时,表示多个字段具有值集。我相信对此进行建模的等式如下:

((4*4*4)+(3*4*4)+(2*4*4)+(1*4*4))*2 = 320

这是在没有重复的情况下走的每对场,因为顺序无关紧要,(1&amp; 2,1和3,1和4,1和5,2和3,2和4,2和5,3和4) ,3&amp; 5,4&amp; 5),并且将每个字段的一个值与另一个4,4倍进行比较(每个可能值一个)。最后的* 2是因为这个数学假设将一个字段值与另一个字段值进行比较只需一步,而实际上需要两个步骤才能完成。

我不相信有更快的方法来完成所有的值,我相信我的数学是正确的。如果其中任何一个或错误,或者可以进行优化,请告诉我。

正如评论中提到的那样,这可以编写脚本,是的。但是,整个设置存在很多问题,我宁愿客观地证明它需要修复,而不是解决它。

1 个答案:

答案 0 :(得分:2)

我认为你的答案尽可能便宜。但是,在尝试计算逻辑的过程中,我发现我需要提出一个更标准的问题定义和你所面对的语言,所以我想把它包含在这里。它可能会有所帮助,所以我在答案之前把它包括在内。

考虑我是否将您收到的数据建模为网格:

        blank  val1  val2  val3  val4
       +-----------------------------+
field1 | X                           |
field2 |              X              |
field3 | X                           |
field4 | X                           |
field5 |                          X  | <--// error - 2 fields set
       +-----------------------------+

我们对此设置了解多少:

  • 没有行可以包含多个X,因为一个字段只能有一个值
  • 您的field = valuefield != value测试与查询主板上一个方格的状态相同。
  • 目标是验证所有字段都是空白的,除了其中一个字段。

现在您可以访问的语法非常重要。我们不只是在寻找位置,我们正在寻找用这种语法表达的最小规则来测试这些位置。我将从您的评论中假设语法是Sum of Products(SoP)形式,其中“和”优先于“或”,并且没有括号来创建嵌套表达式。

为了简洁起见,我将发明一种更短的语法,使用x13表示“字段1,val3是否有x”。这只会缩短编写时间,并且完全可以翻译成if field1 = val3。我们还使用!x13来表示if field1 != val3,这是基于C语言编程语言中!的典型含义。我将使用SoP表示法,x12*x23 + !x34表示:

if field1 = val2 <and>
if field2 = val3 <or>
if field3 != val4

这也有一个巨大的优势,现在使用典型的数学运算符优先级,所以我可以避免浪费大量的空格括号(虽然我可以在方便的地方使用它们)。但是,作为您语言限制的副作用,必须通过否定来测试空白,因此我永远无法测试x30,我必须测试!x31*!x32*!x33*!x34。这将在以后很重要

所以现在你的

示例
if field1 = val1 and 
if field2 = val1 or
if field1 = val1 and 
if field2 = val2 or
...
if field1 = val1 and
if field2 = val4 or
if field1 = val2 and
if field2 = val1 or
...

可以写成[(f11*f21) + (f11*f22) + ... + (f11*f24)] + [(f12*f21) + (f11*f22) + ... + (f11*f24)],为清楚起见,提供括号和括号。现在我们知道一些重要的事情:任何其他有效的符号必须在逻辑上等同于此。我们也知道等式必须是SoP形式。如果我们可以做一个比这更大的层次结构,那么有很多可用的解决方案。

我推荐这种表示法,因为进行SoP优化是微电子工程师的标准配置。我们已经做了很长时间,所以我们知道所有的技巧。

现在,除了那个符号,解决问题

请考虑以下信息:

  • 任何一个查询(字段=值)都不能包含足够的信息来检测失败,因为合法的任何字段都可以具有任何值。
    • 至少需要两个术语来检测故障。它们总是在一起,因为它是SoP形式。
    • 通过将3个术语组合使用,无法收集新信息。对于链接的任何3个术语,任何非失败的输入都不会失败,条件更少。任何失败的输入都会失败,因为第三个词是“不关心”。
  • &LT;和&gt;优先,意味着你必须建立一个失败检测表达式列表,然后&lt;或&gt;他们在一起检测失败。
  • 这些规则总结指出,只有2个查询(如你的答案)的答案总是比涉及3个查询的答案更有效。
    • 因此,我们只需要考虑表格中是否存在规则组合(x1 * y1)+(x2 * y2)+(x3 * y3)+ ...这可能比你的设置更有效。< / LI>

使用此表单检测失败的唯一可能方法是让x1和y1都是查询非空白字段的术语。唯一可能的方法是测试每一个可能的对。如果您跳过一对,则可能会错过无效的输入,这是微不足道的。

我们唯一可以混合的可能是从SoP中剔除更多的价值就是否定。到目前为止,我们只谈到了对平等的测试。不幸的是,由于你的语言,它没有帮助。如果我否定任何与!x32相同的测试,例如x30 + x31 + x33 + x34。遗憾的是,在您的逻辑中没有哪处有助于将x30这样的空白与x31之类的值混合使用。因此,唯一对你有用的否定是!x30,但正如你所提到的,你无法测试空白,所以唯一有用的否定是不可能的。

所有这些都表明还有其他方法可以实现,但它们都需要与您的解决方案所需的步骤相同,或更糟。