有几次我发现我有一个系统,我需要指定所有变量都有不同的值(即非重复)。
我经常做这样的事情:
k = {a, b, c, d, e, f, g};
Reduce[
a != 2 && f == a + b && g == c - d && f == (d + e)/2 && f == e + g &&
First[And @@@ {0 < # < 8 & /@ k}] &&
Times@(Sequence @@ (Subsets[k, {2}] /. {x_, y_} -> (x - y))) != 0,
k, Integers]
Reduce等式的最后部分
Times@(Sequence @@ (Subsets[k, {2}] /. {x_, y_} -> (x - y))) != 0
要求不同的价值观。
有更好的方法吗? (我的意思是,产品不等于零,而是指定I need all variables different
)
答案 0 :(得分:7)
从速度的角度来看,您在产品条件下会产生很大的开销。如果您的解决方案始终是数字,则可以使用Reduce
生成所有解决方案,然后对其进行过滤 - 在某些情况下可能会更快。例如,在手头的情况下:
k = {a, b, c, d, e, f, g};
sl = Reduce[ a != 2 && f == a + b && g == c - d && f == (d + e)/2 && f == e + g &&
First[And @@@ {0 < # < 8 & /@ k}], k, Integers]
您可以进行后期处理,例如这样(也许不是最佳方式):
In[21]:= Select[{#, First[k /. Solve[#, k]]} & /@ List @@ sl,
MatchQ[Tally[#[[2]], Equal][[All, 2]], {1 ..}] &][[All, 1]]
Out[21]= {a == 3 && b == 2 && c == 7 && d == 6 && e == 4 && f == 5 && g == 1}
至少对于这个特殊情况,它要快得多。
答案 1 :(得分:6)
对于小问题,post =处理以删除不需要的解决方案可能是最好的。对于较大的问题,至少有两种有用的方法。
(1)如果允许的值是连续的,或几乎是连续的,则可以为每个原始变量的网格和可能的值创建0-1变量。例如,如果您的变量旨在填写标准的Sudoku数组,则可以使用x [i,j,k] = 1来指示第i行col j中的值为k。例如,约束第1行中的值不会重复
Sum[x[1,j,1]==1, {j,9}]
... Sum [x [1,j,9] == 1,{j,9}]
如果并非所有值都需要在所有地方使用(例如行),那么这些值可能会变成不等式。
(2)另一种方法是,如果需要区分的值,则为每对使用0-1变量。我们假设值范围至少有一个已知的上限和下限。叫它m。所以对于任何一对变量x和y,我们知道差异在-m和m之间(可以在那里加/减,但不是必需的)。
对于需要不同的x [i]和x [j]对,添加一个新变量0-1 k [i,j]。想法是如果x [i]> x [j]则需要为1,如果x [j]> x [i]则需要为0. *
对于这一对,我们添加两个方程。我将以非扩展形式显示它们,因为这可能稍微容易理解。
x[i]-x[j] >= k[i,j] + m*(k[i,j]-1)
x[j]-x[i] >= (1-k[i,j]) + m*(-k[i,j])
如果x [i]> x [j],则仅对k [i,j] == 1满足两者。反之亦然x [j]&gt; x [i]和k [i.j] == 0。
当变量可以跨越大大大于变量数量的值范围时,或者当所有对被约束为不同的值时,这可能是首选方法。
Daniel Lichtblau
*星期六晚上很晚,所以我倒退了。还请在你处理时解决所有拼写错误。
答案 2 :(得分:3)
为什么不直接提供唯一性约束?
k = {a, b, c, d, e, f, g};
uniqueness = {a != b != e};
sl = Reduce[
a != 2 && f == a + b && g == c - d && f == (d + e)/2 && f == e + g &&
First[And @@@ {0 < # < 8 & /@ k}] && First@uniqueness , k,
Integers]//Timing
Out[1]= {0.046791, a == 3 && b == 2 && c == 7 && d == 6 && e == 4 && f == 5 && g == 1}
通过粗略地看一下上面的约束,大多数唯一性要求都是由其他约束自我满足,设置a≠b≠e
修复了所有剩余的约束。没有必要测试一切。例如,
f = a + b
⇒f ≠ a
&amp; f ≠ b
f = e + g
⇒f ≠ e
&amp; f ≠ g
2f = d + e
⇒f ≠ d
∵f ≠ e
⇒g ≠ d
c = g + d
⇒c ≠ g
&amp; c ≠ d
依此类推......你可以详细解决这个问题。
我知道这可能只是一个测试示例,我没有一个聪明而快速的一站式答案,您可以在不考虑问题的情况下使用。