Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 80
0.00% covered (danger)
0.00%
0 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
Simplex
0.00% covered (danger)
0.00%
0 / 80
0.00% covered (danger)
0.00%
0 / 6
1406
0.00% covered (danger)
0.00%
0 / 1
 setFunction
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 addConstraint
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 pivot
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 iterateSimplex
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 initialize
0.00% covered (danger)
0.00%
0 / 74
0.00% covered (danger)
0.00%
0 / 1
992
 solve
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2/**
3 * Jingga
4 *
5 * PHP Version 8.1
6 *
7 * @package   phpOMS\Math\Optimization
8 * @copyright Dennis Eichhorn
9 * @license   OMS License 2.0
10 * @version   1.0.0
11 * @link      https://jingga.app
12 */
13declare(strict_types=1);
14
15namespace phpOMS\Math\Optimization;
16
17/**
18 * Simplex class.
19 *
20 * @package phpOMS\Math\Optimization
21 * @license OMS License 2.0
22 * @link    https://jingga.app
23 * @link    https://github.com/PetarV-/Algorithms/blob/master/Mathematical%20Algorithms/Simplex%20Algorithm.cpp
24 * @since   1.0.0
25 */
26class Simplex
27{
28    private array $function = [];
29
30    private string $functionType = '';
31
32    private int|float $functionLimit = 0.0;
33
34    private array $constraints = [];
35
36    private array $constraintsType = [];
37
38    private array $constraintsLimit = [];
39
40    private array $slackForm = [];
41
42    private array $nonbasicSolution = [];
43
44    private array $basicSolution = [];
45
46    /**
47     * Define the function to optimize
48     *
49     * @param array $function Function to optimize
50     *
51     * @return void
52     *
53     * @since 1.0.0
54     */
55    public function setFunction(array $function) : void
56    {
57    }
58
59    /**
60     * Add function constraint
61     *
62     * @param array  $function Constraint function
63     * @param string $type     Constraint type
64     * @param float  $limit    Constraint
65     *
66     * @return void
67     *
68     * @since 1.0.0
69     */
70    public function addConstraint(array $function, string $type, float $limit) : void
71    {
72    }
73
74    /**
75     * Pivot element
76     *
77     * @param int $x X-Pivot
78     * @param int $y Y-Pivot
79     *
80     * @return void
81     *
82     * @since 1.0.0
83     */
84    private function pivot(int $x, int $y) : void
85    {
86    }
87
88    /**
89     * Perform simplex iteration
90     *
91     * @return void
92     *
93     * @since 1.0.0
94     */
95    private function iterateSimplex() : void
96    {
97    }
98
99    /**
100     * Initialize simplex algorithm
101     *
102     * @return bool
103     *
104     * @since 1.0.0
105     */
106    private function initialize() : bool
107    {
108        $k        = -1;
109        $minLimit = -1;
110
111        $m = \count($this->constraints);
112        $n = \count($this->function);
113
114        for ($i = 0; $i < $m; ++$i) {
115            if ($k === -1 || $this->constraintsLimit[$i] < $minLimit) {
116                $k        = $i;
117                $minLimit = $this->constraintsLimit[$i];
118            }
119        }
120
121        if ($this->constraintsLimit[$k] >= 0) {
122            for ($j = 0; $j < $n; ++$j) {
123                $this->nonbasicSolution[$j] = $j;
124            }
125
126            for ($i = 0; $i < $m; ++$i) {
127                $this->basicSolution[$i] = $n + $i;
128            }
129
130            return true;
131        }
132
133        // Auxiliary LP
134        ++$n;
135        for ($j = 0; $j < $n; ++$j) {
136            $this->nonbasicSolution[$j] = $j;
137        }
138
139        for ($i = 0; $i < $m; ++$i) {
140            $this->basicSolution[$i] = $n + $i;
141        }
142
143        $oldFunction = $this->function;
144        $oldLimit    = $this->functionLimit;
145
146        // Auxiliary function
147        $this->function[$n - 1] = -1;
148        $this->functionLimit    = 0;
149
150        for ($j = 0; $j < $n - 1; ++$j) {
151            $this->function[$j] = 0;
152        }
153
154        // Auxiliary constraints
155        for ($i = 0; $i < $m; ++$i) {
156            $this->constraints[$i][$n - 1] = 1;
157        }
158
159        $this->pivot($k, $n - 1);
160
161        // Solve Auxiliary LP
162        while ($this->iterateSimplex());
163
164        if ($this->functionLimit !== 0) {
165            return false;
166        }
167
168        $zBasic = -1;
169        for ($i = 0; $i < $m; ++$i) {
170            if ($this->basicSolution[$i] === $n - 1) {
171                $zBasic = $i;
172                break;
173            }
174        }
175
176        if ($zBasic === -1) {
177            $this->pivot($zBasic, $n - 1);
178        }
179
180        $zNonBasic = -1;
181        for ($j = 0; $j < $n; ++$j) {
182            if ($this->nonbasicSolution[$j] === $n - 1) {
183                $zNonBasic = $j;
184                break;
185            }
186        }
187
188        for ($i = 0; $i < $m; ++$i) {
189            $this->constraints[$i][$zNonBasic] = $this->constraints[$i][$n - 1];
190        }
191
192        $tmp                                = $this->nonbasicSolution[$n - 1];
193        $this->nonbasicSolution[$n - 1]     = $this->nonbasicSolution[$zNonBasic];
194        $this->nonbasicSolution[$zNonBasic] = $tmp;
195
196        --$n;
197
198        for ($j = 0; $j < $n; ++$j) {
199            if ($this->nonbasicSolution[$j] > $n) {
200                --$this->nonbasicSolution[$j];
201            }
202        }
203
204        for ($i = 0; $i < $m; ++$i) {
205            if ($this->basicSolution[$i] > $n) {
206                --$this->basicSolution[$i];
207            }
208        }
209
210        $this->functionLimit = $oldLimit;
211        for ($j = 0; $j < $n; ++$j) {
212            $this->function[$j] = 0;
213        }
214
215        for ($j = 0; $j < $n; ++$j) {
216            $ok = false;
217
218            for ($jj = 0; $jj < $n; ++$jj) {
219                if ($j === $this->nonbasicSolution[$jj]) {
220                    $this->function[$jj] += $oldFunction[$j];
221
222                    $ok = true;
223                    break;
224                }
225            }
226
227            if ($ok) {
228                continue;
229            }
230
231            for ($i = 0; $i < $m; ++$i) {
232                if ($j = $this->basicSolution[$i]) {
233                    for ($jj = 0; $jj < $n; ++$jj) {
234                        $this->function[$jj] += $oldFunction[$j] * $this->constraints[$i][$jj];
235                    }
236
237                    $this->functionLimit += $oldFunction[$j] * $this->constraintsLimit[$i];
238                    break;
239                }
240            }
241        }
242
243        return true;
244    }
245
246    /**
247     * Solve the optimization
248     *
249     * @return array
250     *
251     * @since 1.0.0
252     */
253    public function solve() : array
254    {
255        if (!$this->initialize()) {
256            return [];
257        }
258    }
259}