OOP(Object-Oriented Programme) ——Waiting time for withdrawal in ATM

Object-Oriented Programme in Python——Chapter One

    • Terminology Overview
    • Creating Class
      • Instance Object and Attributes
      • 5 Methods to create ones
    • Waiting time for withdrawal in ATM(Using OOP to settle this question)
    • Reference

Terminology Overview

Class: a template for logical abstraction and Object generation, a set of variables and functions-specific choreography.
objects: entities that represent data and operations, equivalent to "variable " in a program.
instantiation: the process from a Class to an Object, all “objects” derived from a “Class.”.

Creating Class

class DemoClass:
    "This is a demo for Python class"

print(type(DemoClass))
print(DemoClass.__doc__)

Instance Object and Attributes

dc1 = DemoClass("OLD W")
dc2 = DemoClass("OLD L")
# 类对象
class DemoClass:
    # 类属性,直接在类中定义赋值的
    # 统一用<类名>.<属性名>访问
    count = 0
    def __init__(self ,name,age):
        # 实例属性
        # 在类内部用 self. access
        # 在类外部用 . access
        self.name = name
        self.age = age
        DemoClass.count += 1
#实例对象
dc1 = DemoClass("OLD W",45)
dc2 = DemoClass("OLD L",51)
print("Total",DemoClass.count)
print(dc1.name,dc2.name)
 
  

The attributes are variable defined within the class:

·The attributes of the class object, shared by all the instance objects.
·The attributes of the instance object, owned by each instance object itself.

5 Methods to create ones

  1. Instance method: instance object method, owned by each instance object itself, the most commonly used one.
    ‘def init(sef,~)’ acts as the key words to create Instance object and wait for passing the attributes if there will be some. For example:dc1 and dc2 are two instance objects that has been created:
class DemoClass:
    # 从类对象构建实例对象
    def __init__(self ,name):
        self.name = name
    def luck(self):
        s = 0
        for c in self.name:
            s += ord(c) % 100
            return s
dc1 = DemoClass("OLD W")
dc2 = DemoClass("OLD L")
print(dc1.name, "的幸运数字是:", dc1.luck())
print(dc2.name, "的幸运数字是:", dc2.luck())
  1. Class method: methods of class object, shared by all the instance objects
    ‘@classmethod’ the symbol of this method.
class DemoClass:
    count = 0
    # 从类对象构建实例对象
    def __init__(self ,name):
        self.name = name
        DemoClass.count += 1
    @classmethod
    def getChrCount(cls):
        s = "0123456789'10''11'"
        return s[DemoClass.count]

dc1 = DemoClass("OLD W")
dc2 = DemoClass("OLD L")
print(dc1.getChrCount())
print(DemoClass.getChrCount())
  1. Free method: in the class a common function, managed by class in the namespace, owned by class object solely.
    Derictly define a function in a class structure with no difference with any other function in the whole file(Only for the sake of logically fluent codes!).
class DemoClass:
    count = 0
    # 从类对象构建实例对象
    def __init__(self ,name):
        self.name = name
        DemoClass.count += 1
    #类空间中的普通函数,在类的内外定义无所谓
    def foo():
        DemoClass.count*=100
        return DemoClass.count
dc1 = DemoClass("老王")
print(DemoClass.foo())
  1. Static method: in the class a common function, shared by both the class object and instance objects
    ‘@staticmethod’, this symbol of this method.
class DemoClass:
    count = 0
    # 从类对象构建实例对象
    def __init__(self ,name):
        self.name = name
        DemoClass.count += 1
    @staticmethod
    def foo():
        DemoClass.count*=100
        return DemoClass.count
dc1 = DemoClass("老王")
print(DemoClass.foo())
print(dc1.foo())

Attention: Static method compared with free method allows to cite our function by both class name and object name. By contrast, in free method could we only use class name to cite inner function.

  1. Keeping method: by double underscores the start and end, such as len()
class DemoClass:
    count = 0
    # 从类对象构建实例对象
    def __init__(self ,name):
        self.name = name
        DemoClass.count += 1
    #Python 解释器保留方法已对应,只需要编写代码即可
    def __len__(self):
        return len(self.name)
dc1 = DemoClass("老王")
dc2 = DemoClass('老李')
print(len(dc1))
print(len(dc2))

Waiting time for withdrawal in ATM(Using OOP to settle this question)

Firstly, apologize for my low level of English writting abilities. I’d prefer to use Chinese to eleborate the whole question for the readers.

  1. 问题引出
    银行ATM机处理业务首先要消耗时间,客户出现的时间可能重叠导致排队等待。

  2. 为什么此问题适合面向对象编程
    平时所写的函数语句也可以实现功能的封装和调用,甚至简单的循环语句即可实现复杂的数学过程。但是此问题涉及排队论,对于列表变量以及时间序列的分析难以用循环语句描述,且大量重复的调用函数不如直接构建ATM和客户流对象,对对象之间的交互分析会使得条理清晰。

  3. 转化为数学问题
    ATM机:由于业务不同,办理业务时间符合一定随机分布
    客户:不同地点,客户出现时间符合一定随机分布
    最终目标:一定人次连续实验下每人的等待时间和平均等待时间

  4. 简单假设
    ·ATM机:服务时间在1到maxtime间随机
    ·客户流:n个客户到达时间在1到arrivalTime间随机
    ·所有时间以整数为单位。
    ·采用随机分布函数(其实更加符合泊松分布,只是一个代码测试实验,精度较低)

  5. 代码部分
    ATM机和客户流对象的构建:

class ATM():
    def __init__(self,maxTime = AMT_MT):
        self.t_max = maxTime
    def getServeCompleteTime(self, start = 0):
        return start + random.randint(1 ,self.t_max)

class Customers():
     def __init__(self, n):
         self.count = n
         self.left = n
     def getNextArrivalTime(self, start = 0, arrivalTime = CUS_ARR):
         if self.left != 0:
             self.left -= 1
             return start + random.randint(1, arrivalTime)
         else:
             return 0
     def isOver(self):
         return True if self.left == 0 else False

时间采取全局时间
(1)引用ATM对象的getServeComplete:处理完成后时间向后进行
(2)引用客户流对象:getNextArrivalTime为生成下一个客户到达时间(在全局时间上增加随机数)、isOver为判断客户是否全部完成办理,完全办理则返回False结束。

对象交互,形成列表计算等待时间

def Repetitive_exp():
    c = Customers(CUS_NUM)
    a = ATM()
    wait_list = []
    wait_time = 0
    cur_time = 0
    cur_time += c.getNextArrivalTime()
    wait_list.append(cur_time)
    # 队列中保存在next_time事件前即将到达的所有客户达到时间
    # 以及最多一个超过next_time时间的客户达到时间

    while len(wait_list) != 0 or not c.isOver():

        if wait_list[0] <= cur_time:
            # next_time受到ATM机对象驱动
            # 当ATM对象处理完当前业务时间前进
            next_time = a.getServeCompleteTime(cur_time)
            del wait_list[0]
        else:
            # 当ATM对象不处理业务,则时间前进1
            next_time = cur_time + 1

        # 一旦等待队列为空,则增加一个客户,队列不空保证时间前进
        if not c.isOver() and len(wait_list) == 0:
            next_arrival = c.getNextArrivalTime(cur_time)
            wait_list.append(next_arrival)

        # 如果等待队列的最后一个元素在next_time内在时间更迭中,还可能到达客户
        # 需要维持产生客户,直至其到达时间超过next_time(无需等待)
        if not c.isOver() and wait_list[-1] < next_time:
            next_arrival = c.getNextArrivalTime(wait_list[-1])
            wait_list.append(next_arrival)
            while next_arrival < next_time and not c.isOver():
                next_arrival = c.getNextArrivalTime(next_arrival)
                wait_list.append(next_arrival)

        # 在每个事件更迭周期,累积wait_time
        for i in wait_list:
            if i <= cur_time:
                wait_time += next_time - cur_time
            elif cur_time < i < next_time:
                wait_time += next_time - i
            else:
                pass
        cur_time = next_time
    print(wait_time / c.count)
    return wait_time / c.count
  1. 结果可视化
    ATM最大处理时间:5(处理业务时间在1-5之间随机)
    客户数:100
    新客户到达时间:10(在上一个业务完成后开始生成新顾客到达时间;下一个到达时间=当前业务办理完后的全局时间+一个[1,10]的随机数)

OOP(Object-Oriented Programme) ——Waiting time for withdrawal in ATM_第1张图片
平均等待时间 0.7319999999999998

ATM最大处理时间:10
客户数:100
新客户到达时间:10
OOP(Object-Oriented Programme) ——Waiting time for withdrawal in ATM_第2张图片
平均等待时间 18.565699999999996

  1. 全部代码:
import random
import matplotlib.pyplot as plt
AMT_MT = 5
CUS_ARR = 10
CUS_NUM = 100
class ATM():
    def __init__(self,maxTime = AMT_MT):
        self.t_max = maxTime
    def getServeCompleteTime(self, start = 0):
        return start + random.randint(1 ,self.t_max)

class Customers():
     def __init__(self, n):
         self.count = n
         self.left = n
     def getNextArrivalTime(self, start = 0, arrivalTime = CUS_ARR):
         if self.left != 0:
             self.left -= 1
             return start + random.randint(1, arrivalTime)
         else:
             return 0
     def isOver(self):
         return True if self.left == 0 else False



def Repetitive_exp():
    c = Customers(CUS_NUM)
    a = ATM()
    wait_list = []
    wait_time = 0
    cur_time = 0
    cur_time += c.getNextArrivalTime()
    wait_list.append(cur_time)
    # 队列中保存在next_time事件前即将到达的所有客户达到时间
    # 以及最多一个超过next_time时间的客户达到时间

    while len(wait_list) != 0 or not c.isOver():

        if wait_list[0] <= cur_time:
            # next_time受到ATM机对象驱动
            # 当ATM对象处理完当前业务时间前进
            next_time = a.getServeCompleteTime(cur_time)
            del wait_list[0]
        else:
            # 当ATM对象不处理业务,则时间前进1
            next_time = cur_time + 1

        # 一旦等待队列为空,则增加一个客户,队列不空保证时间前进
        if not c.isOver() and len(wait_list) == 0:
            next_arrival = c.getNextArrivalTime(cur_time)
            wait_list.append(next_arrival)

        # 如果等待队列的最后一个元素在next_time内在时间更迭中,还可能到达客户
        # 需要维持产生客户,直至其到达时间超过next_time(无需等待)
        if not c.isOver() and wait_list[-1] < next_time:
            next_arrival = c.getNextArrivalTime(wait_list[-1])
            wait_list.append(next_arrival)
            while next_arrival < next_time and not c.isOver():
                next_arrival = c.getNextArrivalTime(next_arrival)
                wait_list.append(next_arrival)

        # 在每个事件更迭周期,累积wait_time
        for i in wait_list:
            if i <= cur_time:
                wait_time += next_time - cur_time
            elif cur_time < i < next_time:
                wait_time += next_time - i
            else:
                pass
        cur_time = next_time
    print(wait_time / c.count)
    return wait_time / c.count

Average = []
for i in range(CUS_NUM):
    ab = Repetitive_exp()
    Average.append(ab)

print('平均等待时间',sum(Average)/len(Average))
plt.bar([x for x in range(CUS_NUM)],Average)
title1 = "%s%s" % ('ATM: max_processing_time = ', '%d' % (AMT_MT))
title2 = "%s%s" % (';Customers: numbers = ', '%d' % (CUS_NUM))
title3 = "%s%s" % (',arrival_time = ', '%d' % (CUS_ARR))
title = "%s%s" %(title1,title2)
title = "%s%s" %(title,title3)
plt.title(title)

font1 = {'family' : 'Times New Roman',
'weight' : 'normal',
'size'   : 10,
         }
plt.xlabel("per person",font1)
plt.ylabel("waiting time(standard)",font1)
plt.show()

Reference

Python学习嵩天老师 Python面向对象精讲 - P10 银行ATM等待时间2

你可能感兴趣的:(OOP(Object-Oriented Programme) ——Waiting time for withdrawal in ATM)