def write_fee_schedule(operations, path, sort=True, n_significant_figures=2): if sort: operations = sorted(operations, key=lambda x: x.name) group_dict = SortedDict() for op in operations: if op.group is not None and op.get_model_input_size( ) == 0 and op.get_n_model_param() == 1: if op.group not in group_dict: group_dict[op.group] = [] group_dict[op.group].append(op) with open(path, "w") as ofile: ofile.write("# Fee Schedule\n") ofile.write("\n") ofile.write("| Operation | Gas cost |\n") ofile.write("|-----------|----------|\n") for op in operations: expr = op.get_gas_cost_expr( n_significant_figures=n_significant_figures) if expr is None: continue ofile.write("| `%s` | `%s` |\n" % (op.name, expr)) if group_dict: ofile.write("\n") ofile.write("## Grouped Operations\n") ofile.write("\n") ofile.write("| Group | Maximum Gas cost |\n") ofile.write("|-------|------------------|\n") for key, ops in group_dict.items(): # We should only get operations with 0 input variable and 1 # parameter at this point max_cost = max(op.latest_param[0] for op in ops) expr = "{:_}".format(round_up(max_cost, n_significant_figures)) ofile.write("| `%s` | `%s` |\n" % (key, expr))
def recheduleChangePriority(jobsListExportPrevious, rescheduleTime, priorItinerary, machinesList): """ :param jobsListExportPrevious: 初始调度结果 :param rescheduleTime: 重调度时间 :param priorItinerary: 优先的任务序号 :param machinesList: 可用机器列表 :return: jobsListToExportNew: 重调度方案 """ time = {} allPreviousOperations = {} rescheduleOperations = {} rescheduleJobsList = [] currentTimeOnMachines = {} jobsListToExportNew = [] unchangedOperations = {} # 遍历机器,生成每个机器前工序集合和需要重调度的工序集合 for machine in machinesList: allPreviousOperations[machine.name] = [ job for job in jobsListExportPrevious if job.assignedMachine == machine.name ] allPreviousOperations[machine.name].sort(key=lambda j: j.startTime) rescheduleOperations[machine.name] = [ job for job in jobsListExportPrevious if job.assignedMachine == machine.name and job.startTime >= rescheduleTime ] rescheduleOperations[machine.name].sort(key=lambda j: j.startTime) # 重调度时刻机器时间更新 unchangedLength = len(allPreviousOperations[machine.name]) - len( rescheduleOperations[machine.name]) unchangedOperations[machine.name] = allPreviousOperations[ machine.name][0:unchangedLength] currentTimeOnMachines[machine.name] = unchangedOperations[ machine.name][-1].endTime if currentTimeOnMachines[machine.name] < rescheduleTime: currentTimeOnMachines[machine.name] = rescheduleTime # 初始化各机器时间 time[currentTimeOnMachines[machine.name]] = {} # 更新各机器下重调度工序状态 unchangedOperations[machine.name][-1].completed = True for job in rescheduleOperations[machine.name]: job.startTime = 0 job.completed = False # 输出无需重调度的任务结果 for job in unchangedOperations[machine.name]: jobsListToExportNew.append(job) for machine in machinesList: # 生成重调度列表 for job in rescheduleOperations[machine.name]: if job.idItinerary == priorItinerary: job.priority = 5 rescheduleJobsList.append(job) allJobsList = jobsListToExportNew + rescheduleJobsList # 调度时间初始化 time = SortedDict(time) while len(jobsListToExportNew) < len(jobsListExportPrevious): for t, operations in time.items(): operations = GetWaitingOperationsSPT(allJobsList, float(t), machinesList, currentTimeOnMachines) for keyMach, tasks in operations.items(): if len(tasks): if float(t) < currentTimeOnMachines[keyMach]: continue tasks[0].startTime = float(t) tasks[0].completed = True tasks[0].assignedMachine = keyMach jobsListToExportNew.append(tasks[0]) currentTimeOnMachines[keyMach] = tasks[0].getEndTime() time[currentTimeOnMachines[keyMach]] = {} del time[t] break time = SortedDict(time) # chronological order return jobsListToExportNew
class TimingDiagram: """Two-state (True/False or 1/0) timing diagram with boolean algebra operations.""" def __init__(self, time_state_pairs): """Creates a timing diagram out of a series of (time, state) pairs. Notes ===== The input states can be any truthy/falsey values. The input times can be any type with a partial ordering. The input sequence does not need to be sorted (input is sorted during initialization). Compresses duplicate sequential states and stores them in the `timeline` attribute. Example ======= >>> diagram = TimingDiagram([(0, True), (1, False), (5, False), (10, True)]) >>> print(~diagram) TimingDiagram([(0, False), (1, True), (10, False)]) """ self.timeline = SortedDict( _compress(time_state_pairs, key=operator.itemgetter(1)) ) def __getitem__(self, item): return self.timeline[item] def __matmul__(self, time): """Alias for at()""" return self.at(time) def __eq__(self, other): """Returns a new timing diagram, True where the two diagrams are equal.""" return self.compare(other, key=operator.eq) def __ne__(self, other): """Returns a new timing diagram, True where the two diagrams are equal.""" return ~(self == other) def __and__(self, other): """Returns a new timing diagram, True where the two diagrams are both True.""" return self.compare(other, key=operator.and_) def __or__(self, other): """Returns a new timing diagram, True where either diagram is True.""" return self.compare(other, key=operator.or_) def __xor__(self, other): """Returns a new timing diagram, True where the two diagrams are not equal.""" return self != other def __invert__(self): """Returns a new timing diagram with states flipped.""" return TimingDiagram(((t, not s) for t, s in self.timeline.items())) def at(self, time): """Returns the state at a particular time. Uses bisection for search (binary search).""" idx = max(0, self.timeline.bisect(time) - 1) return self.timeline.values()[idx] def compare(self, other, key): """Constructs a new timing diagram based on comparisons between two diagrams, with (time, key(self[time], other[time])) for each time in the timelines. """ # TODO: Implement linear algorithm instead of .at() for each time, which is O(n log n). return TimingDiagram( ( (k, key(self.at(k), other.at(k))) for k in merge(self.timeline.keys(), other.timeline.keys()) ) ) def __repr__(self): return f"{self.__class__.__qualname__}({list(self.timeline.items())})"
def recheduleMachineFault(jobsListExportPrevious, rescheduleTime, faultyMachine, machinesList): pass #TODO time = {} allPreviousOperations = {} rescheduleOperations = {} rescheduleJobsList = [] currentTimeOnMachines = {} jobsListToExportNew = [] unchangedOperations = {} unscheduleItinerarys = [] # 遍历机器,生成每个机器前工序集合和需要重调度的工序集合 for machine in machinesList: allPreviousOperations[machine.name] = [ job for job in jobsListExportPrevious if job.assignedMachine == machine.name ] allPreviousOperations[machine.name].sort(key=lambda j: j.startTime) rescheduleOperations[machine.name] = [ job for job in jobsListExportPrevious if job.assignedMachine == machine.name and job.startTime >= rescheduleTime ] rescheduleOperations[machine.name].sort(key=lambda j: j.startTime) # 重调度时刻机器时间更新 unchangedLength = len(allPreviousOperations[machine.name]) - len( rescheduleOperations[machine.name]) unchangedOperations[machine.name] = allPreviousOperations[ machine.name][0:unchangedLength] #如果故障机器上有未完工任务,则把该任务工艺路线后续任务不参与重调度 currentTimeOnMachines[machine.name] = unchangedOperations[ machine.name][-1].endTime if currentTimeOnMachines[machine.name] < rescheduleTime: currentTimeOnMachines[machine.name] = rescheduleTime # 初始化各机器时间 time[currentTimeOnMachines[machine.name]] = {} # 更新各机器下重调度工序状态 unchangedOperations[machine.name][-1].completed = True for job in rescheduleOperations[machine.name]: job.completed = False # 输出无需重调度的任务结果 for job in unchangedOperations[machine.name]: jobsListToExportNew.append(job) # 1.先识别出故障机器前未完工任务(包括正在加工的) # 2. 遍历上述任务列表: # 如果任务可选机器列表长度为1,则重调度任务列表中不加入该任务; # 并且记录该任务的工艺路线号,后续是该工艺路线号的任务不参与调度; # 否则将任务加入重调度任务列表 if unchangedOperations[faultyMachine][-1].endTime > rescheduleTime: unscheduleItinerarys.append( unchangedOperations[faultyMachine][-1].idItinerary) # 生成重调度初始列表 for machine in machinesList: for job in rescheduleOperations[machine.name]: rescheduleJobsList.append(job) rescheduleJobsList.sort(key=lambda j: j.startTime) #得到受影响的工艺路线号 for job in rescheduleOperations[faultyMachine]: if len(job.machine) == 1: unscheduleItinerarys.append(job.idItinerary) #去除受机器故障影响的任务 rescheduleJobsListUpdate = [] for job in rescheduleJobsList: if job.idItinerary in unscheduleItinerarys: continue else: rescheduleJobsListUpdate.append(job) # 机器列表更新 machinesAvailableList = [ machine for machine in machinesList if machine.name != faultyMachine ] allJobsList = jobsListToExportNew + rescheduleJobsListUpdate # 调度时间初始化 time = SortedDict(time) while len(jobsListToExportNew) < len(allJobsList): for t, operations in time.items(): operations = GetWaitingOperationsSPT(allJobsList, float(t), machinesAvailableList, currentTimeOnMachines, faultyMachine) for keyMach, tasks in operations.items(): if len(tasks): if float(t) < currentTimeOnMachines[keyMach]: continue tasks[0].startTime = float(t) tasks[0].completed = True tasks[0].assignedMachine = keyMach jobsListToExportNew.append(tasks[0]) currentTimeOnMachines[keyMach] = tasks[0].getEndTime() time[currentTimeOnMachines[keyMach]] = {} del time[t] break time = SortedDict(time) # chronological order return jobsListToExportNew