Publicado pela primeira vez em csdn. Original.
https://blog.csdn.net/weixin_43906799/article/details/105510046
Algoritmo SJF:
O algoritmo de agendamento SJF (Shortest Job First) primeiro correlaciona cada processo com a duração da sua próxima execução da CPU. De fato, os processos / trabalhos curtos (que exigem o menor tempo de serviço) representam uma grande proporção na situação real.Para fazê-los executar preferencialmente, o menor tempo médio de espera, tempo médio de retorno e tempo médio de retorno são buscados. A prioridade curta do trabalho pode resultar no processamento do trabalho longo)
Conceito geral
A idéia de desenhar com python surgiu desde o momento em que se escrevia um trabalho de gráfico de agendamento. Naquela época, pensei em desenhar com python.Existem duas idéias para desenhar dinamicamente um diagrama de agendamento, e existe o método usado agora. Por que usar a classe para escrever esse trabalho, um deles é que o próximo trabalho possa herdar diretamente a classe SJF e, em seguida, modificar a função de agendamento e a função de classificação. O segundo é usar a classe para escrever código para resolver um tipo de problema, o código parece bonito.
Diagrama da estrutura de projeto do algoritmo
Gráfico de resultado de execução de programa
Informações sobre o trabalho
Nome do trabalho | Hora de chegada | Tempo de execução |
---|---|---|
UMA | 0 0 | 5 |
B | 1 | 4 |
C | 2 | 1 |
D | 4 | 2 |
E | 5 | 1 |
Ideia básica
(1) Inicialização de classe:
Para a classe de algoritmo SJF de planejamento de processos, primeiro precisamos ter variáveis de membro, ou seja, as variáveis de membro que são aproximadamente necessárias. Basicamente, é preciso muito.
self.data = [] | Processo armazenado |
---|---|
self.name = '' | Nome do processo |
self.service_time = 0 | Tempo de serviço |
self.arrival_time = 0 | Hora de chegada |
self.state = '' | Estado inicial |
self.number = 0 | Número de processos |
self.timeout = 0 | Limite de tempo limite |
self.start = 0 | Hora de início |
self.end = 0 | Hora de término |
def __init__(self):
super(Solution, self).__init__()
# save tasks
self.data = []
self.name = ''
self.service_time = 0
self.arrival_time = 0
self.state = ''
self.number = 0
self.timeout = 0
self.start = 0
self.end = 0
(2) Obter dados:
Os dados adquiridos podem ser lidos de um arquivo (como .txt) ou do console. Um local necessário aqui é o formato dos dados, nome, horário de chegada e horário do serviço. Separado por espaços. Conforme mostrado na tabela abaixo:
nome | tempo de chegada | tempo de serviço |
---|---|---|
UMA | 0 0 | 5 |
B | 1 | 4 |
C | 2 | 1 |
D | 4 | 2 |
E | 5 | 1 |
def get_data_file(self):
with open('data.txt', "r", encoding="utf-8") as file:
for line in file.read().splitlines():
name, arrival_time, service_time = line.split()
# insert the task
self.insert_data(name, arrival_time, service_time)
file.close()
# initial queue
# sort first arrival_time and second service_time
self.data.sort(key=lambda x: (x['arrival_time'], x['service_time']))
# update and recode id
for i in range(self.number):
self.data[i]['index'] = i
def get_data_input(self):
print('How many tasks do you want input?')
tasks_number = int(input('Please enter an integer of type int:'))
print('Please enter name and arrival_time and service_time of task')
print('such as:A 0 5')
for _ in range(tasks_number):
name, arrival_time, service_time = input('Please enter\n').split()
self.insert_data(name, arrival_time, service_time)
# initial queue
# sort first arrival_time and second service_time
self.data.sort(key=lambda x: (x['arrival_time'], x['service_time']))
# update and recode id
for i in range(self.number):
self.data[i]['index'] = i
(3) Horário:
Ou seja, projetar algoritmos para atingir SJF. A idéia básica do algoritmo é manter uma fila de prioridade. Como mostrado:
Sempre que agendar, de acordo com a necessidade, atualize as informações, altere o status do trabalho e a hora de chegada e final. Para obter o próximo trabalho ou vários trabalhos ao mesmo tempo, uma situação precisa ser considerada aqui, ou seja, o intervalo de tempo atual não pode obter o próximo trabalho e precisa aguardar um período de tempo antes que o trabalho chegue. Esta situação é particularmente crítica. Em seguida, execute a classificação e mantenha essa fila de prioridade.
def implement(self):
'''start algorithm'''
# get first task
data = [self.data[0]]
# update the time of start
self.start = self.end = data[0]['arrival_time']
while data:
# update information
self.update_information(
data[0]['index'], self.end, self.end + data[0]['service_time'])
# get next task or tasks
data += self.get_next_data(data.pop(0)['index'], data)
# maintain the queue
data = self.sort_data(data)
self.data.sort(key=lambda x: x['id'])
(4) Classificação e atualização de informações:
A implementação da classificação é realmente muito simples.O diagrama da estrutura anterior também mostrou que existem dois métodos de classificação para o algoritmo SJF, que são usados em processos diferentes. A atualização de dados é para atualizar os dados originais, incluindo o status do cálculo, horário de início, horário de término, tempo de resposta, tempo médio de resposta e assim por diante.
def update_information(self, index, start, end):
self.data[index]['start'] = start
self.data[index]['end'] = end
self.data[index]['state'] = 'f'
self.data[index]['turnaround_time'] = end - \
self.data[index]['arrival_time']
self.data[index]['authorized_turnover_time'] = self.data[index]['turnaround_time'] / \
self.data[index]['service_time']
self.start = start
self.end = end
self.show_data_running(start, end, self.data[index])
(5) Saída de dados:
Por que a saída de dados, de fato, este é um método de visualização de dados. Isso é para expressar todos os tipos de informações intuitivamente. Portanto, a parte da saída de dados é definir seu próprio layout e layout.Você pode usar a guia \ t para reproduzir a tabela.
def show_data(self):
print("{:<6}{:<10}{:<10}{:<10}{:<6}{:<8}{:<7}{:<6}".format(
'name', 'arr_time', 'ser_time', 'state', '周转时间', '带权周转时间', 'start', 'end'))
for task in sorted(self.data, key=lambda x: x['id']):
print("{:<6}{:<10}{:<10}{:<10}{:<10}{:<14.2f}{:<7}{:<4}".format(
task['name'],
task['arrival_time'],
task['service_time'],
task['state'],
task['turnaround_time'],
task['authorized_turnover_time'],
task['start'],
task['end']))
(6) Exibição do diagrama de programação gerado pelo PLT:
Use a biblioteca de terceiros do Python para desenhar de acordo com os dados e, em seguida, exiba belas imagens.
def init_image(self):
# size = 1000 * 500
plt.figure('SJF', figsize=(10, 5))
self.drow_image()
# setting xticks for 0 to self.end + 2
plt.xticks([i for i in range(self.end + 3)])
# setting title
plt.title('the time of task about SJF')
plt.xlabel('')
plt.ylabel('tasks')
# setting yticks.such as A == 0
plt.yticks(self.get_y_ticks()[0], self.get_y_ticks()[1])
def drow_image(self):
for task in self.data:
# the time line of task from start to end
plt.plot([task['start'], task['end']],
[task['id'], task['id']],
label=task['name'],
lw=2)
# annotation of the key point
plt.plot([task['end'], task['end']],
[-1, task['id']],
'k--',
lw=1)
# legend
plt.legend(loc='best')
def set_ax(self):
ax = plt.gca() # 获取到当前坐标轴信息
ax.spines['right'].set_color('none')
ax.spines['bottom'].set_color('none')
ax.xaxis.set_ticks_position('top') # 将X坐标轴移到上面
ax.invert_yaxis() # 反转Y坐标轴
ax.grid(True, linestyle='-.') # 网格
def show_image(self):
self.init_image()
self.set_ax()
plt.savefig('SJF.png', dpi=300)
plt.show()
Processo de execução do programa:
Suporte para dois métodos de entrada, entrada manual e importação de dados.
Importação de dados:
Dados brutos
Antes de agendar:
Na programação:
Após o agendamento:
Gere o diagrama de agendamento:
Digite os dados manualmente:
Antes de agendar
Agendamento
Após o agendamento
Gere o diagrama de agendamento:
Código fonte do programa:
# -*- coding: utf-8 -*-
# @Author: wfy
# @Date: 2020-04-10 15:31:44
# @Last Modified by: wfy
# @Last Modified time: 2020-04-14 13:46:31
import matplotlib.pyplot as plt
class Solution():
"""to achieve SJF"""
def __init__(self):
super(Solution, self).__init__()
# save tasks
self.data = []
self.name = ''
self.service_time = 0
self.arrival_time = 0
self.state = ''
self.number = 0
self.timeout = 0
self.start = 0
self.end = 0
def insert_data(self, name, arrival_time, service_time):
self.data.append({
'id': self.number,
'name': name,
'arrival_time': int(arrival_time),
'service_time': int(service_time),
'state': 'w',
'turnaround_time': 0,
'authorized_turnover_time': 0,
'start': 0,
'end': 0
})
self.timeout = max(self.timeout, int(arrival_time))
self.number += 1
def get_data_file(self):
with open('data.txt', "r", encoding="utf-8") as file:
for line in file.read().splitlines():
name, arrival_time, service_time = line.split()
# insert the task
self.insert_data(name, arrival_time, service_time)
file.close()
# initial queue
# sort first arrival_time and second service_time
self.data.sort(key=lambda x: (x['arrival_time'], x['service_time']))
# update and recode id
for i in range(self.number):
self.data[i]['index'] = i
def get_data_input(self):
print('How many tasks do you want input?')
tasks_number = int(input('Please enter an integer of type int:'))
print('Please enter name and arrival_time and service_time of task')
print('such as:A 0 5')
for _ in range(tasks_number):
name, arrival_time, service_time = input('Please enter\n').split()
self.insert_data(name, arrival_time, service_time)
# initial queue
# sort first arrival_time and second service_time
self.data.sort(key=lambda x: (x['arrival_time'], x['service_time']))
# update and recode id
for i in range(self.number):
self.data[i]['index'] = i
def show_data_running(self, start, end, data):
print('-'*40)
print("from {:} to {:}".format(start, end))
print("task name:{:}".format(data['name']))
print("task state:{:}\n".format('R'))
def show_data(self):
print("{:<6}{:<10}{:<10}{:<10}{:<6}{:<8}{:<7}{:<6}".format(
'name', 'arr_time', 'ser_time', 'state', '周转时间', '带权周转时间', 'start', 'end'))
for task in sorted(self.data, key=lambda x: x['id']):
print("{:<6}{:<10}{:<10}{:<10}{:<10}{:<14.2f}{:<7}{:<4}".format(
task['name'],
task['arrival_time'],
task['service_time'],
task['state'],
task['turnaround_time'],
task['authorized_turnover_time'],
task['start'],
task['end']))
def cmp(self):
'''the method of sort'''
return lambda x: (x['service_time'], x['arrival_time'], x['index'])
def sort_data(self, data):
return sorted(data, key=self.cmp())
def update_information(self, index, start, end):
self.data[index]['start'] = start
self.data[index]['end'] = end
self.data[index]['state'] = 'f'
self.data[index]['turnaround_time'] = end - \
self.data[index]['arrival_time']
self.data[index]['authorized_turnover_time'] = self.data[index]['turnaround_time'] / \
self.data[index]['service_time']
self.start = start
self.end = end
self.show_data_running(start, end, self.data[index])
def get_next_data(self, index, data):
# get tasks from the beginning to the end of the current task
result = [x for x in self.data if x['arrival_time'] <=
self.end and x['state'] == 'w' and x not in data]
if result or data:
return result
# no tasks entered at current time
for task in self.data:
if task['state'] == 'w':
self.start = self.end = task['arrival_time']
return [task]
return []
def implement(self):
'''start algorithm'''
# get first task
data = [self.data[0]]
# update the time of start
self.start = self.end = data[0]['arrival_time']
while data:
# update information
self.update_information(
data[0]['index'], self.end, self.end + data[0]['service_time'])
# get next task or tasks
data += self.get_next_data(data.pop(0)['index'], data)
# maintain the queue
data = self.sort_data(data)
self.data.sort(key=lambda x: x['id'])
def get_y_ticks(self):
return [x['id'] for x in self.data] + [self.data[-1]['id'] + 1], [x['name'] for x in self.data] + ['']
def init_image(self):
# size = 1000 * 500
plt.figure('SJF', figsize=(10, 5))
self.drow_image()
# setting xticks for 0 to self.end + 2
plt.xticks([i for i in range(self.end + 3)])
# setting title
plt.title('the time of task about SJF')
plt.xlabel('')
plt.ylabel('tasks')
# setting yticks.such as A == 0
plt.yticks(self.get_y_ticks()[0], self.get_y_ticks()[1])
def drow_image(self):
for task in self.data:
# the time line of task from start to end
plt.plot([task['start'], task['end']],
[task['id'], task['id']],
label=task['name'],
lw=2)
# annotation of the key point
plt.plot([task['end'], task['end']],
[-1, task['id']],
'k--',
lw=1)
# legend
plt.legend(loc='best')
def set_ax(self):
ax = plt.gca() # 获取到当前坐标轴信息
ax.spines['right'].set_color('none')
ax.spines['bottom'].set_color('none')
ax.xaxis.set_ticks_position('top') # 将X坐标轴移到上面
ax.invert_yaxis() # 反转Y坐标轴
ax.grid(True, linestyle='-.') # 网格
def show_image(self):
self.init_image()
self.set_ax()
plt.savefig('SJF.png', dpi=300)
plt.show()
def main(self):
if input('Do you want get data by file? y/Y or n/N\n') in ['y', 'Y']:
SJF.get_data_file()
else:
SJF.get_data_input()
SJF.show_data()
SJF.implement()
SJF.show_data()
SJF.show_image()
if __name__ == '__main__':
try:
SJF = Solution()
SJF.main()
except Exception as e:
print('An exception', e)
else:
print('Finish')
finally:
print('finally')