2011-05-01 13 views
9

Estoy buscando una utilidad que tome una expresión y extraiga todas las variables en esa expresión. Tras cinco ejemplos cubren casi todos mis patrones variablesUtilidad para extraer variables de una expresión

a,Subscript[a,....],Subscript[a,...][...],a[...],a[...][...]

Aquí hay dos casos de prueba.

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[[email protected]@expr1 === Union[Variables[expr1][[9 ;;]]]] 
Assert[[email protected]@expr2 === Union[Variables[expr2][[9 ;;]]]] 

Aquí está la solución de MrWizard

extractVariables[formula_] := (
    pat = _Symbol[___][___] | Subscript[_Symbol, __][___] | Subscript[_Symbol, __] | _Symbol; 
    [email protected][formula, pat, -1] 
); 

Respuesta

8

Aquí hay un código que utilizo para llegar a "variables" en diversos tipos de expresión (listas, ecuaciones, desigualdades, y dentro de las funciones numéricas).

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 

Un ejemplo de pruebas previstas:

En [36]: = getAllVariables [expr2]

Fuera [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}]}

Esto podría ampliarse para manejar una clase de expresiones más grande, por ejemplo Boolean, matemática con variables ficticias (por ejemplo, Sum o Integrate), algunas construcciones programáticas. Espere que el problema espinoso aparezca.

Anécdota: En el último milenio, alguien en el Kernel Dept programó una reunión para discutir el tema "¿Qué es una variable?" Esto fue dentro del entorno de Mathematica, no de matemática general o CS. De todos modos, es una cosa difícil de precisar porque las diferentes funciones parecen tener requisitos diferentes para tales entidades. Mi propia opinión fue responder que estaría enfermo ese día (de la reunión prevista). No recuerdo si me preguntaron cómo sabía que de antemano ...

Daniel Lichtblau

+0

Gracias. Agregué una pequeña edición en la respuesta para que pase mis casos de prueba –

+0

@Daniel Lichtblau - En lo que respecta a su anécdota, este es uno de los principales obstáculos con los que lucho con frecuencia en MMA. Me gustaría que hubiera alguna guía sobre cómo definir modelos generales, donde las variables pueden ser endógenas o exógenas. Ej .: ¿Cuál es el "mejor" enfoque para declarar una variable como un parámetro exógeno? ¿Usando la constante de atributo? ¿O simplemente meter todo en Suposiciones (global o localmente) y luego confiar en Simplificar, etc.? El enfoque basado en atributos es fácil, pero incompleto, ya que también deseo aplicar los atributos relacionados con el tipo y el rango, un no ir en MMA. – telefunkenvf14

4

El enfoque obvio (pero presumiblemente incorrecta) sería:

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

Cases[expr1, pat, -1] 
Cases[expr2, pat, -1] 

Pero, francamente no entiendo cuestionas lo suficientemente bien como para saber donde esta va mal.


Si que realmente funciona para usted, entonces me recomiendan:

extractVariables[formula_] := 
    With[{pat = _Symbol[___][___] | Subscript[_Symbol, __][___] | Subscript[_Symbol, __] | _Symbol}, 
    [email protected][formula, pat, -1] 
    ] 
+0

que pasa a mis casos de prueba .... –

+0

@Yaroslav, ver mi edición. Mantiene 'pat' local en lugar de abrir' Global'. –

Cuestiones relacionadas