Как определить новую числовую константу в Mathematica? - PullRequest
11 голосов
/ 26 ноября 2011

Как лучше всего определить числовую константу в 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 ...

Ответы [ 3 ]

5 голосов
/ 27 ноября 2011

Я бы рекомендовал использовать «функцию» с нулевым аргументом. Таким образом, ему могут быть заданы как атрибут NumericFunction, так и числовое правило оценки. последнее важно для таких предикатов, как Позитивный.

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

Даниэль Лихтблау

3 голосов
/ 26 ноября 2011

Может быть, я наивен, но, на мой взгляд, ваши определения - хорошее начало. Такие вещи, как g > 0->True могут быть добавлены через UpValues. Чтобы Positive[g^2] вернул True, вам, вероятно, придется перегрузить Positive из-за ограничения глубины 1 для UpValues. Вообще, я думаю, что точный набор автоматически вычисляемых выражений, включающих константу, является движущейся целью даже для встроенных констант. Другими словами, эти дополнительные встроенные правила, по-видимому, определяются из удобства и частого использования в каждом конкретном случае, а не из первых принципов. Я бы просто добавил новые правила по мере необходимости, когда вы чувствуете, что они вам нужны. Вероятно, вы не можете ожидать, что ваши константы будут так же хорошо интегрированы в систему, как встроенные, но я думаю, что вы можете быть довольно близки. Возможно, вам придется перегружать ряд встроенных функций для этих символов, но опять же, какие из них будут зависеть от того, что вам нужно от вашего символа.

EDIT

Я не решался включить это, поскольку приведенный ниже код является хаком, но может быть полезным в некоторых обстоятельствах. Вот код:

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], HoldPattern@expr], ___]],
                    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}

Поскольку вышеизложенное является хаком, я не могу ничего гарантировать по этому поводу. В некоторых случаях это может быть полезно, но это должно решаться в каждом конкретном случае.

2 голосов
/ 26 ноября 2011

Вы можете рассмотреть возможность работы с единицами, а не только с константами.В Mathematica доступно несколько опций

В работе с юнитами есть немало технических проблем и тонкостей.Я нашел backgrounder в Designer Units очень полезным.Есть также некоторые интересные обсуждения на MathGroup.(например, здесь ).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...