如何将存储在嵌套字典中的稀疏三角矩阵提高到二次方?
How can I raise a sparse triangular matrix stored in a nested dictionary to the 2nd power?
我有一个稀疏三角矩阵,我需要求它的二次方。问题是,其中一个要求是矩阵存储为嵌套字典(我需要创建一个 python 实现),因此 numpy 的标准函数不适用。 (我知道这种存储矩阵的方式可能有点矫枉过正,但这是大学课程)
下面是我如何实现矩阵本身的创建(稀有相当于这里的稀疏):
def __init__(self, *matrix):
self.rare_values = dict()
if len(matrix) > 0:
for i, line in enumerate(matrix):
if i == 0:
self.n = line
continue
value = line[0]
i = line[1]
j = line[2]
if j > i:
i = line[2]
j = line[1]
if i in self.rare_values.keys():
if j in self.rare_values[i].keys():
self.rare_values[i][j] += value
else:
dict_column = {j: value}
self.rare_values[i].update(dict_column)
else:
dict_line = {i: {j: value}}
self.rare_values.update(dict_line)
我的问题是,是否可以实现一种算法来提高这样一个矩阵的二次方?如果是这样,如果您能提供伪代码或最简单的解释来说明我将如何处理它,我将不胜感激。
谢谢!
您提供的代码可以大大简化为:
class Sparse:
def __init__(self, n=None, *matrix):
self.rare_values = dict()
self.n = n
for line in matrix:
value, *indices = line
c,r = sorted(indices)
# Personally, here I would have instead used
# r,c = sorted(indices, reverse=True)
# as (r,c) order seems more common, but it's no big deal.
self.rare_values.setdefault(r, {})[c] = value
这会产生与您的 __init__
方法相同的结构,只是更清晰 (IMO)。
从那里开始,对每个值求平方就像遍历 dict-of-dicts 一样简单,例如使用嵌套的 for 循环遍历 .items()
:
def square(self):
for (r,row) in self.rare_values.items():
for (c,val) in row.items():
self.rare_values[r][c] = val ** 2
示例:
class Sparse:
def __init__(self, n=None, *matrix):
self.rare_values = dict()
self.n = n
for line in matrix:
value, *indices = line
c,r = sorted(indices)
self.rare_values.setdefault(r, {})[c] = value
def square(self):
for (r,row) in self.rare_values.items():
for (c,val) in row.items():
self.rare_values[r][c] = val ** 2
s = Sparse(3, (0,0,0), (2,1,1), (4,0,2), (6,2,3), (8,0,4))
print(s.rare_values) # {0: {0: 0}, 1: {1: 2}, 2: {0: 4}, 3: {2: 6}, 4: {0: 8}}
s.square()
print(s.rare_values) # {0: {0: 0}, 1: {1: 4}, 2: {0: 16}, 3: {2: 36}, 4: {0: 64}}
Follow-up 来自评论
以下示例显示了如何将矩阵乘方(不是我上面显示的 element-wise 操作)。
注意这段代码改变了你的版本和我的原始版本的一些东西。它接受 (r,c,v) 顺序的项目,并且不会像您强制三角矩阵那样尝试“规范化”索引。
如果您想要这种行为,您必须将此版本编辑为 re-add 那个版本。
class Sparse:
def __init__(self, n=None, entries=None):
self.matrix = dict()
self.n = n
for (r,c,v) in (entries or []):
self.set(r, c, v)
def set(self, r, c, v):
self.matrix.setdefault(r, {})[c] = v
def get(self, r, c):
return self.matrix.get(r, {}).get(c, 0)
def square_matrix(self):
result = Sparse(self.n)
for r in range(self.n):
for c in range(self.n):
val = sum(self.get(r,i) * self.get(i,c) for i in range(self.n))
result.set(r, c, val)
return result
sparse = Sparse(2, [
(0,0,1), (0,1,2),
(1,0,3), (1,1,4),
])
print(sparse.matrix) # {0: {0: 1, 1: 2}, 1: {0: 3, 1: 4}}
# = [[1 2]
# [3 4]]
result = sparse.square_matrix()
print(result.matrix) # {0: {0: 7, 1: 10}, 1: {0: 15, 1: 22}}
# = [[ 7 10]
# [15 20]]
我有一个稀疏三角矩阵,我需要求它的二次方。问题是,其中一个要求是矩阵存储为嵌套字典(我需要创建一个 python 实现),因此 numpy 的标准函数不适用。 (我知道这种存储矩阵的方式可能有点矫枉过正,但这是大学课程)
下面是我如何实现矩阵本身的创建(稀有相当于这里的稀疏):
def __init__(self, *matrix):
self.rare_values = dict()
if len(matrix) > 0:
for i, line in enumerate(matrix):
if i == 0:
self.n = line
continue
value = line[0]
i = line[1]
j = line[2]
if j > i:
i = line[2]
j = line[1]
if i in self.rare_values.keys():
if j in self.rare_values[i].keys():
self.rare_values[i][j] += value
else:
dict_column = {j: value}
self.rare_values[i].update(dict_column)
else:
dict_line = {i: {j: value}}
self.rare_values.update(dict_line)
我的问题是,是否可以实现一种算法来提高这样一个矩阵的二次方?如果是这样,如果您能提供伪代码或最简单的解释来说明我将如何处理它,我将不胜感激。
谢谢!
您提供的代码可以大大简化为:
class Sparse:
def __init__(self, n=None, *matrix):
self.rare_values = dict()
self.n = n
for line in matrix:
value, *indices = line
c,r = sorted(indices)
# Personally, here I would have instead used
# r,c = sorted(indices, reverse=True)
# as (r,c) order seems more common, but it's no big deal.
self.rare_values.setdefault(r, {})[c] = value
这会产生与您的 __init__
方法相同的结构,只是更清晰 (IMO)。
从那里开始,对每个值求平方就像遍历 dict-of-dicts 一样简单,例如使用嵌套的 for 循环遍历 .items()
:
def square(self):
for (r,row) in self.rare_values.items():
for (c,val) in row.items():
self.rare_values[r][c] = val ** 2
示例:
class Sparse:
def __init__(self, n=None, *matrix):
self.rare_values = dict()
self.n = n
for line in matrix:
value, *indices = line
c,r = sorted(indices)
self.rare_values.setdefault(r, {})[c] = value
def square(self):
for (r,row) in self.rare_values.items():
for (c,val) in row.items():
self.rare_values[r][c] = val ** 2
s = Sparse(3, (0,0,0), (2,1,1), (4,0,2), (6,2,3), (8,0,4))
print(s.rare_values) # {0: {0: 0}, 1: {1: 2}, 2: {0: 4}, 3: {2: 6}, 4: {0: 8}}
s.square()
print(s.rare_values) # {0: {0: 0}, 1: {1: 4}, 2: {0: 16}, 3: {2: 36}, 4: {0: 64}}
Follow-up 来自评论
以下示例显示了如何将矩阵乘方(不是我上面显示的 element-wise 操作)。
注意这段代码改变了你的版本和我的原始版本的一些东西。它接受 (r,c,v) 顺序的项目,并且不会像您强制三角矩阵那样尝试“规范化”索引。
如果您想要这种行为,您必须将此版本编辑为 re-add 那个版本。
class Sparse:
def __init__(self, n=None, entries=None):
self.matrix = dict()
self.n = n
for (r,c,v) in (entries or []):
self.set(r, c, v)
def set(self, r, c, v):
self.matrix.setdefault(r, {})[c] = v
def get(self, r, c):
return self.matrix.get(r, {}).get(c, 0)
def square_matrix(self):
result = Sparse(self.n)
for r in range(self.n):
for c in range(self.n):
val = sum(self.get(r,i) * self.get(i,c) for i in range(self.n))
result.set(r, c, val)
return result
sparse = Sparse(2, [
(0,0,1), (0,1,2),
(1,0,3), (1,1,4),
])
print(sparse.matrix) # {0: {0: 1, 1: 2}, 1: {0: 3, 1: 4}}
# = [[1 2]
# [3 4]]
result = sparse.square_matrix()
print(result.matrix) # {0: {0: 7, 1: 10}, 1: {0: 15, 1: 22}}
# = [[ 7 10]
# [15 20]]