Это не код ОО, а скорее подтверждение концепции (и мне было скучно).
Код в основном разбит на две половины. Во-первых, это код, который эффективно маркирует строки, а затем создает список зависимостей для каждой переменной. Таким образом, a зависит от b и c et c.
Вторая часть представляет собой систему грубой силы, которая просматривает каждый список зависимостей и проверяет, все ли зависимости разрешимы, каждый раз, когда она может ее решить. (все зависимые поля известны), он добавляет последовательность в список переменных, чтобы сказать, в каком порядке они могут быть запущены. Он продолжает делать это до тех пор, пока все не будут решены, или он больше не будет продвигаться (что может быть что-то вроде = b и b = a).
Я добавил комментарии в коде, может помочь ...
$equations = [
"a = b * c",
"b = c + d",
"c = 5",
"d = 8",
"e = f * 2",
"f = b + 3 + a",
];
$variables = [];
$toBeSolved = [];
$symbols = ["=", "*", "+", "-", "/"];
$evalSeq = 0;
// Extract dependencies and known values
foreach ( $equations as $equation ) {
$parts = explode ( " ", $equation);
$equationVars = [];
$leftVar = array_shift($parts);
$variables[$leftVar] = null;
foreach ( $parts as $part ) {
if ( !in_array ($part, $symbols) && !is_numeric($part) ) {
$variables[$part] = null;
$equationVars[] = $part;
}
}
// If there are dependant values, add to list of things to be solved
if ( count($equationVars) > 0 ) {
$toBeSolved[$leftVar] = $equationVars;
}
// No dependants, so just log sequence as solved
else {
$variables[$leftVar] = $evalSeq++;
}
}
// Find equations solvable, carry on whilst unknowns left
while ( count($toBeSolved) > 0 ){
$progress = 0;
foreach ( $toBeSolved as $var => $dep ) {
$known = true;
foreach ( $dep as $variable ) {
// Flag an unknown variable, so can't solve this yet
if ( $variables[$variable] === null ) {
$known = false;
break;
}
}
// If all values are known, then can be evaluated, so log sequence and remove
if ( $known ) {
$variables[$var] = $evalSeq++;
unset ($toBeSolved[$var]);
$progress++;
}
}
// If no progress has been made, then can't reduce further.
if ( $progress == 0 ){
break;
}
}
print_r($variables);
// If $toBeSolved is not empty, then can't solve
print_r($toBeSolved);
Конечный результат - что-то вроде ...
Array
(
[a] => 3
[b] => 2
[c] => 0
[d] => 1
[e] => 5
[f] => 4
)
, показывающий, что порядок вычисления равен c, d, b, a, f, e.
Возможно, что вместо сохранения последовательности вы можете сохранить значения вместо этого, так как каждый проход сделан, вы можете вычислить результат уравнения и сохранить его вместе с именем переменной.