BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
rosiecao2509
Fluorite | Level 6

I want to simulate 1000 sets comprising 6 weights (w1, w2, w3, w4, w5, w6). Their values are uniformly distributed ranging from -1 to 1 (but their absolute values are greater than 0.01. The sum of their absolute values is added to 1. 

 

Can anyone please help?

1 ACCEPTED SOLUTION

Accepted Solutions
FreelanceReinh
Jade | Level 19

Hello @rosiecao2509,

 

As mkeintz has already pointed out, there is no probability distribution satisfying all your requirements. Indeed, note that for |wi| (i=1, ..., 6) with a uniform distribution on [0.01, 1] you would have the expectation E(|w1|+...+|w6|) = 6*(0.01+1)/2 = 3.03, not 1 as per your requirement.

 

I would probably start with a Dirichlet distribution, Dir(a). For example, consider the special case a=(1,1,1,1,1,1), which yields the uniform distribution over the set of points with positive coordinates in six-dimensional space whose coordinates sum to 1. Once you have generated a random vector (x1, ..., x6) from this distribution, you easily get corresponding weights wi: Just apply the linear transformation xi → 0.01+0.94*xi and generate a random sign.

 

Here is SAS code implementing this approach:

data want(drop=i j);
call streaminit(27182818);
array w[6];
array x[6] _temporary_;
do i=1 to 1000;
  do j=1 to dim(w);
    x[j]=rand('expo');
  end;
  do j=1 to dim(w);
    w[j]=(2*rand('bern',0.5)-1)*(0.01+0.94*x[j]/sum(of x[*]));
  end;
  output;
end;
run;

(Note that the exponential distribution with default parameter 1 is the same as the Gamma(1,1) distribution mentioned in the Wikipedia article.)

 

In particular, this approach ensures that the six weights have the same probability distribution.

View solution in original post

3 REPLIES 3
mkeintz
PROC Star

The moment you require the sum of absolute values of w1..w6 to be 1, you can no longer expect each weight w to be uniformly distributed w~uniform(-1,1). 

 

True, you could distribute w1~uniform(-1,+1), excluding (-0.01,+0.01).  Actually you'd distribute absolute |w1|~uniform(0.01,+1), and then randomly generate a positive or negative sign.  Or to prevent any of w2 through w6 being less than 0.01, you would uniformly distribute |w1|~uniform(0.01,0.95).

 

Let's say the absolute value of |w1| is 0.4.  Then you could uniformly distribute absolute |w2| over (0.01,0.55), i.e. (0.01, 0.95-0.4), and again randomly generate a sign.

 

You could similarly generate w3 through w5, and finally directly calculate absolute |w6| from the others, and randomly give it a sign.  

 

But clearly the only weight distributed uniform(-1,1) is w1.  

 

So could you clarify?

 

 

 

 

--------------------------
The hash OUTPUT method will overwrite a SAS data set, but not append. That can be costly. Consider voting for Add a HASH object method which would append a hash object to an existing SAS data set

Would enabling PROC SORT to simultaneously output multiple datasets be useful? Then vote for
Allow PROC SORT to output multiple datasets

--------------------------
FreelanceReinh
Jade | Level 19

Hello @rosiecao2509,

 

As mkeintz has already pointed out, there is no probability distribution satisfying all your requirements. Indeed, note that for |wi| (i=1, ..., 6) with a uniform distribution on [0.01, 1] you would have the expectation E(|w1|+...+|w6|) = 6*(0.01+1)/2 = 3.03, not 1 as per your requirement.

 

I would probably start with a Dirichlet distribution, Dir(a). For example, consider the special case a=(1,1,1,1,1,1), which yields the uniform distribution over the set of points with positive coordinates in six-dimensional space whose coordinates sum to 1. Once you have generated a random vector (x1, ..., x6) from this distribution, you easily get corresponding weights wi: Just apply the linear transformation xi → 0.01+0.94*xi and generate a random sign.

 

Here is SAS code implementing this approach:

data want(drop=i j);
call streaminit(27182818);
array w[6];
array x[6] _temporary_;
do i=1 to 1000;
  do j=1 to dim(w);
    x[j]=rand('expo');
  end;
  do j=1 to dim(w);
    w[j]=(2*rand('bern',0.5)-1)*(0.01+0.94*x[j]/sum(of x[*]));
  end;
  output;
end;
run;

(Note that the exponential distribution with default parameter 1 is the same as the Gamma(1,1) distribution mentioned in the Wikipedia article.)

 

In particular, this approach ensures that the six weights have the same probability distribution.

rosiecao2509
Fluorite | Level 6
Thanks a lot Reinhard,
It works perfectly well. Thank you so much for your help.

Wish you all the best.

hackathon24-white-horiz.png

The 2025 SAS Hackathon Kicks Off on June 11!

Watch the live Hackathon Kickoff to get all the essential information about the SAS Hackathon—including how to join, how to participate, and expert tips for success.

YouTube LinkedIn

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 3 replies
  • 946 views
  • 2 likes
  • 3 in conversation