How to apply HoldForm to a list of variables without the variables in the list being evaluated first? - wolfram-mathematica

I am writing a debug function, which prints a variable name, and its value. I call this debug function with a list of variables from anywhere in the program. So the idea is for it to work like this:
debug[var_List] := Module[{values = ReleaseHold[var], i},
For[i = 1, i <= Length[values], i++,
Print[var[[i]], " = ", values[[i]]]
]
];
Now I use the above, like this
x = 3; y = 5;
debug[{HoldForm[x], HoldForm[y]}]
and I see in the console the following
x = 3
y = 5
But I have a large program and long list of variables at different places I want to debug. And I do not want to type HoldForm to each variable to make up the list to call the debug[] function. Much easier to Map it if possible. Less typing each time. But this does not work:
debug[ Map[HoldForm,{x,y}]]
The reason is that {x,y} was evaluated before HoldForm got hold of it. So I end up with a list that has the values in it, like this:
3 = 3
5 = 5
I could not find a way to Map HoldForm without the list being evaluated.
The best I could find is this:
debug[HoldForm[Defer[{x, y}]]]
which gives the following output from the above debug[] function:
{x,y} = {3,5}
Since Defer[{x, y}] has length 1, and it is just one thing, I could not break it up to make a 2 column list like in the above example.
It will be better if I can get an output of the form
x = 3
y = 5
easier to match the variable with its value since I have many variables.
question is: Any one knows of a programming trick to convert HoldForm[{x,y}] to {HoldForm[x],HoldForm[y]}
thanks

Just use Thread:
Thread[HoldForm[{x, y}]]
alternatively,
Map[HoldForm, Unevaluated[{x, y}]]

Here is a longer alternative demonstrating use of Hold, found in Roman Maeder's Programming In Mathematica (3rd ed.), page 137:
e1 = Hold[{x, y}];
e2 = MapAt[Hold, e1, {1, 0}];
e3 = Map[HoldForm, e2, {2}];
e4 = MapAt[ReleaseHold, First[e3], {0}];
debug[e4]
x=3
y=5

I did a PrintIt function using attributes that does what you want. I posted it here https://stackoverflow.com/a/8270643/884752, I repeat the code:
SetAttributes[System`ShowIt, HoldAll];
System`ShowIt[code__] := System`ShowIt[{code}];
System`ShowIt[code_] :=
With[{y = code},
Print[Defer[code = y]];
y
];
SetAttributes[System`PrintIt, {HoldAll,Listable}];
System`PrintIt[expr__]:=System`PrintIt[{expr}];
System`PrintIt[expr_] := System`ShowIt[expr];

Related

Modelica: assign array return value to scalars

The following model tries to assign a vector return value of a function call to a vector of scalars. It checks and works if it is inside an equation section, but it fails inside an algorithm section. Is that a bug in the Modelica tool I am using, or am I doing something wrong? And, how can I write it without introducing the intermediate variable x[2]?
model returnVector
Real x1;
Real x2;
Real x[2];
Real A[2,2] = [1,2;3,4];
Real b[2] = {8,7};
algorithm
x = Modelica.Math.Matrices.solve(A,b);
{x1, x2} = Modelica.Math.Matrices.solve(A,b);
end returnVector;
You are doing something wrong :-)
In equations the left-hand-side is any expression; so you could even write Modelica.Math.Matrices.solve(A,b)={x1,x2};.
In algorithms the left-hand-side must be a component-reference (section 11.2 in Modelica 3.4; https://modelica.org/documents/ModelicaSpec34.pdf ) and the right-hand-side is evaluated and then assigned to the left-hand-side variable.
Under the 'algorithm', one must use ' := ' to represent the Assignment in Modelica instead of ' = ' as like in C/C++.
So the code could be rewritten as follows:
model returnVector
Real x1;
Real x2;
Real x[2];
Real A[2,2] = [1, 2; 3, 4];
Real b[2] = {8, 7};
algorithm
x := Modelica.Math.Matrices.solve(A, b);
x1 := x[1];
x2 := x[2];
//{x1, x2} = Modelica.Math.Matrices.solve(A, b);
end returnVector;
Simply write the left-hand-side within round parentheses:
({x1, x2}) := Modelica.Math.Matrices.solve(A, b);

Performance of Wolfram Mathematica InverseFunction

given the constants
mu = 20.82;
ex = 1.25;
kg1 = 1202.76;
kp = 76.58;
kvb = 126.92;
I need to invert the function
f[Vpx_,Vgx_] := Vpx Log[1 + Exp[kp (1/mu + Vgx/(Vpx s[Vpx]))]];
where
s[x_] := 1 + kvb/(2 x^2);
so that I get a function of two variables, the second one being Vgx.
I tried with
t = InverseFunction[Function[{Vpx, Vgx}, f[Vpx, Vgx]], 1, 2];
tested with t[451,-4]
It takes so much time that every time I try it I stop the evaluation.
On the other side, working with only one variable, everything works:
Vgx = -4;
t = InverseFunction[Function[{Vpx}, f[Vpx,Vgx]]];
t[451]
It's my fault? the method is inappropriate? or it's a limitation of Wolfram Mathematica?
Thanks
Teodoro Marinucci
P.S. For everyone interested it's a problem related to the Norman Koren model of triodes.
As I said in my comment, my guess is that InverseFunction first tries to solve symbolically for the inverse, e.g. Solve[Function[{Vpx, Vgx}, f[Vpx, Vgx]][X, #2] == #1, X], which takes a very long time (I didn't let it finish). However, I came across a system option that seems to turn this off and produce a function:
With[{opts = SystemOptions["ExtendedInverseFunction"]},
Internal`WithLocalSettings[
SetSystemOptions["ExtendedInverseFunction" -> False],
t = InverseFunction[Function[{Vpx, Vgx}, f[Vpx, Vgx]], 1, 2],
SetSystemOptions[opts]
]];
t[451, -4]
(* 199.762 *)
A couple of notes:
According to the documentation, InverseFunction with exact input should produce an exact answer. Here some of the parameters are approximate (floating-point) real numbers, so the answer above is a numerical approximation.
The actual definition of t depends on f. If f changes, then a side effect will be that t changes. If that is not something you explicitly want, then it is probably better to define t this way:
t = InverseFunction[Function[{Vpx, Vgx}, Evaluate#f[Vpx, Vgx]], 1, 2]
As my late Theoretical Physics professor said, "a simple and beautiful solution is likely to be true".
Here is the piece of code that works:
mu = 20.82; ex = 1.25; kg1 = 1202.76; kp = 76.58; kvb = 126.92;
Ip[Vpx_, Vgx_] = Power[Vpx/kp Log[1 + Exp[kp (1/mu + Vgx/Sqrt[kvb + Vpx^2])]], ex] 2/kg1;
Vp[y_, z_] := x /. FindRoot[Ip[x, z] == y, {x, 80}]
The "real" amplification factor of a tube is the partial derivative of Ip[Vpx, Vgx] by respect to Vgx, with give Vpx. I would be happier if could use the Derivative, but I'm having errors.
I'll try to understand why, but for the moment the definition
[CapitalDelta]x = 10^-6;
[Micro][Ipx_, Vgx_] := Abs[Vp[Ipx, Vgx + [CapitalDelta]x] - Vp[Ipx, Vgx]]/[CapitalDelta]x
works well for me.
Thanks, it was really the starting point of the FindRoot the problem.

Making a matrix in a for loop

I am currently working with mathematica and I got stuck on some technicalities.
Rvec[R_] := UnitVector[Length[R], RandomInteger[{1, Length[R]}]]
Fvec[R_] := R - Rvec[R] + Rvec[R]
vec[R_] := Module[{S = Fvec[R]}, If[Count[S, -1] > 0, R, S]]
Loop[R_, n_] := For[i = 1; L = R, i < n + 1, i++, L = vec[L]; Print[L]]
The idea is that I now have a loop going that will randomly subtract one number from one entry in a set and add it to another in the next iteration, but with the catch that no entry can drop below zero. The output I then get is a set of outcomes put beneath each other.
Having done that I would like to know how I could put the entire output in the form of one matrix:
https://i.gyazo.com/a4ef70ba5670fd53003e0ac5ec1e434e.png
Instead of having the output like that, I would like to have it in matrix form, as in having this set of outputs placed in a larger set containing those sets as elements. This would greatly help me, as I would be able to manipulate and work with the entire output.
If you need to make matrix by consequently adding vector by vector, you can do like this:
vector = {1, 2, 3, 4, 5};
matrix = {}; (* Initialize matrix *)
Do[matrix = Append[matrix, vector], 5]; (* Construct matrix by adding line by line*)
MatrixForm[matrix] (* Print matrix *)
Please tell me If I didn't understanf youy problem properly.

Set::write error when using For loop

Solving a complicated formula f(u,v)==0, where
I assign some constant value to u and then solve v.
I can solve it without for-loop, but encounter errors by adding For[] enclosing the codes,
where saying
Set::write: Tag Times in "Solve[] with exact coefficients solns is Protected.
A simple example to illustrate my idea:
For[ i = 1, i < 5, i++,
f = x^2 + y^2 - 10;
x = i;
eqn = (f == 0);
soln = Solve[eqn, y]
]
will get error:
Set::write: "Tag Times in (-9+y^2) is Protected."
Only when I add For[ ] at the outside of the code
(inner 4-line code works fine without for loop)
So it seems that there is an variable assignment permission issue in the for loop
How can I avoid it?
I no longer have Mathematica 7 installed, and your code runs (although with no printed output...) on Mathematica 10. Based on the error message, it sounds like you need to Clear[f] before trying to reassign it.
For[i = 1, i < 5, i++,
Clear[f];
f = x^2 + y^2 - 10;
x = i;
eqn = (f == 0);
soln = Solve[eqn, y];
Print[soln]
]
However, you're still really mixing things up. Consider what happens with your code as the loop executes. First it starts with i=1 and says:
Clear[f] -- or don't, this isn't the only issue
f = x^2 + y^2 - 10 -- This gives me an expression with symbols x and y
x=i -- This sets x=1 since i=1 already
At this point, the expression for f has become y^2 - 9`. Next time it comes around, it will repeat:
f = x^2 + y^2 - 10 -- But x is no longer a symbol!! So now it still treats x=1...
This becomes a nightmare. I could try to hack your code into working with the fewest changes (e.g. make it Clear[f,x] or something), but that's not really the best advice I can give.
A better overall construction would be something like:
Eqn[x_,y_]=(x^2+y^2-10==0);
For[i=1,i<5,i++,
Print[Solve[Eqn[i,y],y]];
];
Your function f is a function, so you should make it a function like f[x_,y_]=something. Better yet, just make the entire equation into a function as above. That way, you never actually modify the values of x or y and don't get caught with issues in your loop.
And before you use this new code I've given you, clear everything or just quit the Kernel.

Mathematica, define multiple functions using for loop

I am using usual for-loop for computation in Mathematica:
For[i=1,i<n+1,i++, ...calculation... ]
For each i I need to define a function F_i[x_,y_]:=.... Here "i" is suuposed to be a label of the function. This is however not the corrcet Mathematica expression.
The question is, how to define multiple functions distinguished by the label i? I mean, what is the correct syntax?
Thanks a lot.
I'm not exactly sure what you are trying to do, but I have some confidence that the for loop is not the way to go in Mathematica. Mathematica already has pattern matching that likely eliminates the need for the loop.
What about something like this
f[i_][x_,y_]:= i(x+y)
or something like this
f[s_String][x_,y_]:=StringLength[s](x+y)
or even
f[s_,x_,y_]:=StringLength[s](x+y)
Here are some steps which may help. There are two versions below, the second one includes the value of i on the RHS of the function definition.
n = 2;
For[i = 1, i < n + 1, i++,
f[i][x_, y_] := (x + y)*i]
?f
Global`f
f[1][x_,y_] := (x+y) i
f[2][x_,y_] := (x+y) i
Clear[i]
f[2][2, 3]
5 i
Quit[]
n = 2;
For[i = 1, i < n + 1, i++,
With[{j = i},
f[i][x_, y_] := (x + y)*j]]
?f
Global`f
f[1][x$,y$] := (x$+y$) 1
f[2][x$,y$] := (x$+y$) 2
Clear[i]
f[2][2, 3]
10

Resources