如何在Python中对某些东西进行建模?

2024-05-16 02:51:30 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在寻找一种数据类型,以帮助我在流动的时间内建模资源可用性

  • 我们从9点到6点营业,可以处理5个并行作业。在我想象的编程环境中,我刚刚初始化了一个范围为3的对象
  • 我们有预约,每个都有开始和结束时间
  • 我每天都要把它们打出来
  • 这给我留下了一张可用性上下变化的图表,但最终允许我快速找到剩余可用性的时间范围

我从多个方面讨论过这个问题,但总是回到根本问题上来,即不知道一种数据类型可以随着时间的推移对像整数这样简单的东西进行建模

我可以将我的约会转换为时间序列事件(例如约会到达意味着-1可用性,约会离开意味着+1),但我仍然不知道如何处理这些数据,以便我可以提取出可用性大于零的时段


有人以注意力不集中为由投了接近票数的一票,但我的目标似乎很奇怪,所以我将尝试以图形方式解释这个问题。我试图推断一段时间内,活动作业的数量低于给定的容量

enter image description here

将已知并行容量范围(如9-6之间的3)和具有可变开始/结束的作业列表转换为可用时间的时间范围列表


Tags: 对象列表环境编程作业图表时间资源
3条回答

对我来说,这个问题可以用一系列布尔值来表示。为了便于解释,让我们假设每个潜在工作的时间是15分钟的倍数。因此,从9点到6点,我们有135个“时间段”需要跟踪可用性。我们用布尔变量表示一个队列在一个时隙中的可用性:False如果该队列正在处理一个作业,True如果该队列可用

首先,我们为每个队列以及输出创建一个时隙列表。因此,每个队列和输出都有时隙tk,1<;=k<;=135.

然后,给定五个作业队列,qj,1<;=j<;=5,如果存在至少一个qj,其中索引k处的时隙列表为^{,则我们说tk在时间k处是“打开的”

我们可以在独立Python中实现这一点,如下所示:

slots = [ True ] * 135
queues = [ slots ] * 5
output = [ False ] * 135

def available (k):

 for q in queues:
  if q[k]:
   return True

 return False

然后,我们可以假设存在某个函数dispatch (length),该函数将作业分配给可用队列,将queue[q]中的适当插槽设置为False

最后,要更新输出,我们只需调用:

def update():

 for k in range(0, 135):
  output[k] = available[k]

或者,为了提高效率:

def update(i, j):
 for k in range(i, j):
  output[k] = available[k]

然后,只要在dispatch()为新作业更新时隙ij时调用update(i, j)。这样,分派和更新是一个O(n)操作,其中n是正在更改的时隙数,而不管有多少时隙

这将允许您创建一个简单的函数,将人类可读的时间映射到时隙值的范围上,这将允许按照您的意愿使时隙变大或变小

您还可以很容易地扩展这个想法,使用pandas数据帧,其中每一列都是一个队列,允许您一次对每一行使用Series.any()来快速更新输出列

希望听到关于这种方法的建议!也许我忽略了问题的复杂性,但我认为这是一个很好的解决方案

我会像你对待约会一样对待它。 将空闲时间建模为自己的约会。 对于每个结束约会,请检查是否有其他正在进行的约会,如果有,请跳过此处。 如果没有,请查找下一个开始约会(开始日期大于此结束日期的约会)

在你重复了所有的约会之后,你应该有一个反转的面具

我的方法是构建时间序列,但包括一个值设置为该期间可用性的可用性对象

availability: 
[
  {
    "start": 09:00,
    "end": 12:00,
    "value": 4
  },
  {
     "start": 12:00,
     "end": 13:00,
     "value": 3
  }
]
data: [
  {
    "start": 10:00,
    "end": 10:30,
  }
]

以该值为值,根据开始/结束时间构建时间序列索引。可用性的开始时间为+值,结束时间为-值。而对于一个事件,正如你所说,它应该是-1或+1

"09:00" 4
"10:00" -1
"10:30" 1
"12:00" -4
"12:00" 3
"13:00" -3

然后按指数、总和和累积总和进行分组

获取:

"09:00" 4
"10:00" 3
"10:30" 4
"12:00" 3
"13:00" 0

熊猫中的示例代码:

import numpy as np
import pandas as pd


data = [
  {
    "start": "10:00",
    "end": "10:30",
  }
]

breakpoints = [
  {
    "start": "00:00",
    "end": "09:00",
    "value": 0
  },
  {
    "start": "09:00",
    "end": "12:00",
    "value": 4
  },
  {
    "start": "12:00",
    "end": "12:30",
    "value": 4
  },
  {
    "start": "12:30",
    "end": "13:00",
    "value": 3
  },
  {
    "start": "13:00",
    "end": "00:00",
    "value": 0
  }
]

df = pd.DataFrame(data, columns=['start', 'end'])

print(df.head(5))

starts = pd.DataFrame(data, columns=['start'])
starts["value"] = -1
starts = starts.set_index("start")

ends = pd.DataFrame(data, columns=['end'])
ends["value"] = 1
ends = ends.set_index("end")

breakpointsStarts = pd.DataFrame(breakpoints, columns=['start', 'value']).set_index("start")

breakpointsEnds = pd.DataFrame(breakpoints, columns=['end', 'value'])
breakpointsEnds["value"] = breakpointsEnds["value"].transform(lambda x: -x)
breakpointsEnds = breakpointsEnds.set_index("end")

countsDf = pd.concat([starts, ends, breakpointsEnds, breakpointsStarts]).sort_index()
countsDf = countsDf.groupby(countsDf.index).sum().cumsum()

print(countsDf)

# Periods that are available

df = countsDf
df["available"] = df["value"] > 0

# Indexes where the value of available changes
# Alternatively swap out available for the value.
time_changes = df["available"].diff()[df["available"].diff() != 0].index.values
newDf = pd.DataFrame(time_changes, columns= ["start"])

# Setting the end column to the value of the next start
newDf['end'] = newDf.transform(np.roll, shift=-1)
print(newDf)

# Join this back in to get the actual value of available
mergedDf = newDf.merge(df, left_on="start", right_index=True)

print(mergedDf)

最后返回:

   start    end  value  available
0  00:00  09:00      0      False
1  09:00  13:00      4       True
2  13:00  00:00      0      False

相关问题 更多 >