屋顶计算场景下Symfony ExpressionLanguage依赖变量公式求解算法咨询
屋顶计算应用公式求解算法实现
核心思路
将每个公式抽象为目标变量-依赖变量-计算表达式的结构化数据,通过迭代方式逐步用已知变量求解可计算的目标变量,直到所有变量都被求解,或判定无法完成求解时抛出异常。
算法步骤
- 定义公式元数据:为每个公式记录目标变量、依赖变量列表、Symfony ExpressionLanguage兼容的表达式字符串。
- 初始化已知变量集合:包含用户输入的初始值(如
a或Hr,以及A、B等固定参数)。 - 区分已求解/未求解变量集合:初始时已求解集合等于已知变量,未求解集合为所有公式目标变量减去已知变量。
- 循环迭代求解:
- 遍历所有未求解变量,检查当前已求解变量是否覆盖该变量的所有依赖项。
- 对满足条件的变量,用ExpressionLanguage计算其值,加入已求解集合并从未求解集合移除。
- 若一轮迭代中无新变量被求解,说明无法继续,抛出异常。
- 当未求解集合为空时,返回所有已求解变量。
PHP代码实现示例
首先安装Symfony ExpressionLanguage组件:
composer require symfony/expression-language
实现代码:
use Symfony\Component\ExpressionLanguage\ExpressionLanguage; class RoofCalculator { private $expressionLanguage; // 公式元数据:键为目标变量,值包含依赖列表和计算表达式 private $formulas = [ 'a' => [ 'deps' => ['Hr', 'B'], 'expr' => 'atan(Hr / B)' ], 'Hr' => [ 'deps' => ['B', 'a'], 'expr' => 'B * tan(a) / 2' ], 'R' => [ 'deps' => ['A', 'Hr'], 'expr' => '(A - (Hr / tan(90)))' ], 'X' => [ 'deps' => ['Hr', 'R', 'a'], 'expr' => 'Hr * R + cos(a)' ] ]; public function __construct() { $this->expressionLanguage = new ExpressionLanguage(); } public function calculate(array $initialVariables): array { $solved = $initialVariables; $unsolved = array_diff(array_keys($this->formulas), array_keys($solved)); $hasNewSolved = true; while ($hasNewSolved && !empty($unsolved)) { $hasNewSolved = false; $newlySolved = []; foreach ($unsolved as $variable) { $formula = $this->formulas[$variable]; // 检查是否缺少依赖变量 $missingDeps = array_diff($formula['deps'], array_keys($solved)); if (empty($missingDeps)) { // 计算变量值(注意PHP三角函数使用弧度) $value = $this->expressionLanguage->evaluate($formula['expr'], $solved); $newlySolved[$variable] = $value; $hasNewSolved = true; } } $solved = array_merge($solved, $newlySolved); $unsolved = array_diff($unsolved, array_keys($newlySolved)); } if (!empty($unsolved)) { throw new \RuntimeException(sprintf('无法求解以下变量:%s', implode(', ', $unsolved))); } return $solved; } } // 使用示例 try { $calculator = new RoofCalculator(); // 示例:初始给定a(弧度)、A、B $result = $calculator->calculate(['a' => deg2rad(30), 'A' => 10, 'B' => 5]); print_r($result); } catch (\RuntimeException $e) { echo $e->getMessage(); }
关键注意事项
- 角度单位:PHP内置三角函数默认使用弧度,若用户输入为角度,需用
deg2rad()转换;输出角度则用rad2deg()转换。 - 公式扩展性:新增公式只需在
$formulas数组中添加对应条目,确保依赖变量准确即可。 - 异常场景:当存在无法通过现有变量推导的变量时,会抛出明确的异常信息,便于排查问题。
内容的提问来源于stack exchange,提问作者shineability
相关产品推荐
相关产品推荐

