我正在进行生产计划项目,所以我想在某些机器(A,B)中找到订单生产开始时间。
为简化起见,我想我有2台机器(机器A和机器B) 我有以下约束:
每台机器只能在一天中的某些时段工作(A_TimeLimitation
,B_TimeLimitation
)
出于简化的目的,我认为
机器A可以在以下范围内工作:
(2014/12/4 00:00:00 - 2014/12/4 02:00:00)或(2014/12/4 04:00:00 - 2014/12 / 4 06:00:00)
机器B可以在以下范围内工作:
(2014/12/4 02:00:00 - 2014/12/4 04:00:00)或(2014/12/4 05:00:00 - 2014/12 / 4 07:00:00)
每件产品必须经过机器A,然后经过机器B.
我使用以下代码将DateTime
转换为分钟:
var minutes = new TimeSpan(dateTime.Ticks).TotalMinutes;
因此,使用上面的代码,我的DateTime
范围转换为Double
范围。
我正在使用Microsoft Solver Foundation来解决问题,因此我使用了以下代码:
var context = SolverContext.GetContext();
var model = context.CreateModel();
var a_OperationTime = 60;
var b_OperationTime = 60;
var tolerance = 10;
//Decision
Decision A_StartTime = new Decision(Domain.IntegerNonnegative, "A_StartTime");
model.AddDecision(A_StartTime);
Decision B_StartTime = new Decision(Domain.IntegerNonnegative, "B_StartTime");
model.AddDecision(B_StartTime);
//Constraints
model.AddConstraint("A_TimeLimitations" ,
(1059220800 <= A_StartTime <= 1059220860) |
(1059221160 <= A_StartTime <= 1059221220));
model.AddConstraint("B_TimeLimitations" ,
(1059220920 <= B_StartTime <= 1059220980) |
(1059221100 <= B_StartTime <= 1059221160));
model.AddConstraint("B_ContiguousLimitations" ,
B_StartTime - (A_StartTime + 60) <= tolerence);
//Goal
var A_StartTime = model.Decisions.First(x => x.Name == "A_StartTime");
var B_StartTime = model.Decisions.First(x => x.Name == "B_StartTime");
model.AddGoals("OrderDuration", GoalKind.Minimize, B_StartTime - A_StartTime);
//Solve
var directive = new ConstraintProgrammingDirective();
//directive.TimeLimit = 10000;
var solution = context.Solve(directive);
但是当我运行代码时,似乎进入无限循环,当我为TimeLimit
指定directive
时,在10000毫秒之后,solution.Quality
为Unknown
这意味着MSF
无法找到任何解决方案,如果我删除了机器DateTime
中的第二个A
范围,则代码可以找到解决方案。
有谁知道问题出在哪里?
答案 0 :(得分:1)
我发现了问题
DateTime
更改为double
转换方法所以最终解决方案就在这里:
//extention method for converting DateTime to normalized double
public static double ToMinutes(this DateTime value)
{
return (value-new DateTime(2014, 12, 3)).TotalMinutes;
}
var a1_start = new DateTime(2014, 12, 4).ToMinutes();
var a1_finish = new DateTime(2014, 12, 4, 2, 0, 0).ToMinutes();
var a2_start = new DateTime(2014, 12, 4, 4, 0, 0).ToMinutes();
var a2_finish = new DateTime(2014, 12, 4, 6, 0, 0).ToMinutes();
var b1_start = new DateTime(2014, 12, 4,1,0,0).ToMinutes();
var b1_finish = new DateTime(2014, 12, 4, 1, 55, 0).ToMinutes();
var B2_start = new DateTime(2014, 12, 4, 5, 0, 0).ToMinutes();
var B2_finish = new DateTime(2014, 12, 4, 6, 0, 0).ToMinutes();
var context = SolverContext.GetContext();
var model = context.CreateModel();
var a_OperationTime = 60;
var b_OperationTime = 60;
var tolerance = 10;
//Decision
Decision A_StartTime = new Decision(Domain.IntegerNonnegative,"A_StartTime");
model.AddDecision(A_StartTime);
Decision B_StartTime = new Decision(Domain.IntegerNonnegative,"B_StartTime");
model.AddDecision(B_StartTime);
//Constraints
model.AddConstraint("A_TimeLimitations",
((a1_start <= A_StartTime <= a1_finish) &
(a1_start + 60 <= A_StartTime + 60 <= a1_finish)) |
((a2_start <= A_StartTime <= a2_finish) &
(a2_start + 60 <= A_StartTime + 60 <= a2_finish)));
model.AddConstraint("B_TimeLimitations",
((b1_start <= B_StartTime <= b1_finish) &
((b1_start + 60 <= B_StartTime + 60 <= b1_finish))) |
((B2_start <= B_StartTime <= B2_finish) &
(B2_start + 60 <= B_StartTime + 60 <= B2_finish)));
model.AddConstraint("B_ContiguousLimitations",
B_StartTime - (A_StartTime + 60) <= tolerance);
model.AddConstraint("B_GreaterThan_A",
B_StartTime >= A_StartTime + 60);
//Goal
A_StartTime = model.Decisions.First(x => x.Name == "A_StartTime");
B_StartTime = model.Decisions.First(x => x.Name == "B_StartTime");
model.AddGoals("OrderDuration",GoalKind.Minimize, B_StartTime - A_StartTime);
//Solve
var directive = new ConstraintProgrammingDirective();
var solution = context.Solve(directive);