1

跟进这个问题。我有一个大而稀疏的矩阵(是的,我有)。

A = [
     [0,   0, 0, 1.2, 0]
     [0,   0, 0, 0,   0]
     [3.5, 0, 0, 0,   0]
     [0    7, 0, 0,   0]
]

我想创建一个向量,其中包含每一行v的总和v[j] = v[j,] * log(v[j,])A

我相信有一个迭代器,[x * log(x) for x in row] do...但我很难找到语法。一个特别的 bugaboo 是避免log(0)使用 ,所以也许是if迭代器中的一个语句?

4

1 回答 1

1

我相信有一个像 [x * log(x) for x in row] 这样的迭代器......但我很难找到语法。

我们可以创建一个计算函数,而不是创建一个迭代器,x * log(x)然后将一个数组(或数组切片)传递给它,让提升来处理其余的事情。

而不是+ reduce像我们之前做的那样在数组切片上做一个,

forall i in indices {
  rowsums[i] = + reduce(A[i, ..]);
}

我们可以+ reduce对数组切片做一个提升操作,如下所示:

forall i in indices {
  rowsums[i] = + reduce(logProduct(A[i, ..]));
}

wherelogProduct(x)可以包含一个 if 语句来处理 的特殊情况0,如上所述。

把这一切放在一起看起来像这样:

config const n = 10;

proc main() {
  const indices = 1..n;
  const Adom = {indices, indices};
  var A: [Adom] real;

  populate(A);

  var v = rowSums(A);

  writeln('matrix:');
  writeln(A);

  writeln('row sums:');
  writeln(v);
}


/* Populate A, leaving many zeros */
proc populate(A: [?Adom]) {
  forall i in Adom.dim(1) by 2 do // every other row
    forall j in Adom.dim(2) by 3 do // every third column
      A[i, j] = i*j;
}

/* Compute row sums with custom function (logProduct) */
proc rowSums(A: [?Adom] ?t) {
  var v: [Adom.dim(1)] t;

  [i in v.domain] v[i] = + reduce(logProduct(A[i, ..]));

  return v;
}

/* Custom function to handle log(0) case */
proc logProduct(x: real) {
  if x == 0 then return 0;
  return x * log(x);
}
于 2017-08-21T22:29:46.767 回答