Как определить новую числовую константу в Mathematica?
Каков наилучший способ определения числовой константы в Mathematica?
Например, скажем, я хочу, чтобы g
был приблизительным ускорением из-за силы тяжести на поверхности Земли. Я даю ему числовое значение (в m/s^2
), скажите Mathematica, что он числовой, положительный и константный, используя
Unprotect[g];
ClearAll[g]
N[g] = 9.81;
NumericQ[g] ^= True;
Positive[g] ^= True;
SetAttributes[g, Constant];
Protect[g];
Тогда я могу использовать его в качестве символа в символических вычислениях, который будет автоматически оцениваться до 9.81 при вызове численных результатов. Например, 1.0 g
оценивается как 9.81
.
Это, похоже, не так привязано к Mathematica как построенное в числовых константах. Например Pi > 0
будет оцениваться до True
, но g > 0
не будет. (Я мог бы добавить g > 0
в глобальный $Assumptions
, но даже тогда мне нужен вызов Simplify
, чтобы он вступил в силу.)
Кроме того, Positive[g]
возвращает True
, но Positive[g^2]
не оценивает - сравните это с эквивалентными операторами с помощью Pi
.
Итак, мой вопрос: что еще я должен сделать, чтобы определить числовую константу? Какие еще атрибуты/свойства могут быть установлены? Есть ли более простой способ сделать это? Etc...
Ответы
Ответ 1
Я бы рекомендовал использовать "функцию" с нулевым аргументом. Таким образом, ему могут быть предоставлены атрибут NumericFunction и числовое правило оценки. это последнее важно для предикатов, таких как Positive.
SetAttributes[gravUnit, NumericFunction]
N[gravUnit[], prec_: $MachinePrecision] := N[981/100, prec]
In[121]:= NumericQ[gravitUnit[]]
Out[121]= True
In[122]:= Positive[gravUnit[]^2 - 30]
Out[122]= True
Даниэль Лихтблау
Ответ 2
Может быть, я наивна, но, на мой взгляд, ваши определения - хорошее начало. Такие вещи, как g > 0->True
, можно добавить через UpValues
. Для возврата Positive[g^2]
True
вам, вероятно, придется перегрузить Positive
из-за ограничения глубины-1 для UpValues
. Вообще, я думаю, что точный набор автоматически оцениваемых выражений с константой является движущейся мишенью, даже для встроенных констант. Другими словами, эти дополнительные встроенные правила, по-видимому, определяются из удобства и частого использования, в каждом конкретном случае, а не из первых принципов. Я бы просто добавил новые правила, когда вы идете, когда вы чувствуете, что они вам нужны. Вероятно, вы не можете ожидать, что ваши константы будут так же интегрированы в систему, как встроенные, но я думаю, вы можете приблизиться. Вам, вероятно, придется перегрузить ряд встроенных функций на эти символы, но опять же, какие из них будут, будет зависеть от того, что вам нужно от вашего символа.
ИЗМЕНИТЬ
Я не решался включить это, так как нижеприведенный код - это взломать, но в некоторых случаях он может быть полезен. Вот код:
Clear[evalFunction];
evalFunction[fun_Symbol, HoldComplete[sym_Symbol]] := False;
Clear[defineAutoNValue];
defineAutoNValue[s_Symbol] :=
Module[{inSUpValue},
s /: expr : f_[left___, s, right___] :=
Block[{inSUpValue = True},
With[{stack = Stack[_]},
If[
expr === Unevaluated[expr] &&
(evalFunction[f, HoldComplete[s]] ||
MemberQ[
stack,
HoldForm[(op_Symbol /; evalFunction[op, HoldComplete[s]])
[___, x_ /; ! FreeQ[Unevaluated[x], [email protected]], ___]],
Infinity
]
),
f[left, N[s], right],
(* else *)
expr
]]] /; ! TrueQ[inSUpValue]];
ClearAll[substituteNumeric];
SetAttributes[substituteNumeric, HoldFirst];
substituteNumeric[code_, rules : {(_Symbol :> {__Symbol}) ..}] :=
Internal`InheritedBlock[{evalFunction},
MapThread[
Map[Function[f, evalFunction[f, HoldComplete[#]] = True], #2] &,
Transpose[List @@@ rules]
];
code]
При этом вы можете включить символ для автоматического подстановки его численного значения в местах, где мы укажем, что некоторые функции, связанные с этими вызовами функций, могут извлечь из этого выгоду. Вот пример:
ClearAll[g, f];
SetAttributes[g, Constant];
N[g] = 9.81;
NumericQ[g] ^= True;
defineAutoNValue[g];
f[g] := "Do something with g";
Здесь мы попытаемся вычислить некоторые выражения, содержащие g
, сначала обычно:
In[391]:= {f[g],g^2,g^2>0, 2 g, Positive[2 g+1],Positive[2g-a],g^2+a^2,g^2+a^2>0,g<0,g^2+a^2<0}
Out[391]= {Do something with g,g^2,g^2>0,2 g,Positive[1+2 g],
Positive[-a+2 g],a^2+g^2,a^2+g^2>0,g<0,a^2+g^2<0}
И теперь внутри нашей обертки (второй аргумент дает список правил, чтобы указать, для каких символов, которые функционируют, когда они обернуты вокруг кода, содержащего эти символы, должны приводить к замене этих символов их числовыми значениями):
In[392]:=
substituteNumeric[{f[g],g^2,g^2>0, 2 g, Positive[2 g+1],Positive[2g-a],g^2+a^2,g^2+a^2>0,
g<0,g^2+a^2<0},
{g:>{Positive,Negative,Greater}}]
Out[392]= {Do something with g,g^2,True,2 g,True,Positive[19.62\[VeryThinSpace]-a],
a^2+g^2,96.2361\[VeryThinSpace]+a^2>0,g<0,a^2+g^2<0}
Так как выше это взломать, я ничего не могу гарантировать. Это может быть полезно в некоторых случаях, но это необходимо решать в каждом конкретном случае.
Ответ 3
Возможно, вам захочется рассмотреть работу с единицами, а не просто константами. В Mathematica есть несколько вариантов
Существует множество технических проблем и тонкостей относительно работы с блоками. Я нашел backgrounder в конструкторских модулях очень полезным. Также есть несколько интересных дискуссий о MathGroup. (например, здесь).