Mathematica Reduce / Solve:询问非重复值的最佳方式

时间:2011-05-28 00:17:26

标签: wolfram-mathematica

有几次我发现我有一个系统,我需要指定所有变量都有不同的值(即非重复)。

我经常做这样的事情:

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

3 个答案:

答案 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修复了所有剩余的约束。没有必要测试一切。例如,

  1. f = a + bf ≠ a&amp; f ≠ b
  2. f = e + gf ≠ e&amp; f ≠ g
  3. 2f = d + ef ≠ df ≠ eg ≠ d
  4. c = g + dc ≠ g&amp; c ≠ d
  5. 依此类推......你可以详细解决这个问题。

    我知道这可能只是一个测试示例,我没有一个聪明而快速的一站式答案,您可以在不考虑问题的情况下使用。