我与您联系,以便了解"如何改变流水车间调度问题"进入布尔可满足性。
我已经为N * N Sudoku,N-queens和Class调度问题做了这样的减少,但是我对如何将Flow shop转换为SAT存在一些问题。
SAT问题如下:
目标是:使用不同的布尔变量,找到每个变量的效果,以便制作"句子"真正。 (如果可以找到解决方案)。
我使用遗传算法创建自己的求解器,能够找到解决方案并证明什么时候没有。而现在,我尝试了不同的NP问题,比如Flow Shop。
流水车间调度问题是车间或集团车间的一类调度问题,其中流量控制应能够为每个作业进行适当的排序,并在一组机器或其他资源上进行处理1,2,... 。,m符合给定的处理订单。
特别是需要保持连续的处理任务流,并且空闲时间最短,等待时间最短。
Flow shop调度是作业车间调度的一个特例,其中对所有作业执行所有操作的严格顺序。
流水车间调度也可适用于计算设计的生产设施。
结果是一系列工作将经历每个研讨会,图形结果将如下所示:
所以为了表示flow-shop实例,在输入中我有这样的文件:
2 4
4 26 65 62
63 83 57 9
这个文件意味着我有2个商店和4个工作,每个工作的每个工作的持续时间都是。
目标:找到最小化C_max的序列,如果您愿意,最后一台机器上的最后一个作业的结束日期。
我的Flow-Shop现在非常简单,但我不知道如何形式化它们以便创建一个CNF文件来执行我的SAT求解器。
如果你们其中一个人有一些想法:文章?一个想法的开始?
此问题的下一部分:Flow/Job Shop to Boolean satisfiability [Polynomial-time reduction] part 2
答案 0 :(得分:3)
我这样做:
每个机器的每个可能时间都有一个布尔变量用于每个资源使用开始(当然,这要求时间是有限的和离散的,所以我假设整数)。
所以你得到像s_1_2_3
这样的变量,其含义是从第二个3开始在机器2上使用的资源。
现在,您可以根据这些变量制定各种条件。像:
警告:即使是小问题,也会产生巨大数量的布尔表达式。
正如@gwilkins所提到的,你需要将优化问题转换为布尔问题。并且我遵循他的方法:找到你愿意接受的最长时间并解决该时间限制(实际上限制了变量的数量)。
您还可以从应该有解决方案的内容(比如添加所有作业的时间)和自然下限(最长作业所需的时间)开始,然后通过拆分间隔找到最佳解决方案。
再一次:这可能会表现得非常糟糕,但它应该提供正确的解决方案。
使用此变量制定约束的示例:
机器1必须在机器2完成其工作之前处理资源x(假设作业的长度为1):
(S_x_1_1 and ! S_x_2_1)
or (S_x_1_2 and ! S_x_2_1 and ! S_x_2_2)
or (S_x_1_3 and ! S_x_2_1 and ! S_x_2_2 and ! S_x_2_3)
or ...
答案 1 :(得分:2)
我正在使用c#;我通过这些if
陈述处理了这个结果:
(EndTime = StartTime + Duration
)
// This is for handling start of M1J4 that starts after end of M2J2
// Bt I think this is out of 'Flow Shop Working'
if (i > 1)
if (M[m].jobs[i].StartTime < M[m + 1].jobs[i - 2].EndTime)
M[m].jobs[i].StartTime = M[m + 1].jobs[i - 2].EndTime;
if (i > 0)
if (M[m].jobs[i].StartTime < M[m + 1].jobs[i - 1].StartTime)
M[m].jobs[i].StartTime = M[m + 1].jobs[i - 1].StartTime;
if (M[m + 1].jobs[i].StartTime < M[m].jobs[i].EndTime)
M[m + 1].jobs[i].StartTime = M[m].jobs[i].EndTime;
我的控制台应用程序代码是:
class job
{
public int Id { get; set; }
public int Duration { get; set; }
public int StartTime { get; set; }
public int EndTime { get { return this.StartTime + this.Duration; } }
public job(int _Id) { this.Id = _Id; }
public override string ToString()
{
if (this.Duration == 1)
return "|";
string result = "[";
for (int i = 0; i < this.Duration - 2; i++)
result += "#";
return result + "]";
}
}
class machine
{
public int Id { get; set; }
public List<job> jobs = new List<job>();
public int C_Max { get { return this.jobs[jobs.Count - 1].EndTime; } }
public machine(int _Id) { this.Id = _Id; }
public job AddJob(int _Duration)
{
int newId = 1;
if (newId < jobs.Count + 1)
newId = jobs.Count + 1;
jobs.Add(new job(newId));
jobs[newId - 1].Duration = _Duration;
if (newId == 1)
jobs[newId - 1].StartTime = 0;
else
jobs[newId - 1].StartTime = jobs[newId - 2].EndTime;
return jobs[newId - 1];
}
public void LagJobs(job fromJob, int lagDuration)
{
for (int i = fromJob.Id; i <= jobs.Count; i++)
jobs[i].StartTime += lagDuration;
}
public void AddJobs(int[] _Durations)
{
for (int i = 0; i < _Durations.Length; i++)
this.AddJob(_Durations[i]);
}
public override string ToString()
{
return this.ToString(false);
}
public string ToString(bool withMax)
{
string result = string.Empty;
for (int i = 0; i < jobs.Count; i++)
{
while (jobs[i].StartTime > result.Length)
result += " ";
result += jobs[i].ToString();
}
result = this.Id.ToString() + ". " + result;
if (withMax)
result += " : " + this.C_Max;
return result;
}
}
class Program
{
static void Main(string[] args)
{
int machinesCount = 4;
List<machine> machines = new List<machine>();
for (int i = 0; i < machinesCount; i++)
{
machines.Add(new machine(i + 1));
}
machines[0].AddJobs(new int[] { 5, 5, 3, 6, 3 });
machines[1].AddJobs(new int[] { 4, 4, 2, 4, 4 });
machines[2].AddJobs(new int[] { 4, 4, 3, 4, 1 });
machines[3].AddJobs(new int[] { 3, 6, 3, 2, 6 });
handelMachines(machines);
for (int i = 0; i < machinesCount; i++)
Console.WriteLine(machines[i].ToString(true));
Console.ReadKey();
}
static void handelMachines(List<machine> M)
{
if (M.Count == 2)
{
for (int i = 0; i < M[0].jobs.Count; i++)
{
if (i > 1)
if (M[0].jobs[i].StartTime < M[1].jobs[i - 2].EndTime)
M[0].jobs[i].StartTime = M[1].jobs[i - 2].EndTime;
if (i > 0)
if (M[0].jobs[i].StartTime < M[1].jobs[i - 1].StartTime)
M[0].jobs[i].StartTime = M[1].jobs[i - 1].StartTime;
if (M[1].jobs[i].StartTime < M[0].jobs[i].EndTime)
M[1].jobs[i].StartTime = M[0].jobs[i].EndTime;
}
}
else
{
for (int i = 0; i < M.Count - 1; i++)
{
List<machine> N = new List<machine>();
N.Add(M[i]);
N.Add(M[i + 1]);
handelMachines(N);
}
}
}
}
结果是:
答案 2 :(得分:0)
第一个read this page (Job Shop Scheduling)
问题是最短路径。对于合理的最佳近似值,请忽略SAT表达式。尝试什么是显而易见的。如果您首先在M1上运行最短的作业,则该作业可以使用M2,而下一个最短的作业正在使用M1。
每个人在这些问题中都忽略的是,有“虚拟机器”正在等待时间状态。最大生产率等于等待状态下的最短时间。因此,每个作业都可以表示为二进制字符串,表示生产性或非生产性任务中的时间。长度为n的每组字符串都可以用n-SAT表达式表示。在多项式时间内,该表达式可以简化为2
请参见this (Three complete deterministic polynomial algorithms for 3SAT)来解决SAT表达式。