Solution
Bhaumik answered on
Feb 15 2024
CS3360: Homework #2
Problem 2 Using a pseudo-random number generation function (e.g., rand () in C or other equivalent functions in other languages) that generates uniformly distributed random numbers, write three functions that generate the following: [3 pts each]
(a) 100 uniformly distributed integers between 0 and 99.
Function: def generate_uniform_integers():
return [random.randint(0, 99) for _ in range(100)]
Output: 100 Uniform Integers between 0 and 99: [89, 95, 59, 0, 51, 84, 3, 93, 45, 84, 29, 97, 72, 50, 41, 94, 55, 34, 51, 36, 20, 68, 46, 19, 55, 83, 38, 70, 76, 62, 85, 19, 50, 37, 97, 54, 39, 96, 11, 42, 10, 81, 80, 20, 5, 8, 38, 33, 98, 21, 49, 42, 35, 82, 24, 32, 87, 54, 27, 89, 70, 30, 87, 9, 14, 30, 81, 45, 21, 82, 31, 29, 35, 6, 52, 85, 23, 15, 98, 41, 63, 36, 83, 81, 83, 33, 80, 34, 41, 89, 13, 33, 17, 13, 10, 55, 16, 12, 51, 42]
(b) 100 uniformly distributed floating numbers between 0.25 and 0.5.
Function: def generate_uniform_floats():
return [random.uniform(0.25, 0.5) for _ in range(100)]
Output: 100 Uniform Floats between 0.25 and 0.5: [0.4159522261018752, 0.49832464322828923, 0.42957004697558965, 0.4915356389149934, 0.4784865492532625, 0.4024150995353893, 0.3633020591471934, 0.3055895112071724, 0.2890343422779923, 0.2710160225062585, 0.43762203609242606, 0.46197261091994374, 0.45531838288240667, 0.4620325367069085, 0.47544783805987434, 0.4910382278101913, 0.2692916061958772, 0.40331414394408344, 0.31592554717082205, 0.43309711681442353, 0.3597510275991015, 0.418844693292574, 0.4571695266143384, 0.32444806775427715, 0.47632859593170673, 0.4292681877756737, 0.47529983895427874, 0.43514897513607165, 0.27586375902292704, 0.28051835289084853, 0.3500362159321748, 0.4387513852304902, 0.48368454913789327, 0.432617762837452, 0.4968972939879842, 0.42322351381936396, 0.3174195932807661, 0.2777974515118987, 0.47177168002961023, 0.3812406476771804, 0.378408008393046, 0.35574619332564794, 0.34370265113779375, 0.44003429123984406, 0.3638056092773423, 0.29933822867443827, 0.40043058250074265, 0.2619714404192086, 0.47649097555248787, 0.29661506703414475, 0.3221352261989956, 0.43805128073115573, 0.3844973360116688, 0.28868999181260974, 0.46730578063307304, 0.2602230744211454, 0.49695461953825404, 0.25537067985437484, 0.47152906008646966, 0.3184811411207513, 0.3904049204680483, 0.29892432921179835, 0.3475808491354109, 0.2983881985903831, 0.3682371126463957, 0.42667068900327365, 0.32405224563822865, 0.47545265218203414, 0.3635335692231434, 0.4389506327630574, 0.3148806195952519, 0.3706449426887809, 0.4483123870344828, 0.3024000139213606, 0.45340466113182576, 0.4280392156924191, 0.2978160564752913, 0.3295799365934441, 0.4794905847786969, 0.35797280718340446, 0.3226434574685799, 0.47349052282020015, 0.27341787596526734, 0.4850439964759171, 0.3309387830785312, 0.2698292278070442, 0.38444061125575696, 0.3198669213002726, 0.2746865688628859, 0.289561291298467, 0.2902049197630884, 0.29344715575041713, 0.4658015605434067, 0.35955306456475944, 0.3260956187784022, 0.2724006255742101, 0.3550295486105014, 0.3129736709229278, 0.4149342914666453, 0.2706351889892363]
(c) 100 numbers in which the number 1 is produced with probability 0.5, the number 2 with probability 0.2, otherwise a floating number between 3 and 4.
Function:
def generate_custom_numbers():
numbers = []
for _ in range(100):
rand_num = random.random()
if rand_num < 0.5:
numbers.append(1)
elif rand_num < 0.7:
numbers.append(2)
else:
numbers.append(random.uniform(3, 4))
return numbers
Output: 100 Custom Numbers: [3.6996447344303203, 1, 1, 1, 2, 1, 2, 1, 3.9066227039152386, 1, 2, 2, 1, 3.3929199552219105, 2, 1, 2, 2, 1, 1, 1, 3.018850208041843, 3.951075505775231, 1, 3.920535122181302, 2, 2, 3.4423904703873323, 3.355374638388671, 1, 2, 1, 2, 1, 3.885585584641813, 2, 1, 1, 3.874423805306625, 3.0513577261039004, 1, 1, 3.215082783968139, 2, 3.0266139785753348, 1, 1, 1, 3.9963087608103214, 1, 3.2970577012696323, 1, 1, 1, 1, 2, 2, 1, 3.7738581920523138, 1, 2, 3.1104336443303198, 1, 1, 2, 1, 3.5455568467405723, 1, 2, 3.2122570677510347, 1, 3.0725055980485294, 1, 1, 1, 3.7123830211462683, 3.133900891747674, 1, 3.0014637274170783, 1, 1, 2, 1, 2, 2, 1, 1, 2, 2, 1, 1, 1, 1, 3.263712274737507, 1, 2, 1, 3.650067488546326, 3.8628996499032118, 3.2159237238061524]
Assumptions made:
[1] For generating uniformly distributed integers between 0 and 99, I used the random.randint() function which includes both endpoints.
[2] For generating uniformly distributed floating numbers between 0.25 and 0.5, I used the random.uniform() function which generates a random floating point number within the specified range.
[3] For generating custom numbers where 1 is produced with probability 0.5, 2 with probability 0.2, and otherwise a floating number between 3 and 4, I used the random.random() function which generates a random float in the half-open interval [0.0, 1.0).
Problem 3 Using a pseudo-random number generation function (e.g., rand() in C or other equivalent functions in other languages) that generates uniformly distributed random numbers, generate a workload for a system that is composed of 1000 processes. You can assume that processes a
ive with an average a
ival rate of 2 processes per second that follows a Poisson Distribution and the service time (i.e., requested duration on the CPU) for each process follows an Exponential distribution with an average service time of 1 second. Your outcome would be. You can assume that process IDs are assigned incrementally when processes a
ive and that they start at 1. What are the actual average a
ival rate and average service times that were generated? [30 pts]
Input:
import random
import numpy as np
# Set the parameters
total_processes = 1000
a
ival_rate = 2 # processes per second
average_service_time = 1 # seconds
# Generate a
ival times following a Poisson distribution
a
ival_times = np.random.poisson(1/a
ival_rate, total_processes)
# Generate service times following an Exponential distribution
service_times = np.random.exponential(average_service_time, total_processes)
# Calculate actual average a
ival rate and average service time
actual_a
ival_rate = total_processes / sum(a
ival_times)
actual_average_service_time = np.mean(service_times)
# Output the results
print("Actual Average A
ival Rate:", actual_a
ival_rate, "processes per second")
print("Actual Average Service Time:", actual_average_service_time, "seconds")
Output:
Actual Average A
ival Rate: 1.8484288354898337 processes per second
Actual Average Service Time: 1.0190654627960325 seconds
Explanation:
· We use numpy.random.poisson() to generate a
ival times following a Poisson distribution with the specified a
ival rate.
· We use numpy.random.exponential() to generate service times following an Exponential distribution with the specified average service time.
· The actual average a
ival rate is calculated by dividing the total number of processes by the sum of a
ival times.
· The actual average service time is calculated using the np.mean() function on the generated service times.
This script outputs the actual average a
ival rate and average service time based on the generated workload.
Problem 4 A computing system is composed of two servers that are mi
ors of each other (for redundancy, so if one fails, it can be restored from the other). Assume that each server has an MTBF of 500 hours that follows an exponential distribution. Furthermore, assume that when a server fails, it takes exactly 10 hours to restore the data from the mi
or.
(a) Write a program that generates synthetic data showing the failure and restoration times for each server over 20 years. [5 pts]
Input:
import random
# Constants
MTBF = 500 # Mean Time Between Failures in hours
RESTORE_TIME = 10 # Time to restore data from mi
or in hours
SIMULATION_DURATION_YEARS = 20
HOURS_IN_YEAR = 365 * 24
# Function to generate failure times based on exponential distribution
def generate_failure_times(mtbf, duration):
failure_times = []
cu
ent_time = 0
while cu
ent_time < duration:
time_to_failure = random.expovariate(1 / mtbf)
cu
ent_time += time_to_failure
if cu
ent_time < duration:
failure_times.append(cu
ent_time)
return failure_times
# Function to generate restoration times after failure
def generate_restoration_times(failure_times):
restoration_times = [failure_time + RESTORE_TIME for failure_time in failure_times]
return restoration_times
# Main function to generate synthetic data
def generate_synthetic_data():
failure_times_server1 = generate_failure_times(MTBF, SIMULATION_DURATION_YEARS * HOURS_IN_YEAR)
restoration_times_server1 = generate_restoration_times(failure_times_server1)
failure_times_server2 = generate_failure_times(MTBF, SIMULATION_DURATION_YEARS * HOURS_IN_YEAR)
restoration_times_server2 = generate_restoration_times(failure_times_server2)
return failure_times_server1, restoration_times_server1, failure_times_server2, restoration_times_server2
# Generate synthetic data
failure_times_server1, restoration_times_server1, failure_times_server2, restoration_times_server2 = generate_synthetic_data()
# Output the synthetic data
print("Server 1 Failure Times:", failure_times_server1)
print("Server 1 Restoration Times:", restoration_times_server1)
print("Server 2 Failure Times:", failure_times_server2)
print("Server 2 Restoration Times:", restoration_times_server2)
Output:
Server 1 Failure Times: [611.321016387983, 659.074246739503, 743.2377017833813, 797.362302195912, 1205.9501205821205, 1483.3479104233124, 2037.1661518884382, 2164.7879456071364, 2403.1840953254796, 2585.104847357038, 3438.045243521876, 3792.175980810282, 4085.032328363964, 5916.166355228628, 7097.640037425049, 8140.231959797407, 8403.056714002161, 8730.27490846209, 10355.896613151594, 10571.024284185723, 11323.608347784819, 13014.967039058685, 13510.597769725538, 13714.418721691069, 13934.307703979297, 13987.04784881074, 15410.49132739724, 16336.61325596141, 16442.06013769674, 17245.768582378052, 17597.88045163291, 17605.102377713527, 19661.446223065792, 20838.048153841683, 21125.54031825062, 21263.242958826868, 22179.839856250663, 23270.244539364874, 23570.065904528252, 23662.934072600463, 24149.816447649566, 24296.444654137802, 24514.607455073827, 25374.19188808892, 25489.048426874746, 25874.15208730622, 26312.879001720918, 26588.342268914734, 27256.52455703752, 27417.037033555505, 27778.06418267839, 28180.160728748288, 28562.88182783122, 28804.16121599183, 28968.077975856566, 29451.55851276248, 30315.726315340686, 30703.735253681407, 31171.605331351857, 31253.88833197823, 31989.523260465445, 32834.65689546101, 33820.02162415308, 34983.92558469162, 35117.09039117077, 36970.85904142638, 37053.59490296866, 37435.890217334505, 37511.31025192351, 37773.49469449286, 38154.39848697531, 38922.04424274079, 39079.08601213269, 39114.70642327797, 39424.49111307858, 40975.45919542627, 41060.25344790401, 41097.998939234494, 41175.354855715, 41471.770029831634, 42631.35004702069, 43253.22024186279, 43335.74642952633, 43347.535296454414, 43368.922141122224, 43804.89673527592, 43945.88585787887, 45452.229348972265, 45940.32900423972, 46297.37823988164, 46856.61146189786, 47185.08389501423, 47216.77450476845, 47259.77185611623, 47461.644494278386, 47778.24747156326, 48023.08615531226, 48692.97225022179, 48970.22154419159, 49051.245196195225, 49080.446147188355, 49144.03950798357, 50428.4873724123, 52240.938768384585, 52286.03445912998, 52298.0624792139, 52596.29597511538, 52720.82409499919, 52894.92667279877, 53960.222345049966, 54379.20129050238, 55203.552937245935, 55946.93283316443, 55974.84414478845, 56358.905959586475, 56370.93278921098, 57529.42294704536, 57701.48205889869, 59428.21204993845, 59439.81736080057, 59636.35595960073, 60339.52867528567, 60831.67442638328, 60832.69601529069, 61223.776135266184, 61695.35790951872, 61699.183231309056, 61996.68877519725, 62728.82152455617,...