Related
My aim is to create a lot of functions f_i in a loop. These functions depend on parameters a[[i]], which can be taken from array A = {a1, a2, ...}. In order to eliminate the influence of the interator i, which leads to the situation when all functions are the same, I aspire to create variable names for each iteration.
The example: suppose I have got the array W = {1,2,3, ..., 100} and I should create variables w1 = 1, w2 = 2, ..., w100 = 100. I am trying to do this with the help of a for-loop:
loc[expr1_, expr2_] :=
ToExpression[StringJoin[ToString[expr1], ToString[expr2]]];
For[i = 1, i <= 100, i++,
{
loc[w, i] = W[[i]];
}]
When I need to see which value variable wk contains, then wk is not defined. But loc[w, k] = k is known.
How can I define variables wi? Or is there another way to create functions in a loop?
Thanks in advance
The way you are using {} leads me to believe that you have prior experience with other programming languages.
Mathematica is a very different language and some of what you know and expect will be wrong. Mathematica only uses {} to mean that is a list of elements. It is not used to group blocks of code. ; is more often used to group blocks of code.
Next, try
W={1,2,3};
For[i=i,i<=3,i++,
ToExpression["w"<>ToString[i]<>"="<>ToString[i]]
];
w2
and see that that returns
2
I understand that there is an intense desire in people who have been trained in other programming languages to use For to accomplish things. There are other ways o doing that for most purposes in Mathematica.
For one simple example
W={1,2,3};
Map[ToExpression["z"<>ToString[#]<>"="<>ToString[#]]&,W];
z2
returns
2
where I used z instead of w just to be certain that it wasn't showing me a prior cached value of w2
You can even do things like
W={1,2,3};
loc[n_,v_]:=ToExpression[ToString[n]<>ToString[v]<>"="<>ToString[v]];
Map[loc[a,#]&,W];
a3
which returns
3
Ordinarily, you will use indexed variables for this. E.g.,
ClearAll[x, xs]
n = 4
xs = Array[Indexed[x, #] &, 4]
Example use with random data:
RandomSeed[314]
mA = RandomInteger[{0, 99}, {n, n}]
vb = RandomInteger[{0, 99}, n]
Solve[mA.xs == vb, xs]
This is just for illustration; one would ordinarily use LinearSolve for the example problem. E.g., MapThread[Rule, {xs, LinearSolve[mA, vb]}].
It would be simpler to use a function variable, e.g. w[1], but here is a method to define w1 etc.
Note Clear can clear assignments using string versions of the symbols.
W = {1, 2, 7, 9};
Clear ## Map["w" <> ToString[#] &, W]
Map[(Evaluate[Symbol["w" <> ToString[#]]] = #) &, W];
w9
9
Symbol /# Map["w" <> ToString[#] &, W]
{1, 2, 7, 9}
Alternatively, with a function variable . . .
Map[(w[#] = #) &, W]
{1, 2, 7, 9}
w[9]
9
Also, using the OP's structure
Clear[loc]
Clear[w]
Clear ## Map["w" <> ToString[#] &, W]
W = {1, 2, 3, 4};
loc[expr1_, expr2_] := StringJoin[ToString[expr1], ToString[expr2]]
For[i = 1, i <= 4, i++, Evaluate[Symbol[loc[w, i]]] = W[[i]]]
Symbol /# Map["w" <> ToString[#] &, W]
{1, 2, 3, 4}
Note Evaluate[Symbol[loc[w, i]]] = W[[i]]] has the advantage that if the data at W[[i]] is a string it does not get transformed as it would by using ToExpression.
I have a list of 200 data points. I want to select one value, and change the data using the manipulate function to create a bad data point, and observe the effects on the graph.
My recent attempts included creating a variable i, and assigning like:
myarray[[80,2]] = i;
and then use manipulate as such:
Manipulate[Curve[myarray], {i, 0, 5}]
This is not giving the desired output, however. It doesn't really make sense to me to put it like that, but I don't see the alternative way. Any help on this particular problem would be greatly appreciated!
Making up some data and a Curve function :-
myarray = Transpose[{Range[10], Range[10]/2}];
Curve[myarray_] := ListLinePlot[myarray]
Manipulate[myarray[[8, 2]] = i; Curve[myarray], {i, 0, 5}]
To complement Chris Degnen's answer, which shows a good approach, here is an explanation for why your original code failed.
Manipulate, like Module, acts as a scoping construct. For this reason the i used by Manipulate (the manipulation variable) is not the same i as set with myarray[[80, 2]] = i; -- it exists in a different Context:
Manipulate[Context[i], {i, 0, 5}]
(* FE` *)
Here is a minimal example of the problem:
ClearAll[x, i]
x = i;
Manipulate[{x, i}, {i, 0, 5}]
(* {i, 2.24} *)
One way around this is to use Block, but you need to use a different name for the manipulate variable:
ClearAll[x, i]
x = {1, 2, i};
Manipulate[Block[{i = ii}, x], {ii, 0, 5}]
(* {1, 2, 1.41} *)
To illustrate my problem here is a toy example:
F[x_] := Module[{out},
If[x > 1,
out = 1/2,
out = 1
];
out
];
The function can be evaluated and plotted. However when I try to numerically integrate it I get an error
NIntegrate[F[x], {x, 0, 2}]
NIntegrate::inumr: The integrand out$831 has evaluated to non-numerical values for all sampling points in the region with boundaries {{0,2}}. >>
Integrate and some other functions will do some probing with symbolic values first. Your Module when given only the symbol x will return only the (aliased) out.
Fix this by defining your F only for numeric values. NIntegrate will discover this and then use numeric values.
In[1]:= F[x_?NumericQ] := Module[{out},
If[x > 1, out = 1/2, out = 1]; out];
NIntegrate[F[x], {x, 0, 2}]
Out[2]= 1.5
This is a fun little problem, and I wanted to check with the experts here if there is a better functional/Mathematica way to approach solving it than what I did. I am not too happy with my solution since I use big IF THEN ELSE in it, but could not find a Mathematica command to use easily to do it (such as Select, Cases, Sow/Reap, Map.. etc...)
Here is the problem, given a list values (numbers or symbols), but for simplicity, lets assume a list of numbers for now. The list can contain zeros and the goal is replace the each zero with the element seen before it.
At the end, the list should contain no zeros in it.
Here is an example, given
a = {1, 0, 0, -1, 0, 0, 5, 0};
the result should be
a = {1, 1, 1, -1, -1, -1, 5, 5}
It should ofcourse be done in the most efficient way.
This is what I could come up with
Scan[(a[[#]] = If[a[[#]] == 0, a[[#-1]], a[[#]]]) &, Range[2, Length[a]]];
I wanted to see if I can use Sow/Reap on this, but did not know how.
question: can this be solved in a more functional/Mathematica way? The shorter the better ofcourse :)
update 1
Thanks everyone for the answer, all are very good to learn from. This is the result of speed test, on V 8.04, using windows 7, 4 GB Ram, intel 930 #2.8 Ghz:
I've tested the methods given for n from 100,000 to 4 million. The ReplaceRepeated method does not do well for large lists.
update 2
Removed earlier result that was shown above in update1 due to my error in copying one of the tests.
The updated results are below. Leonid method is the fastest. Congratulation Leonid. A very fast method.
The test program is the following:
(*version 2.0 *)
runTests[sizeOfList_?(IntegerQ[#] && Positive[#] &)] :=
Module[{tests, lst, result, nasser, daniel, heike, leonid, andrei,
sjoerd, i, names},
nasser[lst_List] := Module[{a = lst},
Scan[(a[[#]] = If[a[[#]] == 0, a[[# - 1]], a[[#]]]) &,
Range[2, Length[a]]]
];
daniel[lst_List] := Module[{replaceWithPrior},
replaceWithPrior[ll_, n_: 0] :=
Module[{prev}, Map[If[# == 0, prev, prev = #] &, ll]
];
replaceWithPrior[lst]
];
heike[lst_List] := Flatten[Accumulate /# Split[lst, (#2 == 0) &]];
andrei[lst_List] := Module[{x, y, z},
ReplaceRepeated[lst, {x___, y_, 0, z___} :> {x, y, y, z},
MaxIterations -> Infinity]
];
leonid[lst_List] :=
FoldList[If[#2 == 0, #1, #2] &, First##, Rest##] & #lst;
sjoerd[lst_List] :=
FixedPoint[(1 - Unitize[#]) RotateRight[#] + # &, lst];
lst = RandomChoice[Join[ConstantArray[0, 10], Range[-1, 5]],
sizeOfList];
tests = {nasser, daniel, heike, leonid, sjoerd};
names = {"Nasser","Daniel", "Heike", "Leonid", "Sjoerd"};
result = Table[0, {Length[tests]}, {2}];
Do[
result[[i, 1]] = names[[i]];
Block[{j, r = Table[0, {5}]},
Do[
r[[j]] = First#Timing[tests[[i]][lst]], {j, 1, 5}
];
result[[i, 2]] = Mean[r]
],
{i, 1, Length[tests]}
];
result
]
To run the tests for length 1000 the command is:
Grid[runTests[1000], Frame -> All]
Thanks everyone for the answers.
Much (order of magnitude) faster than other solutions still:
FoldList[If[#2 == 0, #1, #2] &, First##, Rest##] &
The speedup is due to Fold autocompiling. Will not be so dramatic for non-packed arrays. Benchmarks:
In[594]:=
a=b=c=RandomChoice[Join[ConstantArray[0,10],Range[-1,5]],150000];
(b=Flatten[Accumulate/#Split[b,(#2==0)&]]);//Timing
Scan[(a[[#]]=If[a[[#]]==0,a[[#-1]],a[[#]]])&,Range[2,Length[a]]]//Timing
(c=FoldList[If[#2==0,#1,#2]&,First##,Rest##]&#c);//Timing
SameQ[a,b,c]
Out[595]= {0.187,Null}
Out[596]= {0.625,Null}
Out[597]= {0.016,Null}
Out[598]= True
This seems to be a factor 4 faster on my machine:
a = Flatten[Accumulate /# Split[a, (#2 == 0) &]]
The timings I get are
a = b = RandomChoice[Join[ConstantArray[0, 10], Range[-1, 5]], 10000];
(b = Flatten[Accumulate /# Split[b, (#2 == 0) &]]); // Timing
Scan[(a[[#]] = If[a[[#]] == 0, a[[# - 1]], a[[#]]]) &,
Range[2, Length[a]]] // Timing
SameQ[a, b]
(* {0.015815, Null} *)
(* {0.061929, Null} *)
(* True *)
FixedPoint[(1 - Unitize[#]) RotateRight[#] + # &, d]
is about 10 and 2 times faster than Heike's solutions but slower than Leonid's.
You question looks exactly like a task for ReplaceRepeated function. What it does basically is that it applies the same set of rules to the expression until no more rules are applicable. In your case the expression is a list, and the rule is to replace 0 with its predecessor whenever occurs in a list. So here is the solution:
a = {1, 0, 0, -1, 0, 0, 5, 0};
a //. {x___, y_, 0, z___} -> {x, y, y, z};
The pattern for the rule here is the following:
x___ - any symbol, zero or more repetitions, the beginning of the list
y_ - exactly one element before zero
0 - zero itself, this element will be replaced with y later
z___ - any symbol, zero or more repetitions, the end of the list
I like to use With[] with constants that I need to use in 2 different places.
Instead of typing the same long list of constants in 2 places, I have been trying to figure how to use a variable for this list, and then use this variable in the few places I want to use the list.
The problem is that I need to Hold the list and then ReleaseHold it later when time to use it, but I can't get this part right. (tried many things, nothing working for me)
Here is an example:
With[{$age = 2, $salary = 3},
x = $age
]
With[{$age = 2, $salary = 3},
y = $age
]
I do not want to type the same constants around (in my case, these are very long), and I was trying to do something like this:
c = HoldForm[{$age = 2, $salary = 3}]
With[Release[c],
x = $age
]
With[Release[c],
y = $age
]
I tried many other combinations of the above. So many version of Hold* and Release*, I find them all very confusing.
question is: Any one knows how to do the above, so I can reused the list in more than one place without actually copy it?
To put this in context, here is an example where this would be needed:
I can't do surround everything with With in Manipulate: (and I can't put a With outside Manipulate for what I am doing, everything must be inside Manipulate)
Manipulate[
Evaluate#With[{$age = 2, $salary = 3},
x;
$age,
{{x, $age, "age="}, 0, 10, 1}
]
]
Not valid syntax. (due to the "," needed to separate the Manipulate expression from the controls). (it now thinks With has 3 arguments)
I could ofcourse do
Manipulate[
With[{$age = 2, $salary = 3},
x;
$age
],
Evaluate#With[{$age = 2, $salary = 3},
{{x, $age, "age="}, 0, 10, 1}
]
]
But as you see, I had to copy the list of constants around.
If I can figure how to define the list once, I can put it in the Initialization section on Manipulate and use it, like this:
Manipulate[
With[ReleaseHold[myList],
x;
$age
],
Evaluate#With[ReleaseHold[myList],
{{x, $age, "age="}, 0, 10, 1}
],
Initialization :>
(
myList = HoldAll[{$age = 2, $salary = 3}];
)
]
I think what I want to do is possible, I just can't figure the correct commands to use for the Hold/Release hold part.
edit (1)
I thought I put an example of why I want to use constants in With.
I came up with this new method :) to allow me to simulate a record or a struct.
The constant values will be the named field of the record (which is just a list really).
For field name, I give it a sequential number, (I start from 1) and I use $field=number, and then in the code, I write struct[[$field]]=... to access the field.
I need to share the values of the named fields to the struct between the Manipulate expression and the control area, since both need to use the same struct.
Here is a simple example below of a Manipulate that reads the age and current salary from the UI and the expression and assigns new salary based on current salary and ago.
The record is used to communicate the data between the control area and the expression and lower level functions.
In my current demo, I have hundreds of such parameters, (I actually have now few demos, all in one demo, and I flip between different UI layouts (controls) based on which choice is selected on the UI) and using records will simplify life for me, since now I can make function calls, and just pass few parameters, records that contain the UI parameters, and not 100's of the individual parameters, which is what I have to do now. As I said many times before, Mathematica needs a real record/struct as a basic data struct, in addition to List, and Array and such, which is integrated into M.
(the UI parameters have to be send, all, to lower level functions, and there is no other choice than doing this. I do not want to use global variables. Bad design).
I also can now pass this record by reference If I want to to allow updates to happen into it inside other much lower level functions. I am still evaluating this method to see if I can actually use it in my main code.
(*verison 1.1*)
Manipulate[
With[{$age = 1, $salary = 2, $newSalary = 3},
updateRecord[record_] := Module[{},
(*update/process UI input*)
record[[$newSalary]] = record[[$salary]] + record[[$age]]*10;
(*return result*)
record
];
(*call lower level function to process UI parameters*)
myRecord = updateRecord[Unevaluated#myRecord];
(*display the result *)
Grid[{
{"age=", myRecord[[$age]]},
{"current salary=", myRecord[[$salary]]},
{"new salary=", myRecord[[$newSalary]]}
}]
],
(* build the UI controls *)
Evaluate#With[{$age = 1, $salary = 2, $newSalary = 3},
Grid[{
{"age=",
Manipulator[Dynamic[age, {age = #; myRecord[[$age]] = age} &],
{10, 100, 1}, ImageSize -> Tiny], Dynamic[age]},
{"salary=",
Manipulator[
Dynamic[salary, {salary = #; myRecord[[$salary]] = salary} &],
{10, 10000, 10}, ImageSize -> Tiny], Dynamic[salary]}
}
]
],
{{myRecord, {10, 100, 100}}, None},
{{age, 10}, None},
{{salary, 1000}, None},
TrackedSymbols -> {age, salary}
]
edit(2)
On trying to use Leonid below, I can use it in the Manipulate expression, but can't figure how to use in the control area.
Here is the original example using With in 2 places:
Manipulate[
With[{$age = 2, $salary = 3},
x + $age
],
Evaluate#With[
{$age = 2, $salary = 3},
{{x, $age, "age="}, 0, 10, 1}
],
{x, None}
]
now using the new Leonid method below, this is what I have so far:
Manipulate[
env[
x + $age
],
Evaluate#With[
{$age = 2, $salary = 3},
{{x, $age, "age="}, 0, 10, 1}
],
{x, None},
Initialization :>
(
ClearAll[makeCustomEnvironment];
SetAttributes[makeCustomEnvironment, HoldAll];
makeCustomEnvironment[values : (_Symbol = _) ..] :=
Function[code, With ## Hold[{values}, code], HoldAll];
env = makeCustomEnvironment[$age = 2, $salary = 3];
)
]
But is it possible to use it for the control also? I can't just do this:
Manipulate[
env[
x + $age
],
env[
{$age = 2, $salary = 3},
{{x, $age, "age="}, 0, 10, 1}
],
{x, None},
Initialization :>
(
ClearAll[makeCustomEnvironment];
SetAttributes[makeCustomEnvironment, HoldAll];
makeCustomEnvironment[values : (_Symbol = _) ..] :=
Function[code, With ## Hold[{values}, code], HoldAll];
env = makeCustomEnvironment[$age = 2, $salary = 3];
)
]
as the above gives many errors.
edit(3)
deleted as was incorrect
edit (4)
deleted content of edit(3) above as it included a user error on my side reporting an issue.
Here is the WRI support response to why I was getting the error
Manipulate::vsform: Manipulate argument env[{{age,100,age},10,200,1}] does
not have the correct form for a variable specification. >>
When I was writing the following code:
Manipulate[
env[
record[[$age]] = age;
record[[$salary]] = 60*age;
{record[[$age]], record[[$salary]]}
],
env[
{{age, 100, "age"}, 10, 200, 1}
],
{{record, {40, 5}}, None},
{{salary, 40000}, None},
TrackedSymbols :> {age},
Initialization :>
(
makeCustomEnvironmentAlt =
Function[Null, Function[code, With ## Hold[{##}, code], HoldAll],
HoldAll];
env = makeCustomEnvironmentAlt[$age = 1, $salary = 2];
)
]
This is the support explanation of why this error came showed up:
The issue is specifically with the section:
Evaluate#env[{{age, 100, "age"}, 10, 200, 1}]
Manipulate doesn't really evaluate until it gets to the Initialization
option, but it will check its input for correct form. Mathematica reads the
main body of the Manipulate before running the Initialization option. This
is can be verified by using a Print statement:
Initialization -> (Print["Test"];
makeCustomEnvironmentAlt =
Function[Null, Function[code, With ## Hold[{##}, code], HoldAll],
HoldAll];
env = makeCustomEnvironmentAlt[$age = 1, $salary = 2];
Print["Test"])
Test does not print.
Getting around this will be probably not be clean.
....
Having the code for the controller for age depend on evaluation of
some function which must be initialized does not appear to be possible
with simply Manipulate.
I hope this information helps. And thanks for everyone's help and also for WRI support and explanation.
What I'd do is to write a function generator to create custom (lexical) environments:
ClearAll[makeCustomEnvironment];
SetAttributes[makeCustomEnvironment, HoldAll];
makeCustomEnvironment[values : (_Symbol = _) ..] :=
Function[code, With ## Hold[{values}, code], HoldAll];
This takes a declaration list and creates a pure function which uses With internally with encapsulated constants. I used With##Hold[...] to fool the renaming mechanism of Function so that it would not rename the variables inside With (instead of With, one could use the withRules function suggested by #Szabolcs, which would lead to a slightly different substitution semantics).
Now, we create our custom function:
env = makeCustomEnvironment[$age = 2, $salary = 3];
And use it like so:
In[25]:=
env[x=$age];
x
Out[26]= 2
In[27]:=
env[y=$age];
y
Out[28]= 2
The advantage of this construct with respect to a saved variable (with rules or whatever) is that here we encapsulate behavior rather than state. This is arguably cleaner and more along the functional programming paradigm (we create here a closure rather than instantiate a class).
EDIT
Apparently, the rules for demonstrations are pretty strict, and won't allow the sugested code. This version will hopefully be ok:
makeCustomEnvironmentAlt =
Function[Null,
Function[code, With ## Hold[{##}, code], HoldAll],
HoldAll]
But you'll have to remember the format of input arguments (which was clear for the initial solution due to the use of suggestive pattern).
I would recommend using Replace and Rules instead of With for this purpose. See for example the withRules function I described here, which I use for a purpose similar to what you describe: injecting a predefined list of constants into code without having to define those constants as global variables.
ClearAll[withRules]
SetAttributes[withRules, HoldAll]
withRules[rules_, expr_] :=
Internal`InheritedBlock[
{Rule, RuleDelayed},
SetAttributes[{Rule, RuleDelayed}, HoldFirst];
Unevaluated[expr] /. rules
]
Usage:
constants = { a -> 1, b :> 2+2 }
withRules[ constants, a+b ]
Note that you can use both -> and :> so there's no need for Holding the constants.
A word of warning:
Also note that it is different from With in that it doesn't really localize variables. Consider With[{x=1}, With[{x=2}, x]], which renames the x in the inner With to avoid conflict. withRules doesn't do this: is ruthlessly replaces every x within withRules[{x-> ...}, ...] regardless of whether it appears in another Function, With or Module or not.
Regarding your Manipulate example, I would just wrap the whole Manipulate with a With, as in
With[
{age = 2},
Manipulate[{x, age}, {{x, age}, 0, 10, 1}]
]
Can you explain why you want to have everything inside the Manipulate (if you're not manipulating age), and why you can't just wrap it with the With?