function iteration in mathematica - wolfram-mathematica

I'm a beginner in Mathematica programming. My code is not running as expected. I wonder if anyone could examine what goes wrong? Here is part of the code.
F[{k_, n_, x_}] =
Which[k == 0, f[a, b, x],
k == 1, g[a, b, n, x],
k == 2, h[c, d, n, x]]
G[x_] = F[{0, 0, x}]
While[Extract[G[x], 1] != 3, G[x_] = F[G[x]]]
The functions f, g and h are defined by Which as is F, and they are all vector-valued so that it makes sense to iterate F. What I want to achieve is: given initial value {0,0,x}, keep iterating F until the first component of F becomes 3. Is there anything, e.g. syntax, wrong in the above code?
Thanks!

You need to use SetDelayed (:=) for function definitions like: F[x_]:=x. When you use Set (=) like F[x_]=x, the it is essentially the same as F[_]=x since the definition isn't delayed until evaluation, so there is no way to transfer the matched pattern on the left hand side into the evaluation of the right hand side.

As jVincent mentioned, I would use := instead of = while defining F.
I would also use the built in NestWhile instead of manually iterating.
NestWhile[F, {0, 0, x}, Function[e, Extract[e, 1] != 3]]
I can't quite comment on how to correct the code as written because I'm not entirely sure how reassigning G in the While works.

Related

Simple - Plotting a function

Why does this not plot?
Clear[x, b]
b = 2
f[x_] := b^x
Plot[f[x], {x, 1, 5}]
The Plot simply generates and empty graph.
This plots just fine for me in Mathematica 8.
Something to note though, you don't really want to do := in the function declaration here.
:= Postpones mathematica evaluating the function until it is actually called, and then it evaluates with the arguments given.
Basically, the rule I use is if I don't have a reason to use :=, I don't use it.
Good luck.
Edit
I just noticed you didn't clear f, that could be your problem.
Try this:
ClearAll[f, b];
b = 2;
f[x_] := b^x
Plot[f[x], {x, 1, 5}]

Orthogonalize[ ] working as expected only when applied twice

Applying Orthogonalize[] once:
v1 = PolyhedronData["Dodecahedron", "VertexCoordinates"][[1]];
Graphics3D[Line[{{0, 0, 0}, #}] & /#
Orthogonalize[{a, b, c} /.
FindInstance[{a, b, c}.v1 == 0 && (Chop#a != 0.||Chop#b != 0.||Chop#c != 0.),
{a, b, c}, Reals, 4]], Boxed -> False]
And now twice:
Graphics3D[Line[{{0, 0, 0}, #}] & /#
Orthogonalize#Orthogonalize[{a, b, c} /.
FindInstance[{a, b, c}.v1 == 0 && (Chop#a != 0.||Chop#b != 0.||Chop#c != 0.),
{a, b, c}, Reals, 4]], Boxed -> False]
Errr ... Why?
I think the first result is due to numerical error, taking
sys = {a,b,c}/.FindInstance[
{a, b, c}.v1 == 0 && (Chop#a != 0. || Chop#b != 0. || Chop#c !=0.),
{a, b, c}, Reals, 4];
then MatrixRank#sys returns 2, therefor the system itself is only two dimensional. To me, this implies that the first instance of Orthogonalize is generating a numerical error, and the second instance is using the out of plane error to give you your three vectors. Removing the Chop conditions fixes this,
Orthogonalize[{a, b, c} /.
N#FindInstance[{a, b, c}.v1 == 0,{a, b, c}, Reals, 4]]
where N is necessary to get rid of the Root terms that appear. This gives you a two-dimensional system, but you can get a third by taking the cross product.
Edit: Here's further evidence that its numerical error due to Chop.
With Chop, FindInstance gives me
{{64., 3.6, 335.108}, {-67., -4.3, -350.817}, {0, 176., 0},
{-2., -4.3, -10.4721}}
Without Chop, I get
{{-16.8, 3.9, -87.9659}, {6.6, -1.7, 34.558}, {13.4, -4.3, 70.1633},
{19.9, -4.3, 104.198}}
which is a significant difference between the two.
I also assumed it would be a numerical error, but didn't quite understand why, so I tried to implement Gram-Schmidt orthogonalization myself, hoping to understand the problem on the way:
(* projects onto a unit vector *)
proj[u_][v_] := (u.v) u
Clear[gm, gramSchmidt]
gm[finished_, {next_, rest___}] :=
With[{v = next - Plus ## Through[(proj /# finished)[next]]},
gm[Append[finished, Normalize#Chop[v]], {rest}]
]
gm[finished_, {}] := finished
gramSchmidt[vectors_] := gm[{}, vectors]
(Included for illustration only, I simply couldn't quite figure out what's going on before I reimplemented it myself.)
A critical step here, which I didn't realize before, is deciding whether a vector we get is zero or not before the normalization step (see Chop in my code). Otherwise we might get something tiny, possibly a mere numerical error, which is then normalized back into a large value.
This seems to be controlled by the Tolerance option of Orthogonalize, and indeed, raising the tolerance, and forcing it to discard tiny vectors fixes the problem you describe. Orthogonalize[ ... , Tolerance -> 1*^-10] works in a single step.
Perhaps it is a characteristic of the default GramSchmidt method?
Try: Method -> "Reorthogonalization" or Method -> "Householder".

Getting Indices from Mathematica's Select

How can I get the indices of a selection rather than the values. I.e.
list={3->4, 5->2, 1->1, 5->8, 3->2};
Select[list, #[[1]]==5&]; (* returns {5->2, 5->8} *)
I would like something like
SelectIndices[list, #[[1]]==5&]; (* returns {2, 4} *)
EDIT: I found an answer to the immediate question above (see below), but what about sorting. Say I want to sort a list but rather than returning the sorted list, I want to return the indices in the order of the sorted list?
Ok, well, I figured out a way to do this. Mathematica uses such a different vocabulary that searching the documentation still is generally unfruitful for me (I had been searching for things like, "Element index from Mathematica Select", to no avail.)
Anyway, this seems to be the way to do this:
Position[list, 5->_];
I guess its time to read up on patterns in Mathematica.
WRT to the question remaining after your edit: How about Ordering?
In[26]:= Ordering[{c, x, b, z, h}]
Out[26]= {3, 1, 5, 2, 4}
In[28]:= {c, x, b, z, h}[[Ordering[{c, x, b, z, h}]]]
Out[28]= {b, c, h, x, z}
In[27]:= Sort[{c, x, b, z, h}]
Out[27]= {b, c, h, x, z}
I think you want Ordering:
Sort[list, #[[1]] == 5 &]
Ordering[list, All, #[[1]] == 5 &]
(*
{5->2,5->8,3->2,1->1,3->4}
{2,4,5,3,1}
*)
Sorry, I had read your question to fast.
I think your second question is about how to sort the list according to the values of the rules. The simplest way that come to mind is by using a compare function. then simply use your solution to retrieve the indices:
comp[_ -> x_, a_ -> y_] := x < y;
Position[Sort[list, comp], 5 -> _]
Hope this helps!
Without sorting or otherwise altering the list, do this:
SelectIndex[list_, fn_] := Module[{x},
x = Reap[For[i = 1, i < Length[list], i++, If[fn[list[[i]]], Sow[i], Null];]];
If[x[[1]] == {}, {}, x[[2, 1]]]]
list={ {"foo",1}, {"bar",2}};
SelectIndex[list, StringMatchQ[ #[[1]], "foo*"] &]
You can use that to extract records from a database
Lookup[list_, query_, column_: 1, resultColumns_: All] := list[[SelectIndex[list, StringMatchQ[query, #[[column]]] &], resultColumns]]
Lookup(list,"foo")

A problem when wrongly using Dot command in Mma

In[1]:= SameQ[Dot[1, 2], 1.2]
TrueQ[Dot[1, 2] == 1.2]
a = 1; b = 2;
SameQ[Dot[a, b], a.b]
TrueQ[Dot[a, b] == a.b]
Out[1]= False
Out[2]= False
Out[4]= True
Out[5]= True
I know this uses Dot command wrong. Anybody can give me a clear reson for the above different results?
thanks!
a.b is interpreted as Dot[a,b] and then variables a and b are substituted, meaning Dot[1,2] and thus equality holds. This is not the same as 1.2 where the dot stands for the decimal separator and not for the inline operator of Dot.
When you write 1.2, Mma understands a number (aka 6/5), but if you write {1, 1}.{2, 2} or a.b Mma understands a scalar product, as usual in any book using vectors.
HTH!
It can be informative to view an expression under Hold and FullForm:
a = 1; b = 2;
SameQ[Dot[a, b], a.b]] //Hold //FullForm
Hold[SameQ[Dot[a, b], Dot[a, b]]]
With this combination of commands, Mathematica parses but does not evaluate the expression (Hold), and then shows the long pseudo-internal form of the expression (FullForm).
In this case, you can see that the second term a.b is parsed as Dot[a, b] before any evaluation happens.
When . appears with numerals as in 1.2 it is interpreted specially as a decimal point. This is similar to other numeric entry formats such as: 1*^6 which is recognized directly as 1000000:
1*^6 //Hold //FullForm
Compare trying to enter:
a = 1;
a*^6

Can I have two values for a constant within an NDSolve function that are dependent on the output of the NDSolve function?

I have a system of ODE's. One of the ODE's has a constant parameter which I want to alter between two different values depending on one of the ODE solutions.
So for example let's say that I have the following equations:
{
A'[x] == -q A[x]B[x],
B'[x] == q A[x]B[x] - g B[x],
C'[x] == g B[x]
}
Now I can solve them easily using the NDSolve function when q and g are constant values. What I want to do though is vary the value of q so that it has one value when B[x] is below a certain threshold but then changes in value when B[x] rises above this threshold value.
I've tried using If statements and Piecewise functions outside of the NDSolve but I haven't managed to get it working.
This might do something like what you want. I left out the third equation, which seems superfluous.
Clear[f, g, s, t, x];
s[a_, b_] = Piecewise[{{a*b - b, b < 1}, {2 a*b - b, b >= 1}}];
t[a_, b_] = Piecewise[{{-a*b, b < 1}, {-2 a*b, b >= 1}}];
{f[x_], g[x_]} = {f[x], g[x]} /.
First[NDSolve[{
f'[x] == t[f[x], g[x]],
g'[x] == s[f[x], g[x]],
f[0] == 10, g[0] == 1},
{f[x], g[x]}, {x, 0, 2}]]

Resources