def generate_exponential_samples(n, params): try: assert len(params) == 1 L = float(params[0]) assert L > 0 except (ValueError, AssertionError): abort("invalid exponential parameters") for _ in range(n): yield exponential(L)
def exponential_distribution(mean): stream = distributions.exponential(mean) while True: value = stream.next() # Получение значения # И его обработка try: for function in postprocess: value = function(value) except: continue # Следующее значение yield value
def distribution(field): 'Распределение' # Определим тип распределения types = ('exponential', 'equal', 'normal') # Допустимые типы try: t = field['type'] except: # Тип не указан t = types[0] else: if not (t in types): raise ValueError(u'Распределение %s неизвестно.' % t) if t == 'exponential': values = validate(field, piece(conditions, ('mean', ))) return distributions.exponential(values['mean']) elif t == 'equal': values = validate(field, piece(conditions, ('from', 'to'))) return distributions.equal(*values.values()) else: return distributions.normal(float(field['mean']))
def event_stream(): 'Поток событий' timer = distributions.exponential(in_stream) # Время появления следующей заявки next_order = next(timer) while True: time, source = next_order, ENVIRONMENT for link, queue in enumerate(chain): if queue and queue[0] < time: time, source = queue[0], link if source == ENVIRONMENT: next_order += next(timer) # Если закончилось время, выходим if time >= total_time: return # Иначе возвращаем результат yield (time, source)
def agen(): return exponential(l)
import distributions import csv with open('exponential-distr.csv', 'w') as csvfile: writer = csv.writer(csvfile, delimiter=' ', quotechar='|', quoting=csv.QUOTE_MINIMAL, dialect='excel') numbers = [] for i in range(1, 100000): writer.writerow([distributions.exponential(0.2)])
def simulate(self): gain = 0 # [True] * self.technicals free_sellers = [0] * self.sellers free_technical = [0] * self.technicals free_specialized_technicals = [0] * self.specialized_technicals customers_waiting_sellers = Queue() customers_waiting_technicals = Queue() customers_waiting_specialized_technicals = Queue() client_time = 0 for _ in range(self.journal_duration): # Update client reach time if client_time > 0: client_time -= 1 else: client_time = poisson(20) customers_waiting_sellers.put(select_random_type()) if (customers_waiting_sellers.empty() and customers_waiting_specialized_technicals.empty() and customers_waiting_technicals.empty()): for i in range(len(free_sellers)): free_sellers[ i] = free_sellers[i] - 1 if free_sellers[i] > 0 else 0 for i in range(len(free_technical)): free_technical[i] = free_technical[ i] - 1 if free_technical[i] > 0 else 0 for i in range(len(free_specialized_technicals)): free_specialized_technicals[i] = free_specialized_technicals[i] - 1 \ if free_specialized_technicals[i] > 0 else 0 continue # Update specialized technicals details for i in range(len(free_specialized_technicals)): free_specialized_technicals[i] = free_specialized_technicals[i] - 1 \ if free_specialized_technicals[i] > 0 else 0 if not customers_waiting_specialized_technicals.empty(): for i in range(len(free_specialized_technicals)): if free_specialized_technicals[i] == 0: _ = customers_waiting_specialized_technicals.get() free_specialized_technicals[i] = int(exponential(15)) gain += 500 if customers_waiting_specialized_technicals.empty(): break # Update technicals details for i in range(len(free_technical)): free_technical[ i] = free_technical[i] - 1 if free_technical[i] > 0 else 0 if not customers_waiting_technicals.empty(): for i in range(len(free_technical)): if free_technical[i] == 0: client_type = customers_waiting_technicals.get() free_technical[i] = int(exponential(20)) gain += 0 if client_type == 1 else 350 if customers_waiting_technicals.empty(): break else: for i in range(len(free_specialized_technicals)): if free_specialized_technicals[i] == 0: client_type = customers_waiting_technicals.get() free_specialized_technicals[i] = int( exponential(15)) gain += 0 if client_type == 1 else 350 if customers_waiting_technicals.empty(): break # Update sellers details for i in range(len(free_sellers)): free_sellers[ i] = free_sellers[i] - 1 if free_sellers[i] > 0 else 0 if not customers_waiting_sellers.empty(): for i in range(len(free_sellers)): if free_sellers[i] == 0: client_type = customers_waiting_sellers.get() free_sellers[i] = int(abs(normal(5, 2))) if client_type == 4: gain += 750 else: if client_type == 1 or client_type == 2: customers_waiting_technicals.put(client_type) else: customers_waiting_specialized_technicals.put( client_type) if customers_waiting_sellers.empty(): break return gain
# Lists Initialization uniform_values = np.zeros(iterations) normal_values = np.zeros(iterations) exponential_values = np.zeros(iterations) gamma_values = np.zeros(iterations) binomial_values = np.zeros(iterations) pascal_values = np.zeros(iterations) hypergeometric_values = np.zeros(iterations) poisson_values = np.zeros(iterations) empirical_values = np.zeros(iterations) # Distributions Generation for i in range(iterations): uniform_values[i] = uniform(a, b) normal_values[i] = normal(m, d) exponential_values[i] = exponential(1 / alpha_exp) gamma_values[i] = gamma(k_gamma, alpha_gamma) binomial_values[i] = binomial(n_binomial, p_binomial) pascal_values[i] = pascal(k_pascal, p_pascal) hypergeometric_values[i] = hypergeometric(N_hyper, n_hyper, p_hyper) poisson_values[i] = poisson(L) empirical_values[i] = empirical() print(iterations, "pseudorandom numbers generated of each distribution\n") # Statistics Parameter Tests print("//////////// STATISTICS PARAMETERS TESTS ////////////\n") print('-----UNIFORM DISTRIBUTION------') # print(uniform_values) statistics_parameters_test(uniform_values, (a + b) / 2, 'Mean')
def mss(channelsCount, queue, streams, faults, totalTime): u'Система массового обслуживания' # Потоки in_stream = streams['in'] out_stream = streams['out'] fault_stream = distributions.exponential(faults['problems']) repair_stream = distributions.exponential(faults['repairs']) # Действия mss.actions = {} increment, decrement = 1, -1 def action(state=0): def mix(f): key = f.__name__ mss.actions[key] = 0 def spice(*args): result = f(*args) mss.actions[key] += 1 # Статистика # Состояние duration = (args[0] - mss.prevTime) try: mss.states[mss.state] += duration except: mss.states.append(duration) mss.prevTime = args[0] mss.state += state return result return spice return mix @action(state=increment) def accept(time): 'Принять заявку в обработку' # Поиск свободного канала free = [key for key, value in enumerate(orders) if value == Infinity and 1 <= key <= channelsCount] # Выбор случайного канала channel = random.choice(free) # Время обработки заявки orders[channel] = time + next(out_stream) @action(state=increment) def sit(time): 'Отправка заявки в очередь' orders.append(time + queue['time']) @action() def sizeout(time): 'Отклонение заявки по размеру очереди' @action(state=decrement) def leave(time, channel): 'Окончание обслуживания заявки' orders[channel] = Infinity @action(state=decrement) def stand(time): 'Удаление первого элемента из очереди' orders.pop(channelsCount + 1) @action(state=decrement) def timeout(time): 'Уход элемента из очереди по таймауту' orders.pop(channelsCount + 1) @action() def fault(time, destructive): 'Неисправность' if not mss.state: return # Авария проходит без последствий, если нет заявок в обработке # Занятые каналы busy = [index for index, value in enumerate(orders) if 1 <= index <= channelsCount and value < Infinity] # Выбор канала, на котором происходит авария channel = random.choice(busy) # Заявка ожидает ремонта оборудования orders[channel] += next(repair_stream) if destructive: # Если случилась авария, orders[channel] += next(out_stream) # Заявка ещё и обрабатывается заново # События def onNew(time): 'Появление новой заявки' if mss.state < channelsCount: # Если есть пустые каналы, accept(time) # то принимаем заявку; elif mss.state < channelsCount + queue['size']: # если их нет, но есть места в очереди - sit(time) # направляем её в очередь. else: # если же и очередь забита - sizeout(time) # отвергаем заявку. def onLeave(time, channel): 'Канал channel освобождается заявкой' leave(time, channel) # Заявка уходит из канала if mss.state + 1 > channelsCount: # Если очередь непуста... stand(time) # то из очереди вызывается первая заявка accept(time) # и уходит на выполнение def onTimeout(time): 'Уход заявки из очереди по таймауту' timeout(time) def onDispatch(*args): 'Редирект на нужный обработчик события' onDispatch.route(*args) orders[0] = next(eventStream) def onFault(time): 'Неисправность' fault(time, random.random() <= faults['destructive']) def inputCombinator(): 'Комбинация генераторов' # Время последней заявки и последней неисправности new, fault = next(in_stream), next(fault_stream) while True: # Время следующей заявки и следующей неисправности if new < fault: onDispatch.route = onNew yield new new += next(in_stream) else: onDispatch.route = onFault yield fault fault += next(fault_stream) # Бесконечность Infinity = float('Infinity') # Поток событий - заявок и аварий eventStream = inputCombinator() # Время последнего изменения состояния mss.prevTime = 0 # Структура, хранящая местоположение заявок и операции над ними. orders = [next(eventStream)] + [Infinity] * channelsCount # Состояние mss.state = 0 mss.states = [] while True: # Тип и значение следующего события event = min(range(len(orders)), key=orders.__getitem__) time = orders[event] # Ограничение времени жизни модели if time > totalTime: break if event: if event <= channelsCount: # Завершена обработка заявки onLeave(time, event) else: # Заявка уходит из очереди по таймауту onTimeout(time) else: # Независимое событие (новая заявка или неисправность) onDispatch(time) # уходит на диспетчеризацию. # Время истекло, но в обработке и в очереди ещё могли остаться заявки. mss.actions['shutdown'] = mss.state # Качество работы СМО rejectedFields = ( # Заявки, отклонённые: 'timeout', # По таймауту 'sizeout', # По размеру очереди 'shutdown', # По окончанию рабочего времени ) # Количество заявок, отменённых по каждой из причин absolute = {} for field in rejectedFields: absolute[field] = mss.actions[field] # Все отменённые заявки absolute['reject'] = sum(absolute.values()) # Принятые заявки и все заявки, прошедшие через систему absolute['accept'] = mss.actions['accept'] absolute['total'] = absolute['reject'] + absolute['accept'] # Значения в процентах relative = {} for key, value in absolute.items(): if key != 'total': relative[key] = round(value / float(absolute['total']) * 100, 2) # Среднее количество занятых каналов km = 0 for channel, time in enumerate(mss.states): km += channel * time if channel <= channelsCount else channelsCount * time km /= totalTime # Среднее время пребывания заявки import operator times = {} orderTime = sum(orders * time for orders, time in enumerate(mss.states)) queueTime = sum(time * orders for orders, time in enumerate(mss.states[channelsCount:])) if absolute['total']: # В системе times['total'] = round(orderTime / absolute['total'], 3) if mss.actions['sit']: # В очереди times['queue'] = round(queueTime / mss.actions['sit'], 3) # Среднее количество заявок orders = {'work': round(km, 3)} orders['total'] = round(orderTime / totalTime, 3) orders['queue'] = round(queueTime / totalTime, 3) # Результаты работы states = tuple(round(duration / totalTime * 100, 3) for duration in mss.states) return { 'quality': { 'abs': absolute, 'pc': relative, }, 'load': { 'states': states, 'longestState': max(states), 'times': times, 'orders': orders, }, 'faults': mss.actions['fault'], }
def recharge_time(): return exponential(30)
def fix_time(): return exponential(15)
def arrival_time(lambd): return exponential(lambd)
def unloading_time(): return exponential(30)