Как определить новую числовую константу в 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. (например, здесь).