以树的形式表达和可能简化逻辑表达式

问题描述

我得到了一堆布尔表达式(以乘积形式),例如:

(1  & 0  &  2) |
(1  & 0  &  3  &  4  &  5) |
(1  &  6  &  7  &  2  &  8) |
(1  &  6 &  3) |
(6  &  7  &  8) |
(1  &  9  &  11  &  12 &  10) |
(1  &  9  &  11  &  12  &  13)

每个数字(例如:1、0 等)代表一个原子布尔表达式。

  1. 我想把它们放在一个单一的条件树中。 (例如:

    1
       0
          2
          3
             4
               5
     ...
    

我想像上面那样将它们布置在树中(即每个分支代表一个条件表达式,每个节点代表一个原子条件)。

当我将它们放在树上时,我还需要满足以下要求。

  1. 树不能有冲突的条件(即每个分支都应该是互斥的)。树构建算法必须尽最大努力确保构建的分支没有冲突(尽管我不确定是否可以 100% 完成,因为输入条件本身可能会发生冲突)。
  2. 一些条件重复并且有多个父级(例如:“8”它有 2 个不同的父级 2 和 7_ - 这违反了树的原则。

我正在尝试寻找解决此问题所需的方法的任何指示。 也有兴趣验证我的观点,即问题无法 100% 解决(意思是,我们无法获得无冲突的树),因为这取决于输入条件的性质?

解决方法

我不确定我的脚本是否是您想要的。我使用 php、html、css 和一个 css 库调用 Treeflex(基于 flexbox 的 CSS 库,用于使用 HTML 列表绘制层次树)制作了一个小脚本,以从您的布尔表达式中绘制一棵树。

我假设逻辑 OR 运算符 (|) 分隔分支。

在分支 (1 & 6 & 3) 中,您可以在末尾看到 4 & 5 个节点,因为在其他分支中,3 是 4 的“父亲”,我不确定它是否正确。

输入数据:

$booleanExpression = "(1  & 0  &  2) | (1  & 0  &  3  &  4  &  5) | (1  &  6  &  7  &  2  &  8) | (1  &  6 &  3) | (6  &  7  &  8) | (1  &  9  &  11  &  12 &  10) | (1  &  9  &  11  &  12  &  13)";

功能:

<?php

const ROOT_NODE = "Root";

**
 * Function to parse boolean Expression into an
 * associative array with each node and its father.
 * Duplicate nodes (some node number and father) are
 * not included.
 * 
 * @param string $booleanExpression
 * @return array("node","father","order","branchNumber")
 */
function parseExpression($booleanExpression) {
    $nodes = [];

    $branchs = explode("|",$booleanExpression);
    $branchNumber = 1;

    foreach($branchs as $branch) {
        $branchClear = preg_replace("(\(|\))","",$branch);

        $branchNodes = array_map(function($n) {
                                    return trim($n);
                                },explode("&",trim($branchClear)));

        $order = 1;
        $nodeFather = ROOT_NODE;

        foreach($branchNodes as $node) {
            $key = array_search($node,array_column($nodes,"node"));

            if($key === false || array_column($nodes,"father")[$key] !== $nodeFather) {
                $nodes[] = array("node" => $node,"father" => $nodeFather,"order" => $order,"branchNumber" => $branchNumber);
            }

            $order++;
            $nodeFather = $node;
        }

        $branchNumber++;
    }

    //Order could be omit:

    usort($nodes,function($a,$b) {
        if($a["order"] == $b["order"]) {
            if($a["father"] == $b["father"]) {
                if($a["branchNumber"] <= $b["branchNumber"]) {
                    return -1;
                } else {
                    return 1;
                }
            } else if($a["father"] < $b["father"]) {
                return -1;
            } else {
                return 1;
            }
        } else if($a["order"] < $b["order"]) {
            return -1;
        } else {
            return 1;
        }
    });

    return $nodes;
}

/**
 * Functión to draw the html tree;
 * 
 * @param array("node","branchNumber") $nodes
 * @param exp $father
 * @return string //html code
 */
function getTree($nodes,$father) {
    $res = "";
    $res .= "<li>";
    $res .= "<span class='tf-nc'>{$father}</span>";
    $cantHijos = 0;

    foreach($nodes as $node) {
        if($node['father'] == $father) {
            $cantHijos++;

            $res .= $cantHijos == 1 ? "<ul>" : "";

            $res .= getTree($nodes,$node["node"]);
        }
    }

    $res .= $cantHijos > 0 ? "</ul>" : "";

    $res .= "</li>";

    return $res;
}

?>

代码:

<?php

$tree = getTree(parseExpression($booleanExpression),ROOT_NODE);

echo "<div class='tf-tree'>";
echo "<ul>";

echo $tree;

echo "</ul>";
echo "</div>";

?>

输出是下面的html代码:

/*
MIT License

Copyright (c) 2018 dumptyd

Permission is hereby granted,free of charge,to any person obtaining a copy
of this software and associated documentation files (the "Software"),to deal
in the Software without restriction,including without limitation the rights
to use,copy,modify,merge,publish,distribute,sublicense,and/or sell
copies of the Software,and to permit persons to whom the Software is
furnished to do so,subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS",WITHOUT WARRANTY OF ANY KIND,EXPRESS OR
IMPLIED,INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,DAMAGES OR OTHER
LIABILITY,WHETHER IN AN ACTION OF CONTRACT,TORT OR OTHERWISE,ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

.tf-tree {
  font-size: 16px;
  overflow: auto
}

.tf-tree * {
  box-sizing: border-box;
  margin: 0;
  padding: 0
}

.tf-tree ul {
  display: inline-flex
}

.tf-tree li {
  align-items: center;
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  padding: 0 1em;
  position: relative
}

.tf-tree li ul {
  margin: 2em 0
}

.tf-tree li li:before {
  border-top: .0625em solid #000;
  content: "";
  display: block;
  height: .0625em;
  left: -.03125em;
  position: absolute;
  top: -1.03125em;
  width: 100%
}

.tf-tree li li:first-child:before {
  left: calc(50% - .03125em);
  max-width: calc(50% + .0625em)
}

.tf-tree li li:last-child:before {
  left: auto;
  max-width: calc(50% + .0625em);
  right: calc(50% - .03125em)
}

.tf-tree li li:only-child:before {
  display: none
}

.tf-tree li li:only-child>.tf-nc:before,.tf-tree li li:only-child>.tf-node-content:before {
  height: 1.0625em;
  top: -1.0625em
}

.tf-tree .tf-nc,.tf-tree .tf-node-content {
  border: .0625em solid #000;
  display: inline-block;
  padding: .5em 1em;
  position: relative
}

.tf-tree .tf-nc:before,.tf-tree .tf-node-content:before {
  top: -1.03125em
}

.tf-tree .tf-nc:after,.tf-tree .tf-nc:before,.tf-tree .tf-node-content:after,.tf-tree .tf-node-content:before {
  border-left: .0625em solid #000;
  content: "";
  display: block;
  height: 1em;
  left: calc(50% - .03125em);
  position: absolute;
  width: .0625em
}

.tf-tree .tf-nc:after,.tf-tree .tf-node-content:after {
  top: calc(100% + .03125em)
}

.tf-tree .tf-nc:only-child:after,.tf-tree .tf-node-content:only-child:after,.tf-tree>ul>li>.tf-nc:before,.tf-tree>ul>li>.tf-node-content:before {
  display: none
}

.tf-tree.tf-gap-sm li {
  padding: 0 .6em
}

.tf-tree.tf-gap-sm li>.tf-nc:before,.tf-tree.tf-gap-sm li>.tf-node-content:before {
  height: .6em;
  top: -.6em
}

.tf-tree.tf-gap-sm li>.tf-nc:after,.tf-tree.tf-gap-sm li>.tf-node-content:after {
  height: .6em
}

.tf-tree.tf-gap-sm li ul {
  margin: 1.2em 0
}

.tf-tree.tf-gap-sm li li:before {
  top: -.63125em
}

.tf-tree.tf-gap-sm li li:only-child>.tf-nc:before,.tf-tree.tf-gap-sm li li:only-child>.tf-node-content:before {
  height: .6625em;
  top: -.6625em
}

.tf-tree.tf-gap-lg li {
  padding: 0 1.5em
}

.tf-tree.tf-gap-lg li>.tf-nc:before,.tf-tree.tf-gap-lg li>.tf-node-content:before {
  height: 1.5em;
  top: -1.5em
}

.tf-tree.tf-gap-lg li>.tf-nc:after,.tf-tree.tf-gap-lg li>.tf-node-content:after {
  height: 1.5em
}

.tf-tree.tf-gap-lg li ul {
  margin: 3em 0
}

.tf-tree.tf-gap-lg li li:before {
  top: -1.53125em
}

.tf-tree.tf-gap-lg li li:only-child>.tf-nc:before,.tf-tree.tf-gap-lg li li:only-child>.tf-node-content:before {
  height: 1.5625em;
  top: -1.5625em
}

.tf-tree li.tf-dotted-children .tf-nc:after,.tf-tree li.tf-dotted-children .tf-nc:before,.tf-tree li.tf-dotted-children .tf-node-content:after,.tf-tree li.tf-dotted-children .tf-node-content:before {
  border-left-style: dotted
}

.tf-tree li.tf-dotted-children li:before {
  border-top-style: dotted
}

.tf-tree li.tf-dotted-children>.tf-nc:before,.tf-tree li.tf-dotted-children>.tf-node-content:before {
  border-left-style: solid
}

.tf-tree li.tf-dashed-children .tf-nc:after,.tf-tree li.tf-dashed-children .tf-nc:before,.tf-tree li.tf-dashed-children .tf-node-content:after,.tf-tree li.tf-dashed-children .tf-node-content:before {
  border-left-style: dashed
}

.tf-tree li.tf-dashed-children li:before {
  border-top-style: dashed
}

.tf-tree li.tf-dashed-children>.tf-nc:before,.tf-tree li.tf-dashed-children>.tf-node-content:before {
  border-left-style: solid
}
<div class='tf-tree'>
  <ul>
    <li><span class='tf-nc'>Root</span>
      <ul>
        <li><span class='tf-nc'>1</span>
          <ul>
            <li><span class='tf-nc'>0</span>
              <ul>
                <li><span class='tf-nc'>2</span>
                  <ul>
                    <li><span class='tf-nc'>8</span></li>
                  </ul>
                </li>
                <li><span class='tf-nc'>3</span>
                  <ul>
                    <li><span class='tf-nc'>4</span>
                      <ul>
                        <li><span class='tf-nc'>5</span></li>
                      </ul>
                    </li>
                  </ul>
                </li>
              </ul>
            </li>
            <li><span class='tf-nc'>6</span>
              <ul>
                <li><span class='tf-nc'>7</span>
                  <ul>
                    <li><span class='tf-nc'>8</span></li>
                    <li><span class='tf-nc'>2</span>
                      <ul>
                        <li><span class='tf-nc'>8</span></li>
                      </ul>
                    </li>
                  </ul>
                </li>
                <li><span class='tf-nc'>3</span>
                  <ul>
                    <li><span class='tf-nc'>4</span>
                      <ul>
                        <li><span class='tf-nc'>5</span></li>
                      </ul>
                    </li>
                  </ul>
                </li>
              </ul>
            </li>
            <li><span class='tf-nc'>9</span>
              <ul>
                <li><span class='tf-nc'>11</span>
                  <ul>
                    <li><span class='tf-nc'>12</span>
                      <ul>
                        <li><span class='tf-nc'>10</span></li>
                        <li><span class='tf-nc'>13</span></li>
                      </ul>
                    </li>
                  </ul>
                </li>
              </ul>
            </li>
          </ul>
        </li>
        <li><span class='tf-nc'>6</span>
          <ul>
            <li><span class='tf-nc'>7</span>
              <ul>
                <li><span class='tf-nc'>8</span></li>
                <li><span class='tf-nc'>2</span>
                  <ul>
                    <li><span class='tf-nc'>8</span></li>
                  </ul>
                </li>
              </ul>
            </li>
            <li><span class='tf-nc'>3</span>
              <ul>
                <li><span class='tf-nc'>4</span>
                  <ul>
                    <li><span class='tf-nc'>5</span></li>
                  </ul>
                </li>
              </ul>
            </li>
          </ul>
        </li>
      </ul>
    </li>
  </ul>
</div>

enter image description here

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...