根据相同的随机值更改表中的两个不同部分

时间:2011-07-02 16:01:43

标签: wolfram-mathematica

我试图每次根据一个随机变量更改我表中的2个不同的行,例如我想要一个随机数> 0.5然后用它中的值改变一行+1而另一行用它来改变值-1,否则什么都不做。我尝试了以下代码,但我很困惑,有人可以帮助我吗?

InitialMatrix[3, 3, 3, 3] + 
  MapAt[f, MapAt[g, Table[0, {3}, {3}, {3}, {3}],

    Flatten[Table[{i, j, 1, k}, {i, 3}, {j, 3}, {k, 3}], 2]], 
   Flatten[Table[{i, j, 2, k}, {i, 3}, {j, 3}, {k, 3}], 2]] // TableForm

f[x_] := If[RandomReal[] > 0.5, g[x] = If[x > 0, x - 1, x]; 
  If[g[x] > 0, x + 1, x], x]

非常感谢!!

修改:更改了要求

我有一个四维表,我想相对于彼此更改它的值。

我的桌子是

InitialMatrix[x_, y_, age_, disease_] :=

  ReplacePart[ Table[Floor[Divide[dogpopulation/cellsno,  9]], 
    {x}, {y}, {age},  {disease}], {{_, _, 1, _} ->   0, {_, _, 3, _} -> 6}];

我试图每次根据一个随机变量更改每个子矩阵中的前两行。

例如,我想要一个随机数> 0.4,然后改变第一行中的第一个元素,其值为+1,第二行的第一个元素的值减去1,否则保持该值不变。 / p>

我想用不同的随机数检查第一行中的每个元素,如果条件为真,则更改第1行和第2行。我可以这样做吗?

2 个答案:

答案 0 :(得分:2)

f[mylist_List, rowPlus_Integer, rowMinus_Integer] := 
  Module[{temp = mylist},
    If[1 <= rowPlus <= Length@temp && 1 <= rowMinus <= Length@temp,
      If[ RandomChoice[{True, False}], 
        temp[[rowPlus]]++;
        temp[[rowMinus]]--];
      Return@temp,
    (*else*)
       Print@"Wrong row value"; Abort[]]]

a = IdentityMatrix[3]
a = f[a, 1, 2]
(*
{{2, 1, 1}, {-1, 0, -1}, {0, 0, 1}}
*)
a = IdentityMatrix[3]
a = f[a, 1, 2]
(*
{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}
*)

修改

根据您的新规范:

f[mylist_List, rowPlus_Integer, rowMinus_Integer, cutoff_Real] :=
 Module[{temp = mylist},
  If[1 <= rowPlus <= Length@temp && 1 <= rowMinus <= Length@temp,
   MapIndexed[
    If[#1 > cutoff,
      temp[[rowPlus, First@#2]]++;
      temp[[rowMinus, First@#2]]--] &,
    RandomReal[1, Dimensions@temp[[2]]]];
   Return@temp,
   (*else*)
   Print@"Wrong row value"; Abort[]]]

用法

a = IdentityMatrix[3];
a = f[a, 1, 2, .5]
(*
->{{2,1,0},{-1,0,0},{0,0,1}}
*)

答案 1 :(得分:1)

这个答案有“我在没有Mathematica工作的情况下检查我的语法”咨询

@belisarius'的答案非常有效,更优雅,几乎可以肯定比我的更有效率。但是您可能会发现使用ArrayFlatten命令(documentation)或Join命令(documentation)更容易理解的替代方法。

第一个选项假设您需要类似问题中的CODE要求的内容,而不是文本中所述的内容。然后你会使用类似的东西:

nonisFunction[mylist_List,firstrowsub_?VectorQ, 
secondrowsub_?VectorQ,cutoff_Real]/; Length[Dimensions[mylist]]==4  :=
Table[
If[RandomReal[]>cutoff, 
    Join[{firstrowsub},{secondrowsub},Drop[mylist[[i,j]],2] ],
    mylist[[i,j]] ], 
    {i,Dimensions[mylist][[1]]}, {j,Dimensions[mylist][[2]]} ]

这有效地使每个子矩阵再次将它重新拼接在一起,如果超过了截止值,则每次取代两行时进行替换,但如果不是则保留单独的子矩阵。

如果您想要的是增加和减少两行(即您的文本问题而不是您提供的代码),那么类似的解决方案只需要添加,而不是Join。因为PlusListable,所以它应该在每个子矩阵的行上添加向量的线程。

nonisFunction[mylist_List,cutoff_Real]/; Length[Dimensions[mylist]]==4  :=
Table[
mylist[[i,j]] +
 If[RandomReal[]>cutoff, {1,-1,0,0}, {0,0,0,0} ],
    {i,Dimensions[mylist][[1]]}, {j,Dimensions[mylist][[2]]} ]

这种基于表格的编程风格更像是你习惯的程序编程风格(四重嵌套For循环),但它仍然更有效,我得出的结论是你更多可能会理解代码。

编辑:回复评论中的noni问题的其他材料 要运行此代码(以上面的第二个示例函数作为此过程的示例),您首先要通过将上述代码复制并粘贴到Mathematica笔记本中来定义函数。然后,您将定义输入矩阵并为其指定名称。 e.g。

myinputmatrix = RandomInteger[{10,100},{4,4,4,4}];

最后,使用适当的参数调用nonisFunction

nonisFunction[myinputmatrix,0.4]

如果这没有帮助,我推荐视频教程http://www.wolfram.com/support/learn/get-started-with-mathematica/