Reputation: 43
my problem is following: I need to create some random values for scheduling. For example process times are given. Lets say a job j on a machine i gets a random value between (1,99). thats the time the jobs needs on this machine.
Now, I need to manipulate this random values. I like to say of all random process times, 20% of them are zero process times. So does anybody know how it is possible to give an array with integers a specific amount with a specific time??
here the normal random:
p_machine_job_completionTime = new int[Constants.numberMachines][];
for (i = 0; i < Constants.numberMachines; i++)
{
p_machine_job_completionTime[i] = new int[Constants.numberJobs];
for (j = 0; j < Constants.numberJobs; j++)
{
p_machine_job_completionTime[i][j] = random.Next(1, 99);
}
}
Now, jobs may skip a machine and consequently have a processing time of 0. Is it possible to limit the random values, with guaranteeing that x% of all my random values has the value 0 ?? e.g.:
20% of p_machine_job_completionTime[i][j] = 0
80% of p_machine_job_completionTIme[i][j] = random (1,99)
I am very thankful for any small any tiny advice.
Upvotes: 4
Views: 144
Reputation: 23796
I think what the existing answers are missing is this important point:
"Is it possible to limit the random values, with guaranteeing that x% of all my random values has the value 0"
If you need to guarantee that at the end of the day some random exactly x% of the items are given a value of zero, then you can't use random as in the answer from @Douglas. As @Douglas says, "To get 0 with 20% probability." But as stated in the question we don't want 20% probability, we want EXACTLY 20%, and the other exactly 80% to have random values. I think the code below does what you want. Filled in some values for numberMachines
and numberJobs
so the code can be run.
int numberMachines = 5;
int numberJobs = 20;
Random random = new Random();
var p_machine_job_completionTime = new int[numberMachines][];
var theTwentyPercent = new HashSet<int>(Enumerable.Range(0,(numberJobs * numberMachines) -1 ).OrderBy(x => Guid.NewGuid()).Take(Convert.ToInt32((numberMachines * numberJobs) * 0.2)));
for (int i = 0; i < numberMachines; i++) {
p_machine_job_completionTime[i] = new int[numberJobs];
for (int j = 0; j < numberJobs; j++) {
int index = (i * numberJobs) + j;
if (theTwentyPercent.Contains(index)) {
p_machine_job_completionTime[i][j] = 0;
}
else {
p_machine_job_completionTime[i][j] = random.Next(1, 99);
}
}
}
Debug.Assert( p_machine_job_completionTime.SelectMany(x => x).Count(val => val==0) == (numberMachines * numberJobs) * 0.2 );
Upvotes: 0
Reputation: 54897
One way to do this would be by generating two random values: One for determining whether to use 0, and (possibly) another to generate non-zero values. However, you can combine both randoms into one by increasing the range of your random values by the appropriate amount, and converting any results above your limit to 0:
int val = random.Next(1, 123);
if (val >= 99)
val = 0;
In this case, your target range contains 98 possible values (1 to 98, since the upper bound is exclusive). To get 0 with 20% probability, you need to extend the range of your random generator to 1 / (1 - 20%), or 125% of its present value, which would be 123.
Upvotes: 1
Reputation: 6366
I think that you do not need to include this within Random in your case. You could simply use modulo as a part of your for loop:
p_machine_job_completionTime = new int[Constants.numberMachines][];
int counter = 0;
for (i = 0; i < Constants.numberMachines; i++)
{
p_machine_job_completionTime[i] = new int[Constants.numberJobs];
for (j = 0; j < Constants.numberJobs; j++)
{
if( counter%5 == 0)
{
p_machine_job_completionTime[i][j] = 0;
}
else
{
p_machine_job_completionTIme[i][j] = random (1,99);
}
counter++;
}
}
Upvotes: 0
Reputation: 186803
Just separate two cases: 20% when 0 should be returned and 80% when 1..99 is the outcome
Random random;
...
int value = random.Next(5) == 0 ? 0 : random.Next(99) + 1;
Upvotes: 1