(Oddly enough, the title for another question that ended up dealing with an unrelated problem could have worked better here, but I didn't want to plagiarize.)
Given a symbolic vector function U[t]
with independent variable t
in an arbitrary number of dimensions, let f[U[t]]:=Normalize[U'[t]]
. Then, one can succinctly define the unit tangent, normal, and binormal vectors as {T[t],N[t],B[t]}=NestList[f,U[t],3][[2;;]]
. (Note that in this case, N
does not refer to the built-in numerical approximation function; it's just an unfortunate coincidence in notation.) Although there's no reason why NestList
has to stop at three layers, I have been having problems with going beyond such due to the size and complexity of the output, which I know can be greatly simplified. Here are the methods I have come up with so far, and the problems I have encountered with each of them:
- Using the given definition: This leads to instances of
Norm'[_]
, which prevents much of the simplification. - Adjusting the given definition: Changing the definition of
f
to something likef[v_]:=#/Sqrt[#.#]&[Dt[v,t]]
gets closer, butDot
is neither distributive overPlus
nor commutative, as Mathematica includes the possibility of the arguments toDot
being rectangular matrices, which would indeed produce different results. - Using
Simplify
and the like: This takes a rather long time, given that the input expression is a 16-level fraction with square roots. - Using assumptions to indicate vectors:
Assuming[VectorQ[v],_]
fails because lone variables that aren't explicitly lists are treated as scalars, makingVectorQ[v]
evaluate toFalse
. - Using patterns to indicate vectors: While using expressions like
{u__}
is an intriguing possibility, when taking the derivative, Mathematica ends up producing the nonsensical expressionDerivative[1,0][Pattern][u,__]
as a part of the result. - Adding the distributive-over-
Plus
and commutative properties to the dot product: While the latter is easy enough to do via theOrderless
attribute, I have no idea how to do the former, given the aforementioned problems withVectorQ
. (For the record, I'm talking abouta.(b+c)==a.b+a.c
.) - Defining a substitute for the
Dot
function with those properties: While the substitute function itself does not have to be defined, defining its properties would likely require reverse-engineering of theDot
function, and especially how it interacts with theDt
function, which might or might not be against the terms of the license, depending on whether the reverse-engineering or it being common mathematical knowledge takes precedence within the context of the license. - Defining a substitute for the
Dt
function: This runs into the problem with attributes. - Doing everything manually: While I am better able to find repeating sub-patterns within the expressions myself than I am programming Mathematica to do it, the computer is far faster than me, and I'm sure I'll make a sign error or something somewhere.
Is there any way to fix any of these?
FIRST UPDATE: I ended up using a substitute Dot
function and defining its attributes (aside from Orderless
) through assignments (e.g. dot[a_,b_+c_]:=dot[a,b]+dot[a,c]
). However, factoring expressions out over Times
had been an issue, as incorrectly factoring out undotted instances of Derivative[_][U][t]
would lead to the nonsensical result of a dot product between a scalar and a vector, or even between two scalars. Nevertheless, I found a possible way around this by adding a function i
that encloses undotted instances of Derivative[_][U][t]
as a sort of indicator, and serves as an identity function otherwise; it would finally disappear using the assignment of dot[i[a_],i[b_]]:=dot[a,b]
. (In other words, one could use MatchQ[i]
or FreeQ[i]
on an expression as a substitute for the [non-functioning] VectorQ[expr]
.)
But now I've run into another issue that, on its face, seems bizarre. Consider the expression dot[2*i[U''[t]]*dot[U'[t],U'[t]],-2*i[U'[t]]*dot[U'[t],U''[t]]]
, an actual subexpression encountered for the unit normal vector. The assignment dot[a_,b_*c_?FreeQ[i]]:=c*dot[a,b]
fails to do anything, due to MatchQ[-2*i[U'[t]]*dot[U'[t],U''[t]],b_*c_?FreeQ[i]]
returning False
(even if the test ?MemberQ[i]
is added onto b_
in addition to or instead of the test on c_
, and/or the positions of b_
and c_
are swapped with each other), despite the fact that all of the following return True
:
MatchQ[-2*i[U'[t]]*dot[U'[t],U''[t]],b_*c_]
MatchQ[-2*i[U'[t]]*dot[U'[t],U''[t]],b_*c_Integer]
MatchQ[-2*i[U'[t]]*dot[U'[t],U''[t]],b_*c_?IntegerQ]
Now what is going on here?
SECOND UPDATE: Immediately after posting the previous update, I found that setting the assignment dot[a_,b_*c_/;FreeQ[c,i]]:=c*dot[a,b]
actually does work in solving the second issue (and the whole problem in general), but this only makes that issue even more strange: what would allow FreeQ[dot[U'[t],U''[t]],i]
and MatchQ[dot[U'[t],U''[t]],c_/;FreeQ[c,i]]
to evaluate to True
, yet force MatchQ[dot[U'[t],U''[t]],c_?FreeQ[i]]
, a supposedly identical expression, to evaluate to False
?