clojure.core.matrix ::矩阵中的Mutate元素

时间:2017-04-18 12:24:14

标签: matrix clojure

我使用的矩阵如下

(require '[clojure.core.matrix :as ccm])
(def M (ccm/matrix [[1 2] [3 4]]))
(ccm/mset! M 0 0 10)

然而,这会引发错误

  

IllegalArgumentException没有方法的实现:: set-2d!协议:#'找到类的clojure.core.matrix.protocols / PIndexedSettingMutable:clojure.lang.PersistentVector clojure.core / -cache-protocol-fn(core_deftype.clj:568)

然而,根据维基https://mikera.github.io/core.matrix/doc/clojure.core.matrix.html#var-mset.21

,这应该有效

2 个答案:

答案 0 :(得分:1)

  

然而,这应该根据维基

工作

不,您提供的链接明确指出,如果矩阵不可变,它将抛出异常。 matrix的文档并不清楚它是否产生可变矩阵,但显然它没有。但是,找到一种生成可变矩阵的方法并不难:函数mutable就在同一页面上。

答案 1 :(得分:1)

core.matrix可以使用不同的底层矩阵实现。默认情况下,它使用persistent-vector实现,这意味着矩阵只是包含Clojure向量的Clojure向量。但是,Clojure向量是不可变的,因此mset!不会对它们起作用。这是预期的行为。

要使用mset!,您需要使用可以制作可变矩阵的core.matrix实现之一。 ndarray是默认情况下在core.matrix中始终可用的矩阵实现,但您必须告诉core.matrix您要使用它。

user=> (use 'clojure.core.matrix)
nil
user=> (matrix [[1 2] [3 4]])
[[1 2] [3 4]]

这就是持久向量矩阵的样子。

您可以通过将额外的关键字传递给matrix函数来创建ndarray矩阵:

user=> (def M (matrix :ndarray [[1 2] [3 4]]))
#'user/M
user=> M
#object[clojure.core.matrix.impl.ndarray_object.NDArray 0x561ddbde "[[1 2] [3 4]]"]

现在mset!将起作用:

user=> (mset! M 0 0 10)
10
user=> M
#object[clojure.core.matrix.impl.ndarray_object.NDArray 0x561ddbde "[[10 2] [3 4]]"]

注意右边的元素。您还可以使用pm创建更好的表示形式:

user=> (pm M)
[[10 2]
 [ 3 4]]

要使ndarray成为默认值,请使用set-current-implementation

user=> (set-current-implementation :ndarray)
:ndarray

user=> (def M (matrix [[1 2] [3 4]]))
#'user/M

user=> M
#object[clojure.core.matrix.impl.ndarray_object.NDArray 0x5cd44e57 "[[1 2] [3 4]]"]

user=> (mset! M 0 0 10)
10

user=> M
#object[clojure.core.matrix.impl.ndarray_object.NDArray 0x5cd44e57 "[[10 2] [3 4]]"]

如果将它们设置为依赖项(例如在Leiningen project.clj中),还有其他几种可用的实现。其中一些支持可变和不可变矩阵。

顺便说一句,正如合金建议的那样,你可以通过将不可变矩阵传递给mutable来从不可变矩阵中获得可变矩阵。如果使用持久向量矩阵执行此操作,则返回的矩阵将不是持久向量矩阵,因为没有可变的持久向量矩阵。新矩阵将是来自不同实现的矩阵。使用哪种实现取决于您当前的环境,但如果您没有做任何特殊操作,则应该返回ndarray矩阵。