【问题标题】:Express and (possibly simplify) Logical expressions as a tree将逻辑表达式表达和(可能简化)为树
【发布时间】:2021-05-11 05:25:39
【问题描述】:

我得到了一堆布尔表达式(以产品总和形式),例如:

(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% 解决(意思是,我们无法获得无冲突的树),因为这取决于输入条件的性质?

【问题讨论】:

    标签: tree logic boolean-logic discrete-mathematics boolean-expression


    【解决方案1】:

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

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

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

    输入数据:

    $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", "father", "order", "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>

    【讨论】:

      猜你喜欢
      • 2011-11-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多