Group Abstract Group Abstract

Message Boards Message Boards

0
|
4.5K Views
|
12 Replies
|
2 Total Likes
View groups...
Share
Share this post:

Module doesn't recognize function parameters

Posted 2 years ago

Hello everyone. I hope you can help me solve this problem. I want to find if the functions fA1, fB2, fC3 are within the range LowerLimit <= hF1[fA1, fB2, fC3] <= UpperLimit and save the matching values into the list selectedData. The code must work for arbitrary functions.

Running the code shows the following error:

Set::setraw: Cannot assign to raw object 1.80609586246897`.

Set::setraw: Cannot assign to raw object 1.4410360862456661`.

Set::setraw: Cannot assign to raw object 1.0125069354448308`.

General::stop: Further output of Set::setraw will be suppressed during this calculation.

below the code: (* Step 1.- Construction of test functions *)

fA1[w1_,w2_,w3_,w4_]:= 10+w1+w2+w3+w4

fB2[r1_,r2_,r3_,r4_]:= 1+r1+r2+r3+r4

fC3[t1_]:=5*t1

(* Step 2.- Cconstruction of the rule where the functions will be evaluated*)

hF1[fA1_,fB2_,fC3_]:= (2*fA1)*(3*fB2)*(4*fC3)

(* Step 3.- Construction of the Main function  *)
GT5[fA1_,fB2_,fC3_,x1_,x1min_,x1max_,x2_,x2min_,x2max_,x3_,x3min_,x3max_,x4_,x4min_,x4max_,NN_]:=
Module[
 {
  p1, p1min, p1max, 
  p2, p2min, p2max,
  p3, p3min, p3max,
  p4, p4min, p4max,
  n, selectedData,LowerLimit,UpperLimit
 },
 LowerLimit = 1;
 UpperLimit = 10000000;
 selectedData={};
 p1=x1; p1min=x1min; p1max=x1max;
 p2=x2; p2min=x2min; p2max=x2max; 
 p3=x3; p3min=x3min; p3max=x3max; 
 p4=x4; p4min=x4min; p4max=x4max;
 n=1;
 Do[
   {  
    x1 = RandomReal[{p1min, p1max}];
    x2 = RandomReal[{p2min, p2max}];
    x3 = RandomReal[{p3min, p3max}];
    x4 = RandomReal[{p4min, p4max}]; 
    If[
       LowerLimit <= hF1[fA1, fB2, fC3] <= UpperLimit,
       selectedData = AppendTo[selectedData, {p1,p2,p3,p4,hF1[fA1, fB2, fC3]}], 
       0
      ]; 
    }, {n, NN}
   ];
   selectedData
]

Now, run the instruction:

GT5[
    fA1[D1+D2,D3,D1,D2],
    fB2[D1+D2,D3,D1,D2],
    fC3[2*D1],
    D1,1,2,
    D2,1,2,
    D3,1,2,
    D4,1,2,
    10
   ]

and I get:

During evaluation of In[18]:= Set::setraw: Cannot assign to raw object 1.80609586246897`.

During evaluation of In[18]:= Set::setraw: Cannot assign to raw object 1.4410360862456661`.

During evaluation of In[18]:= Set::setraw: Cannot assign to raw object 1.0125069354448308`.

During evaluation of In[18]:= General::stop: Further output of Set::setraw will be suppressed during this calculation.

Out[18]= {{1.8061, 1.44104, 1.01251, 1.13217, 64553.9}, {1.8061, 
  1.44104, 1.01251, 1.13217, 64553.9}, {1.8061, 1.44104, 1.01251, 
  1.13217, 64553.9}, {1.8061, 1.44104, 1.01251, 1.13217, 
  64553.9}, {1.8061, 1.44104, 1.01251, 1.13217, 64553.9}, {1.8061, 
  1.44104, 1.01251, 1.13217, 64553.9}, {1.8061, 1.44104, 1.01251, 
  1.13217, 64553.9}, {1.8061, 1.44104, 1.01251, 1.13217, 
  64553.9}, {1.8061, 1.44104, 1.01251, 1.13217, 64553.9}, {1.8061, 
  1.44104, 1.01251, 1.13217, 64553.9}}

I will appreciate your help or comments.

Precisely, I want to use functions whose inputs will not always be like this fA1[x1 + x2, x3, x1, x2], fB2[x1 + x2, x3, x1, x2], fC3[2*x1] I've been able to get it to work by removing Module and adding Clear[x1,x2,x3,x4] to the end, but I think there must be a better way to solve it.

GT5[fA1_,fB2_,fC3_,x1_,x1min_,x1max_,x2_,x2min_,x2max_,x3_,x3min_,x3max_,x4_,x4min_,x4max_,NN_]:=
{
selectedData = {};
LowerLimit = 1;
UpperLimit = 10000000;
selectedData = {};
Do[
{
x1 = RandomReal[{x1min, x1max}];
x2 = RandomReal[{x2min, x2max}];
x3 = RandomReal[{x3min, x3max}];
x4 = RandomReal[{x4min, x4max}]; 
If[
LowerLimit <= hF1[fA1, fB2, fC3] <= UpperLimit,
selectedData = AppendTo[selectedData, {x1,x2,x3,x4,hF1[fA1, fB2, fC3]}], 
0]
}, {n, NN}
];
Print[selectedData];
Clear[x1,x2,x3,x4];
}
Attachments:
POSTED BY: Tomás Valencia
12 Replies
Posted 2 years ago

I've been very confused about your question, but I think I've finally figured it out. Here's what I think you're trying to achieve:

  • You want to define a predicate that depends on some arguments that in turn you want to depend on some functions.
  • Those other functions can be arbitrary, and they don't all have the same signature.
  • While they don't have the same signature, they do all depend on the same overall set of arguments, so you somehow need to pass in all of these lower level arguments and feed them to your functions in some pre-specified manner

If all of that's correct, then here's a possible answer. I'll start by defining a function that does all the work of putting things together correctly. It'll be a bit confusing, but I'll demonstrate how to use it.

SpecialFunction[combiner_, lower_, upper_, count_][fns__][ranges : {_, _} ...] :=
 With[
  {randomVals = Table[RandomReal /@ {ranges}, count],
   applicators = MapApply /@ {fns},
   checker = Function[Null, lower <= combiner[##] <= upper]},
  With[
   {appliedVals = Through[applicators[randomVals]]},
   Transpose[{randomVals, Transpose@appliedVals, checker @@@ Transpose[appliedVals]}]]]

The first set of arguments correspond to how you want to do your checking (basically your hF1 and the less-equal tests). The second set of arguments are the functions you want to apply to the arguments (your fA1, fB2, and fB3). We'll need to put them in a special form, but we'll get to that later. The last set of arguments are the ranges in which you want to pick random values for each argument that will be fed to the functions. The way this is set up, you can pass any number of fns and any number of ranges.

Let's try it out with some dummy arguments so you can see what it does:

SpecialFunction[someCombiner, 0, 100, 2][func1, func2, func3][{1, 5}, {10, 20}]

{{{4.62279, 16.5337}, {func1[4.62279, 16.5337], func2[4.62279, 16.5337], func3[4.62279, 16.5337]}, 0 <= someCombiner[func1[4.62279, 16.5337], func2[4.62279, 16.5337], func3[4.62279, 16.5337]] <= 100}, {{1.44301, 17.4801}, {func1[1.44301, 17.4801], func2[1.44301, 17.4801], func3[1.44301, 17.4801]}, 0 <= someCombiner[func1[1.44301, 17.4801], func2[1.44301, 17.4801], func3[1.44301, 17.4801]] <= 100}}

Let's focus on just the first item in this output (note that the random numbers will be different when you try this yourself).

{{4.62279, 16.5337}, {func1[4.62279, 16.5337], func2[4.62279, 16.5337], func3[4.62279, 16.5337]}, 0 <= someCombiner[func1[4.62279, 16.5337], func2[4.62279, 16.5337], func3[4.62279, 16.5337]] <= 100}

We have our random values, the values we get when we apply our intermediate functions, and then the result of applying our combiner and the limits. We get that kind of output for as many trials as we do (which is determined by count).

Now, the challenge we have is that you've got several low-level arguments that get fed to the intermediate functions in different ways, in terms of count, order, and even more intermediate computations (like adding the first and second or doubling the first). So, we need to define our intermediate functions by wrapping our actual functions. You can do this with OperatorApplied or CurryApplied, but rather than introduce yet another complication, let's just use plain Function.

wrappedFA1 = Function[Null, fA1[#1 + #2, #3, #1, #2]];
wrappedFB2 = Function[Null, fB2[#1 + #2, #3, #1, #2]];
wrappedFC3 = Function[Null, fC3[2*#1]];

Now we can pass these to SpecialFunction. I'll also change it to use the parameters you were using.

SpecialFunction[hF1, 1, 10000000, 2][wrappedFA1, wrappedFB2, wrappedFC3][{1, 2}, {1, 2}, {1, 2}, {1, 2}]

{{{1.13805, 1.77789, 1.77946, 1.09484}, {fA1[2.91594, 1.77946, 1.13805, 1.77789], fB2[2.91594, 1.77946, 1.13805, 1.77789], fC3[2.2761]}, 1 <= hF1[fA1[2.91594, 1.77946, 1.13805, 1.77789], fB2[2.91594, 1.77946, 1.13805, 1.77789], fC3[2.2761]] <= 10000000}, {{1.2858, 1.52344, 1.41616, 1.93163}, {fA1[2.80924, 1.41616, 1.2858, 1.52344], fB2[2.80924, 1.41616, 1.2858, 1.52344], fC3[2.5716]}, 1 <= hF1[fA1[2.80924, 1.41616, 1.2858, 1.52344], fB2[2.80924, 1.41616, 1.2858, 1.52344], fC3[2.5716]] <= 10000000}}

Now we're ready to use the definitions you provided for the fA1 and so forth.

hF1[fA1_, fB2_, fC3_] := (2*fA1)*(3*fB2)*(4*fC3);
fA1[w1_, w2_, w3_, w4_] := 10 + w1 + w2 + w3 + w4;
fB2[r1_, r2_, r3_, r4_] := 1 + r1 + r2 + r3 + r4;
fC3[t1_] := 5*t1;

Finally, let's evaluate our SpecialFunction again:

SpecialFunction[hF1, 1, 10000000, 2][wrappedFA1, wrappedFB2, wrappedFC3][{1, 2}, {1, 2}, {1, 2}, {1, 2}]

{{{1.23086, 1.13019, 1.20986, 1.62693}, {15.932, 6.93197, 12.3086}, True}, {{1.96329, 1.14836, 1.4373, 1.46791}, {17.6606, 8.66061, 19.6329}, True}}

At this point, you can select the ones with True.

Comments/suggestions:

  • Looking at it now, I realize that it might have been useful to add the value of the combiner to the output. I don't want to worry about copy-paste errors at this point, so I'll let you decide how you want your results to be displayed.
  • This currently assumes that hF1 takes its arguments in the order of the fns. If you want to play with that, then you'd want to wrap hF1 like we did for fA1 et al.
  • Obviously, you need to provide as many argument range specs as you'll need for the fns. And you'll need to provide as many fns as you'll need for the combiner.
  • You could work the final selection into SpecialFunction, but I thought it was easier to demonstrate without that step, so that's an exercise I leave to you.
  • This could all be simplified if there were known constraints on your functions. Given that you wanted a general solution that works for any arbitrary set of functions, you'll need something at about this level of complexity.
POSTED BY: Updating Name
Posted 2 years ago

Ugh. I see an edit I need to make, but for some reason that post was attributed to "Updating Name" and so now I can't edit my own post! I was just going to fix the line that was truncated, but hopefully it's not too unclear as it stands.

POSTED BY: Eric Rimbey
POSTED BY: Tomás Valencia

not really sure that you are actually wanting to find the functions. The code looks for a vector of 4 random numbers that when evaluated by a function stay within a range.

The function you are evaluating is

fA1[w1_, w2_, w3_, w4_] := 10 + w1 + w2 + w3 + w4
fB2[r1_, r2_, r3_, r4_] := 1 + r1 + r2 + r3 + r4
fC3[t1_] := 5*t1
hF1[fA1_, fB2_, fC3_] := (2*fA1)*(3*fB2)*(4*fC3)

FullSimplify[
 hF1[fA1[d1 + d2, d3, d1, d2], fB2[d1 + d2, d3, d1, d2], fC3[2*d1]]]

which evaluates to

240 d1 (1 + 2 d1 + 2 d2 + d3) (2 (5 + d1 + d2) + d3)

so:

f[{d1_, d2_, d3_, d4_}] := 
 240 d1 (1 + 2 d1 + 2 d2 + d3) (2 (5 + d1 + d2) + d3)

the input parameters are

n = 100
{min, max} = {1, 10^6};
ranges = {{1, 2}, {1, 2}, {1, 2}, {1, 2}};

so this would solve the problem in one line.

Column[{#, f[#]} & /@ Select[Transpose[RandomReal[#, n] & /@ ranges], min < f[#] < max &]]

or step by step

(*gerenrate the random vectors where each row of ds = {d1, d2, d3, d4}*)
ds = Transpose[RandomReal[#, n] & /@ ranges]
(*select the values for which each row of ds remains in the limits*)
sel = Select[ds, min < f[#] < max &]
(*show the output show the output, where it recomputes f again, which is not needed*)
Column[{#, f[#]} & /@ sel]
POSTED BY: Martijn Froeling

Thanks for reviewing the code and providing your help. The problem is that the code must work for arbitrary functions.

POSTED BY: Tomás Valencia
POSTED BY: Martijn Froeling
Posted 2 years ago
POSTED BY: Eric Rimbey
Posted 2 years ago
POSTED BY: Eric Rimbey

Thank you very much for reviewing my code. Precisely, I want to use functions whose inputs will not always be like this fA1[x1 + x2, x3, x1, x2], fB2[x1 + x2, x3, x1, x2], fC3[2*x1] I've been able to get it to work by removing Module and adding Clear[x1,x2,x3,x4] to the end, but I think there must be a better way to solve it.

GT5[fA1_,fB2_,fC3_,x1_,x1min_,x1max_,x2_,x2min_,x2max_,x3_,x3min_,x3max_,x4_,x4min_,x4max_,NN_]:=
{
selectedData = {};
LowerLimit = 1;
UpperLimit = 10000000;
selectedData = {};
Do[
{
x1 = RandomReal[{x1min, x1max}];
x2 = RandomReal[{x2min, x2max}];
x3 = RandomReal[{x3min, x3max}];
x4 = RandomReal[{x4min, x4max}]; 
If[
LowerLimit <= hF1[fA1, fB2, fC3] <= UpperLimit,
selectedData = AppendTo[selectedData, {x1,x2,x3,x4,hF1[fA1, fB2, fC3]}], 
0]
}, {n, NN}
];
Print[selectedData];
Clear[x1,x2,x3,x4];
}
POSTED BY: Tomás Valencia
Posted 2 years ago

When you define this:

hF1[fA1_,fB2_,fC3_]:= (2*fA1)*(3*fB2)*(4*fC3)

Are you using the argument names fA1 and so forth as just a mnemonic device, or are you expecting some actual computational link to the functions fA1 etc that you previous defined?

POSTED BY: Eric Rimbey
Posted 2 years ago
POSTED BY: Eric Rimbey
POSTED BY: Tomás Valencia
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard