6
$\begingroup$

So I have some rules for a symbolic inner product that work for quite a lot of cases:

SetAttributes[CircleDot, Orderless]
x_ \[CircleDot] 0 := 0
(x_ + a_)\[CircleDot] b_ := x \[CircleDot] b + a\[CircleDot] b
(x_ a_) \[CircleDot] b_  := x (a\[CircleDot] b) /; NumericQ[x]

This is great if all symbols are vectors, and the scalars satisfy NumericQ == True.

Does anyone know a good way to define symbolic scalars? I'd like some kind of 'MakeScalar' function which I can use to mark some of my symbols so that they're taken out of the inner product, and then all other symbols would be interpreted as vectors

I've tried messing around with setting Attributes, but they didn't work very well, partially because I need that if a is a scalar, so is 1/a, Sin[a] etc. . Is it possible to assign NumericQ to be true for a given symbol? I'm not sure if this would be a good idea, but I think it would work for me

$\endgroup$
4
$\begingroup$

We can get a long way by directly declaring that the symbols in question are NumericQ. For example, θ is normally treated as non-scalar:

CircleDot[a, Times[θ, b]]
(* CircleDot[a, Times[b, θ]] *)

CircleDot[a, Times[Sin[θ], b]]
(* CircleDot[a, Times[b, Sin[θ]]] *)

NumericQ is a protected symbol, but its built-in definition still permits direct assignment (in the same manner as other built-ins like N and Format). Thus, as speculated in the question, we can define θ to be NumericQ to make it act like a scalar:

NumericQ[θ] = True;

CircleDot[a, Times[θ, b]]
(* Times[θ, CircleDot[a, b]] *)

CircleDot[a, Times[Sin[θ], b]]
(* Times[CircleDot[a, b], Sin[θ]] *)

We can take away the numeric status by executing NumericQ[θ] =..

As noted in the question, we must take care when changing the meaning of symbols in this fashion. It is probably not a good idea to change a common symbol like i since it NumericQ status affects many built-in functions. Therefore, I suggest restricting such changes to letter forms that have no other function in your application, (e.g. Greek, double-struck, Gothic, Hebrew, etc).

$\endgroup$
  • $\begingroup$ Thanks for your help. NumericQ[a] = True works to remove a from the inner product, but eg. Sin[a] is not removed, and when I check, NumericQ[Sin[a]] evaluates to false, even though I have set NumericQ of a to be true. This seems strange to me, do you know why it is? $\endgroup$ – Joe Jun 2 '16 at 11:15
  • $\begingroup$ As you say, strange. I just evaluated NumericQ[a] = True; NumericQ[Sin[a]] in every version of Mathematica from V9 through V10.4.1 and got True every time. What version are you using? Is there any possibility of other definitions in your application that might interfere? $\endgroup$ – WReach Jun 2 '16 at 14:19
  • $\begingroup$ OK great thanks, I restarted the kernel and now it's fine with a, not sure what was going on there. Unluckily it's still not working for the case I want to use it in though. I am trying to use Subscript[m,1] as my variable, and I have called Symbolize[Subscript[m,1]]. After this I then call NumericQ[Subscript[m,1]] = True and then NumericQ[Subscript[m,1]] which evaluates to False, do you know anything about this? $\endgroup$ – Joe Jun 3 '16 at 9:33
  • $\begingroup$ The discussion in (16976) is probably relevant. $\endgroup$ – WReach Jun 3 '16 at 14:14
  • $\begingroup$ Great thanks I'll take a look there $\endgroup$ – Joe Jun 3 '16 at 14:51
3
$\begingroup$

Try adding this to your existing definitions:

(x_scalar a_)\[CircleDot]b_ := x (a\[CircleDot]b)

This specifies a definition similar to your last one that only applies when the Head of $x$ is scalar, an auxiliary operator we introduce.

Now, suppose that you want $t$ to be a scalar and $vec_i$ to be vectors:

(scalar[t] vec1) \[CircleDot] vec2   (* Out: vec1 \[CircleDot] vec2 scalar[t] *)

The auxiliary function scalar need not have any definition. It is just there as a wrapper to indicate the "type" of $t$.

If you don't want to see the scalar wrapper in your result, you can define a formatting rule for it:

Format[scalar[a_]] := a

The same expression above will then print as follows:

(scalar[t] vec1) \[CircleDot] vec2    (* Out: vec1 \[CircleDot] vec2 t *)

The scalar wrapper is retained, however:

InputForm[%]                          (* Out: vec1 \[CircleDot] vec2 * scalar[t] *)
$\endgroup$
  • $\begingroup$ To cover the case of 1/t, Sin[t] as mentioned in the question, it could be useful to define an UpValue for scalar as follows: scalar/:(f_/;MemberQ[Attributes[f],NumericFunction])[x_scalar,args___] := scalar[f[x,args]]. $\endgroup$ – Bruno Le Floch Jun 1 '16 at 22:39
  • $\begingroup$ @MarcoB, do I understand correctly that with your method, every time I want eg. m to be a scalar, in my code I write scalar[m]? @ Bruno, I have tried your code, and when executing (1/scalar[m] a)\[CircleDot] b , I get During evaluation of In[117]:= $RecursionLimit::reclim: Recursion depth of 1024 exceeded. >> a\[CircleDot]b scalar[ scalar[scalar[ scalar[scalar[... etc. Unluckily I don't understand it so I can't edit it myself $\endgroup$ – Joe Jun 2 '16 at 11:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.