时间表排列生成和内存优化

时间:2018-02-08 15:46:57

标签: c# optimization memory-management cartesian-product

我正在创建一个程序来优化我大学为学生的时间表提供的课程。

我将数据解析为以下结构/类:

public struct Subject
{  
    public int Classes {...}
    public int Hours { ... }
    public string Name { get; set; }
    public string Code { get; set; }
    public string Base_Code;
    public Campus Campus { get; set; }
    public Semester Semester;  
}

public struct Timeslot
{
    public string ClassType; //code for type: i.e. L for Lecture, W for Workshop
    public string Description;
    public DayOfWeek Day;
    public DateTime Start, Finish;
    public List<Tuple<string, string>> weekSpans;
    public string Location;
}

public struct Class
{
    public Subject subject { get; set; }
    public Timeslot time { get; set; }
}

在本学期的 n 科目中,我总共有 m 必修课程(讲座1,2,3,研讨会e.t.c)。我将这些存储在类型&#39;类&#39;列表中。

例如:

第1讲(科目1)

  • class @ 9am Monday
  • 星期一下午1点

工作坊1(科目2)

  • class @ 9am Monday
  • 课堂周二下午2点

我目前正在使用Eric Lippert的笛卡尔积法生成由{em> n - 类组合组成的IEnumerable<IEnumerable<Class>>

static IEnumerable<IEnumerable<T>> CartesianProduct<T>(this IEnumerable<IEnumerable<T>> sequences) 
{ 
  // base case: 
  IEnumerable<IEnumerable<T>> result = new[] { Enumerable.Empty<T>() }; 
  foreach(var sequence in sequences) 
  { 
    var s = sequence; // don't close over the loop variable 
    // recursive case: use SelectMany to build the new product out of the old one 
    result = 
      from seq in result 
      from item in s 
      select seq.Concat(new[] {item}); 
    } 
  return result; 
}

然而,当我需要从每个IEnumerable收集必要的信息以确定哪个时间表符合设定标准(更短的天数,大多数休假日,e.t.c。)时,我的问题就出现了。试图遍历所有并将它们存储在我的TimeTable容器类中对于存储初始排列所需的内存之外的内存实际上是非常重要的。

public class TimeTable
{
    public IEnumerable<Class> _classes;
    public DateTime MinStart { get; private set; }
    public DateTime MaxFinish { get; private set; }
    public int DaysOff { get; private set; }
    public TimeTable(IEnumerable<Class> Classes) { ... }
}

事实上,我的内存猛增至2GB然后崩溃,实在太费力了。我曾想过通过丢弃包含冲突的时间表来优化排列过程,我知道该怎么做,但我无法弄清楚我可以将代码放入CartesianProduct算法的哪个位置,以便它不会保留在内存中。我还想过为每个班级分配一个ID,然后计算排列,但是并没有根据用户的偏好来优化对时间表进行排序的需要。

这是我的第一个个人项目,我必须处理组合和内存优化,所以我会非常感谢任何有关如何优化此优化过程的建议和帮助(哈!)。

1 个答案:

答案 0 :(得分:0)

您无需将所有元素组合存储在大型超级集合中,以迭代它们。我曾写过一个java solution,它应该可以轻松转换为c#,但可能不完全适合,但主要的想法,我可以在这里布局。

你有一些必修课程要结合,让我们假设a1,a2,a3; b1,b2; c1,c2,c3,c4。

学生必须选择一个,一个是b,一个是c。

可能的组合数量为a.size * b.size * c.size = 3*2*4 = 24

因此,不是生成组合并迭代它们,而是使用int i循环或迭代数字0到23,并选择一个课程组合,如果你已经构建了组合,那么它将在索引i处。

怎么做?好吧,假设数字i是17. i%(c.size)= 17%4 = 1.这将是c,c2的第二个(0,1,2,3)元素。

现在我们将i&#39; (i%c.size)由c.size得到17/4 = 4。 4%b.size(2)= 0因此对于b,我们得到index = 0,即b1。

我&#39;除以b.size,即i&#34; = 2。在指数2(%(3 = a.size)),我们找到a3。对于最后一个元素,我们不需要模数,但另一方面,它没有任何伤害并且允许统一的过程。

尝试使用小数字来说服自己,所有组合都会以系统的顺序完全可靠地发生。

如果两个课程发生冲突,请选择下一个课程。