Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #72325 > unrolled thread
| Started by | Josh English <Joshua.R.English@gmail.com> |
|---|---|
| First post | 2014-05-30 20:38 -0700 |
| Last post | 2014-05-30 23:46 -0700 |
| Articles | 5 — 4 participants |
Back to article view | Back to comp.lang.python
Yet another "simple" headscratcher Josh English <Joshua.R.English@gmail.com> - 2014-05-30 20:38 -0700
Re: Yet another "simple" headscratcher Josh English <Joshua.R.English@gmail.com> - 2014-05-30 20:55 -0700
Re: Yet another "simple" headscratcher Gary Herron <gary.herron@islandtraining.com> - 2014-05-30 20:57 -0700
Re: Yet another "simple" headscratcher Ian Kelly <ian.g.kelly@gmail.com> - 2014-05-30 21:54 -0600
Re: Yet another "simple" headscratcher wxjmfauth@gmail.com - 2014-05-30 23:46 -0700
| From | Josh English <Joshua.R.English@gmail.com> |
|---|---|
| Date | 2014-05-30 20:38 -0700 |
| Subject | Yet another "simple" headscratcher |
| Message-ID | <a7dbde77-6bec-4b04-a940-5e8beb926232@googlegroups.com> |
I am trying to whip up a quick matrix class that can handle multiplication.
Should be no problem, except when it fails.
--- Begin
#!/usr/bin/env python
# _*_ coding: utf-8
from operator import mul
class Matrix(object):
"""Matrix([data])
Data should be a list of equal sized lists.
Defaults to a 2d identity matrix
"""
def __init__(self, data=None):
if data is None:
data = [[1,0], [0,1]]
self.data = []
if isinstance(data, (list, tuple)):
ncols = len(data[0])
for row in data:
if len(row) != ncols:
raise ValueError("Rows are unequal lengths")
self.data.append(row)
self.size = (len(self.data), len(self.data[0]))
def get_row(self, idx):
if (0 <= idx < self.size[0]):
return self.data[idx]
else:
raise ValueError("Bad row")
def get_col(self, idx):
if (0 <= idx < self.size[1]):
return list(d[idx] for d in self.data)
else:
raise ValueError("Bad column index")
def __mul__(self, other):
if not isinstance(other, (Matrix,int, float)):
raise ValueError("Cannot multiply by given value")
if isinstance(other, (int, float)):
res = []
for row in self.data:
res.append([d*other for d in row])
return Matrix(res)
# left with a matrix
res = zero_matrix(self.size[0], other.size[1])
for i in range(res.size[0]):
for j in range(res.size[1]):
print i, j, self.get_row(i), other.get_col(j),
temp = map(mul, self.get_row(i), other.get_col(j))
print temp,
t = sum(temp)
print t
res.data[i][j] = t
print res.data
return res
def as_string(self):
# return a list of lines that look pretty
stringed =[]
for row in self.data:
stringed.append(map(str, row))
widths = []
for col in range(self.size[1]):
column = [s[col] for s in stringed]
widths.append(max(map(len, column)))
item_format = "{:>%s}"
format_items = [item_format % w for w in widths]
format_string = " ".join(format_items)
formatted = [format_string.format(*s) for s in stringed]
return formatted
def zero_matrix(rows, cols):
row = [0] * cols
data = []
for r in range(rows):
data.append(row)
return Matrix(data)
M = Matrix(([1, 0], [0, -1]))
N = M*4
print '\n'.join(M.as_string())
print '-'
print '\n'.join(N.as_string())
print '-'
S = N * M
print '\n'.join(S.as_string())
--- END
For some reason, my output from this is:
1 0
0 -1
-
4 0
0 -4
-
0 0 [4, 0] [1, 0] [4, 0] 4
[[4, 0], [4, 0]]
0 1 [4, 0] [0, -1] [0, 0] 0
[[4, 0], [4, 0]]
1 0 [0, -4] [1, 0] [0, 0] 0
[[0, 0], [0, 0]]
1 1 [0, -4] [0, -1] [0, 4] 4
[[0, 4], [0, 4]]
0 4
0 4
>>>
The print lines prove to me that the logic is working, but for some reason, assigning the sum to a particular item in a particular row is assigning the same row values to every row.
This should be one of those really simple Python things, but for the life of me I don't see it.
The first [[4, 0], [4, 0]] is clearly wrong. In each step, this algorithm is repeating the row.
Any ideas as to why this is happening?
Python 2.7.5, Windows 7, so nothing exotic.
Josh
[toc] | [next] | [standalone]
| From | Josh English <Joshua.R.English@gmail.com> |
|---|---|
| Date | 2014-05-30 20:55 -0700 |
| Message-ID | <4bf8faee-f4ee-46d6-99f8-ad43a5a59cab@googlegroups.com> |
| In reply to | #72325 |
Mea culpa, gang. I found it. It had absolutely nothing to do with the multiplication. It was in zero_matrix. I feel like a fool. Josh
[toc] | [prev] | [next] | [standalone]
| From | Gary Herron <gary.herron@islandtraining.com> |
|---|---|
| Date | 2014-05-30 20:57 -0700 |
| Message-ID | <mailman.10503.1401508915.18130.python-list@python.org> |
| In reply to | #72325 |
On 05/30/2014 08:38 PM, Josh English wrote:
> ...
>
> def zero_matrix(rows, cols):
> row = [0] * cols
> data = []
> for r in range(rows):
> data.append(row)
>
> return Matrix(data)
There is a simple and common newbie mistake here. It looks like you
are appending several copies of a zero row to data, but in fact you are
appending multiple references to a single row. (The hint is that you
only created *one* row.)
Put the
row = [0] * cols
inside the loop so each append is using its own row rather than one
shared row being used multiple times.
Here's a small example that demonstrates problem:
>>> row = [0,0,0,0]
>>> data = []
>>> data.append(row)
>>> data.append(row)
>>> data[0][0] = 99
>>> data
[[99, 0, 0, 0], [99, 0, 0, 0]]
Gary Herron
[toc] | [prev] | [next] | [standalone]
| From | Ian Kelly <ian.g.kelly@gmail.com> |
|---|---|
| Date | 2014-05-30 21:54 -0600 |
| Message-ID | <mailman.10504.1401508949.18130.python-list@python.org> |
| In reply to | #72325 |
On Fri, May 30, 2014 at 9:38 PM, Josh English <Joshua.R.English@gmail.com> wrote: > I am trying to whip up a quick matrix class that can handle multiplication. > > Should be no problem, except when it fails. > > [SNIP] > > def zero_matrix(rows, cols): > row = [0] * cols > data = [] > for r in range(rows): > data.append(row) Each row of the matrix that you create here is the *same* list, not different lists that happen to be equal. So when you mutate one row, you mutate all of them. See: https://docs.python.org/3/faq/programming.html#how-do-i-create-a-multidimensional-list
[toc] | [prev] | [next] | [standalone]
| From | wxjmfauth@gmail.com |
|---|---|
| Date | 2014-05-30 23:46 -0700 |
| Message-ID | <9660e790-4734-4f41-a0bf-840b207c5a15@googlegroups.com> |
| In reply to | #72328 |
>>> # from my lib >>> def NewMat(nr, nc, val=0.0): ... val = float(val) ... return [[val] * nc for i in range(nr)] ... >>> import vmio6 >>> aa = NewMat(2, 3) >>> vmio6.pr(aa) ( 0.00000e+000 0.00000e+000 0.00000e+000 ) ( 0.00000e+000 0.00000e+000 0.00000e+000 ) >>> aa[0][0] = 3.1416 >>> vmio6.pr(aa) ( 3.14160e+000 0.00000e+000 0.00000e+000 ) ( 0.00000e+000 0.00000e+000 0.00000e+000 ) >>> aa[1][1] = 1.2345 >>> vmio6.pr(aa) ( 3.14160e+000 0.00000e+000 0.00000e+000 ) ( 0.00000e+000 1.23450e+000 0.00000e+000 ) >>> jmf
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web