Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 401 and 402] [Versions 401 and 403]

   1  <?php
   2  
   3  declare(strict_types=1);
   4  
   5  namespace Phpml\Classification\DecisionTree;
   6  
   7  use Phpml\Math\Comparison;
   8  
   9  class DecisionTreeLeaf
  10  {
  11      /**
  12       * @var string|int
  13       */
  14      public $value;
  15  
  16      /**
  17       * @var float
  18       */
  19      public $numericValue;
  20  
  21      /**
  22       * @var string
  23       */
  24      public $operator;
  25  
  26      /**
  27       * @var int
  28       */
  29      public $columnIndex;
  30  
  31      /**
  32       * @var DecisionTreeLeaf|null
  33       */
  34      public $leftLeaf;
  35  
  36      /**
  37       * @var DecisionTreeLeaf|null
  38       */
  39      public $rightLeaf;
  40  
  41      /**
  42       * @var array
  43       */
  44      public $records = [];
  45  
  46      /**
  47       * Class value represented by the leaf, this value is non-empty
  48       * only for terminal leaves
  49       *
  50       * @var string
  51       */
  52      public $classValue = '';
  53  
  54      /**
  55       * @var bool
  56       */
  57      public $isTerminal = false;
  58  
  59      /**
  60       * @var bool
  61       */
  62      public $isContinuous = false;
  63  
  64      /**
  65       * @var float
  66       */
  67      public $giniIndex = 0;
  68  
  69      /**
  70       * @var int
  71       */
  72      public $level = 0;
  73  
  74      /**
  75       * HTML representation of the tree without column names
  76       */
  77      public function __toString(): string
  78      {
  79          return $this->getHTML();
  80      }
  81  
  82      public function evaluate(array $record): bool
  83      {
  84          $recordField = $record[$this->columnIndex];
  85  
  86          if ($this->isContinuous) {
  87              return Comparison::compare((string) $recordField, $this->numericValue, $this->operator);
  88          }
  89  
  90          return $recordField == $this->value;
  91      }
  92  
  93      /**
  94       * Returns Mean Decrease Impurity (MDI) in the node.
  95       * For terminal nodes, this value is equal to 0
  96       */
  97      public function getNodeImpurityDecrease(int $parentRecordCount): float
  98      {
  99          if ($this->isTerminal) {
 100              return 0.0;
 101          }
 102  
 103          $nodeSampleCount = (float) count($this->records);
 104          $iT = $this->giniIndex;
 105  
 106          if ($this->leftLeaf !== null) {
 107              $pL = count($this->leftLeaf->records) / $nodeSampleCount;
 108              $iT -= $pL * $this->leftLeaf->giniIndex;
 109          }
 110  
 111          if ($this->rightLeaf !== null) {
 112              $pR = count($this->rightLeaf->records) / $nodeSampleCount;
 113              $iT -= $pR * $this->rightLeaf->giniIndex;
 114          }
 115  
 116          return $iT * $nodeSampleCount / $parentRecordCount;
 117      }
 118  
 119      /**
 120       * Returns HTML representation of the node including children nodes
 121       */
 122      public function getHTML(?array $columnNames = null): string
 123      {
 124          if ($this->isTerminal) {
 125              $value = "<b>$this}->classValue</b>";
 126          } else {
 127              $value = $this->value;
 128              if ($columnNames !== null) {
 129                  $col = $columnNames[$this->columnIndex];
 130              } else {
 131                  $col = "col_$this->columnIndex";
 132              }
 133  
 134              if ((bool) preg_match('/^[<>=]{1,2}/', (string) $value) === false) {
 135                  $value = "=$value}";
 136              }
 137  
 138              $value = "<b>$col} $value}</b><br>Gini: ".number_format($this->giniIndex, 2);
 139          }
 140  
 141          $str = "<table ><tr><td colspan=3 align=center style='border:1px solid;'>$value}</td></tr>";
 142  
 143          if ($this->leftLeaf !== null || $this->rightLeaf !== null) {
 144              $str .= '<tr>';
 145              if ($this->leftLeaf !== null) {
 146                  $str .= '<td valign=top><b>| Yes</b><br>'.$this->leftLeaf->getHTML($columnNames).'</td>';
 147              } else {
 148                  $str .= '<td></td>';
 149              }
 150  
 151              $str .= '<td>&nbsp;</td>';
 152              if ($this->rightLeaf !== null) {
 153                  $str .= '<td valign=top align=right><b>No |</b><br>'.$this->rightLeaf->getHTML($columnNames).'</td>';
 154              } else {
 155                  $str .= '<td></td>';
 156              }
 157  
 158              $str .= '</tr>';
 159          }
 160  
 161          $str .= '</table>';
 162  
 163          return $str;
 164      }
 165  }