如何优化跳转表的大小?

时间:2013-09-02 09:59:15

标签: algorithm enums mathematical-optimization

考虑类似C语言的典型枚举类型:

enum foo {
    FOO_A,
    FOO_B,
    FOO_C,
    /* ... */
    FOO_N
};

enum foo类型的值有switch语句,可能无法处理某些枚举值:

enum foo bar;
/* ... */
switch (bar) {
case FOO_A: /* ... */
case FOO_B: /* ... */
case FOO_D: /* ... */
case FOO_L: /* ... */
default: /* ... */
}

现在,为了处理足够多的枚举值,编译器将使用大小为的跳转表来实现switch语句(<最高处理值> - <最低处理值> + 1)*的sizeof(无效*)

考虑我有多个这样的switch语句已知使用跳转表,因为每个语句都知道正在处理哪些值而哪些值不是。如何以某种方式对enum foo中的值重新排序,生成的所有跳转表的总大小是最小的?

实施例

这是一个略微简化的示例,假设编译器为所有switch语句生成跳转表。这是枚举:

enum example {
    EX_A,
    EX_B,
    EX_C,
    EX_D
};

这是两个开关语句:

enum example a, b;

switch (a) {
case EX_A: /* ... */
case EX_C: /* ... */
default: /* ... */
}

switch (b) {
case EX_B: /* ... */
case EX_D: /* ... */
default: /* ... */
}

对于此示例,编译器将生成两个跳转表,每个跳转表包含三个条目(在第一种情况下从EX_AEX_C,在第二种情况下从EX_B到{{1用于跳转表的总共6个机器字。如果我像这样重新排序枚举:

EX_D

我只需要4个数据字作为跳转表。

2 个答案:

答案 0 :(得分:4)

这个问题是NP难的,因为它概括了从图到超图的最小线性排列问题(MinLA),MinLA是NP-hard(Garey-Johnson-Stockmeyer 1976)。

已经完成了一些关于解决MinLA问题的研究。有一个看起来很普遍的Theta(2 ^ n m)时间动态程序(Koren - Harel 2002)。线性编程松弛有很多工作,既可以获得保证的近似值,也可以用于分支定界。不幸的是,这些放松似乎都太大了,无法通过求解器直接消费。可能有人尝试过限制编程,但我的粗略搜索没有任何结果。有许多启发式方法,包括Juvan和Mohar(1992)提出的以下可爱想法:根据拉普拉斯算子的第二个特征向量对标签进行排序。

只有50个标签,如果找到一个可证明的最佳安排,我不会感到惊讶,但如果它没有在实例上进行几轮新颖的算法设计,实现和实验,我会感到惊讶(s ) 出于兴趣。如果你想学习一些涉及的技巧,我会推荐Pascal van Hentenryck在Coursera上的Discrete Optimization课程(我从他加入布朗大学时的早期版本开始)。

答案 1 :(得分:-1)

一种解决方案(可能更快)。是通过做部分蛮力。

如果将每个开关视为一组,则可以首先聚集所有组(即开关)的交集。

拥有以下枚举:

enum example {
    EX_A,
    EX_B,
    EX_C,
    EX_D,
    EX_E
};

这两个转换语句:

枚举示例a,b;

switch (a) {
case EX_A: /* ... */
case EX_C: /* ... */
case EX_E: /* ... */
default: /* ... */
}

switch (b) {
case EX_B: /* ... */
case EX_D: /* ... */
case EX_E: /* ... */
default: /* ... */
}

交叉点是:

{ EX_E }

其余的元素是:

{ EX_A, EX_B, EX_C, EX_D }

因此,您可以先放置交集,然后浏览其余的所有排列并生成所有跳转表,并查看哪一个是较小的跳转表。这是n! (在这个例子中,您必须查看4!= 24个配置)。