Wolfram mathematica 从表达式中提取变量的实用程序

Wolfram mathematica 从表达式中提取变量的实用程序,wolfram-mathematica,Wolfram Mathematica,我正在寻找一个实用程序,它将接受一个表达式并提取该表达式中的所有变量。 以下五个示例涵盖了我的几乎所有变量模式 a,下标[a,…],下标[a,…][…],a[…],a[…][…] 这里有两个测试用例 expr1 = -Log[Subscript[\[Mu], 2][]] Subscript[\[Mu], 2][] - Log[Subscript[\[Mu], 2][2]] Subscript[\[Mu], 2][2] + Log[Subscript[\[Beta], 1, 2][

我正在寻找一个实用程序,它将接受一个表达式并提取该表达式中的所有变量。 以下五个示例涵盖了我的几乎所有变量模式

a,下标[a,…],下标[a,…][…],a[…],a[…][…]

这里有两个测试用例

expr1 = -Log[Subscript[\[Mu], 2][]] Subscript[\[Mu], 2][] - 
   Log[Subscript[\[Mu], 2][2]] Subscript[\[Mu], 2][2] + 
   Log[Subscript[\[Beta], 1, 2][]] Subscript[\[Beta], 1, 2][] + 
   Log[2] Subscript[\[Beta], 1, 2][1] + 
   Log[Subscript[\[Beta], 1, 2][1]] Subscript[\[Beta], 1, 2][1] + 
   Log[2] Subscript[\[Beta], 1, 2][2] + 
   Log[Subscript[\[Beta], 1, 2][2]] Subscript[\[Beta], 1, 2][2] + 
   Log[Subscript[\[Beta], 2, 3][]] Subscript[\[Beta], 2, 3][] + 
   Log[Subscript[\[Beta], 2, 3][2]] Subscript[\[Beta], 2, 3][2] + 
   Log[2] Subscript[\[Beta], 2, 3][3] + 
   Log[Subscript[\[Beta], 2, 3][3]] Subscript[\[Beta], 2, 3][3];

expr2 = Log[\[Beta][{1, 2}][{}]] \[Beta][{1, 2}][{}] + 
  Log[2] \[Beta][{1, 2}][{1}] + 
  Log[\[Beta][{1, 2}][{1}]] \[Beta][{1, 2}][{1}] + 
  Log[2] \[Beta][{1, 2}][{2}] + 
  Log[\[Beta][{1, 2}][{2}]] \[Beta][{1, 2}][{2}] + 
  Log[\[Beta][{2, 3}][{}]] \[Beta][{2, 3}][{}] + 
  Log[\[Beta][{2, 3}][{2}]] \[Beta][{2, 3}][{2}] + 
  Log[2] \[Beta][{2, 3}][{3}] + 
  Log[\[Beta][{2, 3}][{3}]] \[Beta][{2, 3}][{3}] - 
  Log[\[Mu][{2}][{}]] \[Mu][{2}][{}] - 
  Log[\[Mu][{2}][{2}]] \[Mu][{2}][{2}]

On[Assert];
Assert[Union@extractVariables@expr1 === Union[Variables[expr1][[9 ;;]]]]
Assert[Union@extractVariables@expr2 === Union[Variables[expr2][[9 ;;]]]]
这是向导的解决方案

extractVariables[formula_] := (
   pat = _Symbol[___][___] | Subscript[_Symbol, __][___] | Subscript[_Symbol, __] | _Symbol;
   Union@Cases[formula, pat, -1]
);
显而易见(但可能不正确)的方法是:

pat = _Symbol[___][___] | Subscript[_Symbol, __][___] |  Subscript[_Symbol, __] | _Symbol;

Cases[expr1, pat, -1]
Cases[expr2, pat, -1]
但坦率地说,我不太理解你的问题,不知道哪里出了问题


如果这确实对你有效,那么我建议:

extractVariables[formula_] := 
  With[{pat = _Symbol[___][___] | Subscript[_Symbol, __][___] | Subscript[_Symbol, __] | _Symbol},
    Union@Cases[formula, pat, -1]
  ]

下面是我用来获取各种类型表达式(列表、方程、不等式和内部数值函数)中的“变量”的一些代码

提供的测试中的一个示例:

在[36]:=getAllVariables[expr2]中

Out[36]={[Beta][{1,2}][{}],[Beta][{1,2}][{1}],[Beta][{1,, 2} [{2}],[Beta][{2,3}][{}],[Beta][{2,3}][{2}],[Beta][{2, 3} [{3}],[Mu][{2}][{}],[Mu][{2}][{2}]}

这可以扩展到处理更大一类的表达式,例如布尔表达式、带有伪变量的数学表达式(例如Sum或Integrate)、一些编程结构。期待棘手的问题出现

轶事:早在上个千年,内核部门有人安排了一次会议来讨论“什么是变量?”这是在Mathematica的环境中进行的,而不是在普通数学或CS中。尽管如此,这是一件难以捉摸的事情,因为不同的功能似乎对这些实体有不同的要求。我自己的看法是回答说,那天(预定的会议)我会生病。我不记得有人问过我是怎么事先知道的


Daniel Lichtblau

@Yaroslav,请参见我的编辑。它保持
pat
本地而不是向
Global
开放。谢谢。我在答案中添加了一个小的编辑,以使它通过我的测试cases@Daniel关于你的轶事,这是我在MMA中经常遇到的主要绊脚石之一。我希望有一些关于如何定义一般模型的指导,其中变量可以是内生的,也可以是外生的。例如:将变量声明为外生参数的“最佳”方法是什么?使用属性常量?或者只是把一切都塞进假设(全球或本地),然后依靠简化,等等。?基于属性的方法很简单,但不完整——因为我还想强制执行与类型和范围相关的属性——这是MMA中的一个禁忌。
headlist = {Or, And, Equal, Unequal, Less, LessEqual, Greater, 
   GreaterEqual, Inequality};

getAllVariables[f_?NumericQ] := Sequence[]
getAllVariables[{}] := Sequence[]
getAllVariables[t_] /; MemberQ[headlist, t] := Sequence[]

getAllVariables[ll_List] := 
 Flatten[Union[Map[getAllVariables[#] &, ll]]]

getAllVariables[Derivative[n_Integer][f_][arg__]] := 
 getAllVariables[{arg}]

getAllVariables[f_Symbol[arg__]] := 
 Module[{fvars}, 
  If[MemberQ[Attributes[f], NumericFunction] || MemberQ[headlist, f], 
   fvars = getAllVariables[{arg}],(*else*)fvars = f[arg]];
  fvars]

getAllVariables[other_] := other