Solves a series of related expressions
a = 1
b = a + 1
c = b * 2
d = a + b
Usage:
$solver = new Solver();
$solver->addValue('a', 1);
$solver->addFormula('b', 'a + 1');
$solver->addFormula('c', 'b * 2');
$solver->addFormula('d', 'a + c');
$solver->solve();
var_dump($solver->getResults());
Outputs:
array (size=4)
'a' => int 1
'b' => float 2
'c' => float 4
'd' => float 5
Solver class:
class Solver
{
protected $values = [];
protected $formulas = [];
protected $answers = [];
protected $functions = [];
function addValue($name, $value)
{
if (isset($this->values[$name])) {
throw new \Exception("Value '{$name}' already declared cannot redeclare/overwrite value");
}
if (isset($this->formulas[$name])) {
throw new \Exception("Formula already exists with the name '{$name}'. Can you give it another name?");
}
$this->values[$name] = $value;
}
//Used internally to add answers back to the value stack
private function pushValue($name, $value)
{
if (isset($this->values[$name])) {
throw new \Exception("Value '{$name}' already declared cannot redeclare/overwrite value");
}
$this->values[$name] = $value;
}
function addFormula($name, $formula)
{
if (isset($this->formulas[$name])) {
throw new \Exception("Formula '{$name}' already declared cannot redeclare/overwrite formula");
}
if (isset($this->values[$name])) {
throw new \Exception("Value already exists with the name '{$name}'. Can you give it another name?");
}
$this->formulas[$name] = $formula;
}
function addFunction($name, callable $closure)
{
$this->functions[$name] = $closure;
}
function getVisitor()
{
$instance = new Hoa\Math\Visitor\Arithmetic();
foreach ($this->values as $key => $value) {
$instance->addVariable($key, function() use ($value) {
return $value;
});
}
foreach ($this->functions as $key => $closure) {
$instance->addFunction($key, $closure);
}
return $instance;
}
function solve()
{
foreach ($this->formulas as $name => $formula) {
$compiler = Hoa\Compiler\Llk::load(new Hoa\File\Read('hoa://Library/Math/Arithmetic.pp'));
$visitor = $this->getVisitor();
$ast = $compiler->parse($formula);
$answer = $visitor->visit($ast);
$this->answers[$name] = $answer;
$this->pushValue($name, $answer);
}
}
function getResults()
{
$result = array_merge($this->values, $this->answers);
return $result;
}
function getAnswers()
{
return $this->answers;
}
}