Array copy m1=m2 works only on the first pass.
Array copy m1=m2 works only on the first pass.
First I am just learning python and playing with my pyboard. To understand the capabilities of the pyboard I run a 5x5 matrix inversion program a large number of times (and get a measurable delay) and at the end compare one of the result values to the known answer and light the green LED if it matches. To speed things up I loaded an array/matrix before the main loop and use a copy as the array that is manipulated into the solution. Using the m1=m2 statement worked without looping. After adding the repeat loop I kept getting the wrong answer light.
The number of passes was then set to 1 and the correct answer was indicated. Next I coded an individual item copy and replaced the m1=m2 statement and it gave the correct answer with any loop count >0.
To check, the python coding was put into Anaconda Spyder and there the array copy works as expected.
My pyboard responds with MicroPython v1.5-134-g5be60d6 on 2015-11-14 ...
Part of the coding:
itt =0
while itt<10000:
"""
m1=m2
"""
i=0
while i<col:
j=0
while j<n:
m1[j] = m2[j]
j+=1
i+=1
The number of passes was then set to 1 and the correct answer was indicated. Next I coded an individual item copy and replaced the m1=m2 statement and it gave the correct answer with any loop count >0.
To check, the python coding was put into Anaconda Spyder and there the array copy works as expected.
My pyboard responds with MicroPython v1.5-134-g5be60d6 on 2015-11-14 ...
Part of the coding:
itt =0
while itt<10000:
"""
m1=m2
"""
i=0
while i<col:
j=0
while j<n:
m1[j] = m2[j]
j+=1
i+=1
Re: Array copy m1=m2 works only on the first pass.
If you wrap your code examples with [ code] and [ /code] (but don't put the spaces after the opening square brackets) then it will preserve all of the indentation and look something like this:
In python lists are mutable. So if you do this: then you'll see that m1 and m2 are really pointing to the same underlying object. To make a copy do it this way:
Code: Select all
while True:
do something
Code: Select all
>>> m1 = [1, 2, 3, 4, 5, 6]
>>> m2 = m1
>>> m2[0] = 99
>>> m1
[99, 2, 3, 4, 5, 6]
Code: Select all
>>> m1 = [1, 2, 3, 4, 5, 6]
>>> m2 = list(m1)
>>> m2[0] = 99
>>> m1
[1, 2, 3, 4, 5, 6]
Re: Array copy m1=m2 works only on the first pass.
Same behavior with m1=list(m2).
I will try to load the entire code
I will try to load the entire code
Code: Select all
import pyb #Testing pyboard math speed.
pyb.LED(3).on()
#5x5 matrix y=A*X, X unknoown, coded A:Y:I, solved to I:X:Ainv,
#This code may be shortened to solve only for X at minimal waste
m2=[ [ 0.0 for i in range(11) ] for j in range(5) ]
m1=[ [ 0.0 for i in range(11) ] for j in range(5) ]
m2=[[2.3,5.5,7.5,8.2,7.2,3.4,1,0,0,0,0],
[4.3,2.2,2.1,6.3,9.4,6.5,0,1,0,0,0],
[0,6.6,5.8,4.2,8.1,8.8,0,0,1,0,0],
[3.6,3.6,-8.6,0,-3.4,-3.1,0,0,0,1,0],
[8.1,-4.5,2.6,6.7,5.1,5,0,0,0,0,1]]
col=11 #total collumbs n+1+n, n+1 to not solve Ainv.
n= 5 #rows
m= 4 #n-1
i=0
j=0
k=0
e=0.0
f=0.0
g=0.0
h=0.0
d=1e-4 #zero? close enough
h=-d
itt =0
while itt<1001: #Increase until desired delay
#reset to initial matrix
"""
m1=list(m2)
"""
i=0
while i<n:
j=0
while j<col:
m1[i][j] = m2[i][j]
j+=1
i+=1
#
i=0
while i < n: #for each row
e=m1[i][i] #read the diagonal element
if d>e and e>h: #deal with zero diagonal element?
j=i
if j>=n:
pyb.LED(1).on() #error no solution
while j<m:#look for a row with non-zero element
j+=1
g=m1[j][i]
if g<h or g>d:#add the rows
k=i #zeros assumed to left
while k<col:
m1[i][k]+=m1[j][k]
k+=1
j=n
e=m1[i][i]#read the new diagonal element
#scale row for 1 in diagonal
e=1/e
j=i #zeros assumed to left
while j<col:
m1[i][j]=m1[i][j]*e
j+=1
j=0
while j<n:
if j!=i:
f=-m1[j][i]#value of element to eliminate
k=i+1#k=i to actualy eliminate it and give clean I
while k<col:
m1[j][k]+=m1[i][k]*f
k+=1
j+=1
i+=1
itt+=1
pyb.LED(4).toggle()
answer = 2.192383196 #X(0)
e = m1[0][5]-answer #error difference
if d>e and e>h:#little diff.
pyb.LED(2).on()#green light on
else:
pyb.LED(1).on()#red light on
Re: Array copy m1=m2 works only on the first pass.
I ran the code you presented and the green light comes on.
What does the code look like when it fails.
What does the code look like when it fails.
Re: Array copy m1=m2 works only on the first pass.
Code: Select all
import pyb #Testing pyboard math speed.
pyb.LED(3).on()
#5x5 matrix y=A*X, X unknoown, coded A:Y:I, solved to I:X:Ainv,
#This code may be shortened to solve only for X at minimal waste
m2=[ [ 0.0 for i in range(11) ] for j in range(5) ]
m1=[ [ 0.0 for i in range(11) ] for j in range(5) ]
m2=[[2.3,5.5,7.5,8.2,7.2,3.4,1,0,0,0,0],
[4.3,2.2,2.1,6.3,9.4,6.5,0,1,0,0,0],
[0,6.6,5.8,4.2,8.1,8.8,0,0,1,0,0],
[3.6,3.6,-8.6,0,-3.4,-3.1,0,0,0,1,0],
[8.1,-4.5,2.6,6.7,5.1,5,0,0,0,0,1]]
col=11 #total collumbs n+1+n, n+1 to not solve Ainv.
n= 5 #rows
m= 4 #n-1
i=0
j=0
k=0
e=0.0
f=0.0
g=0.0
h=0.0
d=1e-4 #zero? close enough
h=-d
itt =0
while itt<1001: #Increase until desired delay
#reset to initial matrix
m1=list(m2)
"""
i=0
while i<n:
j=0
while j<col:
m1[i][j] = m2[i][j]
j+=1
i+=1
"""
i=0
while i < n: #for each row
e=m1[i][i] #read the diagonal element
if d>e and e>h: #deal with zero diagonal element?
j=i
if j>=n:
pyb.LED(1).on() #error no solution
while j<m:#look for a row with non-zero element
j+=1
g=m1[j][i]
if g<h or g>d:#add the rows
k=i #zeros assumed to left
while k<col:
m1[i][k]+=m1[j][k]
k+=1
j=n
e=m1[i][i]#read the new diagonal element
#scale row for 1 in diagonal
e=1/e
j=i #zeros assumed to left
while j<col:
m1[i][j]=m1[i][j]*e
j+=1
j=0
while j<n:
if j!=i:
f=-m1[j][i]#value of element to eliminate
k=i+1#k=i to actualy eliminate it and give clean I
while k<col:
m1[j][k]+=m1[i][k]*f
k+=1
j+=1
i+=1
itt+=1
pyb.LED(4).toggle()
answer = 2.192383196 #X(0)
e = m1[0][5]-answer #error difference
if d>e and e>h:#little diff.
pyb.LED(2).on()#green light on
else:
pyb.LED(1).on()#red light on
Re: Array copy m1=m2 works only on the first pass.
I see the problem.
m1 is actually a list with embedded lists. only makes copies of the topmost lists. If you use: then it will copy 2 levels. CPython has a copy.deepcopy() routinte that isn't currently implemented in MicroPython or you could have used that.
Making the change above, I get a green LED at the end.
m1 is actually a list with embedded lists.
Code: Select all
m1=list(m2)
Code: Select all
m1=[list(row) for row in m2]
Making the change above, I get a green LED at the end.
Re: Array copy m1=m2 works only on the first pass.
I have a lot to learn before I understand this...
Thanks for the solution.
Thanks for the solution.
Re: Array copy m1=m2 works only on the first pass.
The big thing to remember is that when you pass around list objects, you're really doing the C equivalent thing of passing around pointers.
If you had declared the original list using parenthesis then it makes an immutable list, and you would have gotten an error when you tried to modify it.
This web page has some insights into mutable versus immutable objects: http://codehabitude.com/2013/12/24/pyth ... immutable/
If you had declared the original list using parenthesis then it makes an immutable list, and you would have gotten an error when you tried to modify it.
Code: Select all
MicroPython v1.5.1-33-g9bc8568 on 2015-11-27; PYBv1.0 with STM32F405RG
Type "help()" for more information.
>>>
>>> x = (1, 2, 3)
>>> x[0] = 4
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> y = list(x)
>>> y[0] = 4
>>> x
(1, 2, 3)
>>> y
[4, 2, 3]
Re: Array copy m1=m2 works only on the first pass.
And not less big thing to remember that almost any higher-level language (from Java) does it like that - objects are passed by reference.The big thing to remember is that when you pass around list objects, you're really doing the C equivalent thing of passing around pointers.
It's of course available in micropython-lib.CPython has a copy.deepcopy() routinte that isn't currently implemented in MicroPython or you could have used that.
Awesome MicroPython list
Pycopy - A better MicroPython https://github.com/pfalcon/micropython
MicroPython standard library for all ports and forks - https://github.com/pfalcon/micropython-lib
More up to date docs - http://pycopy.readthedocs.io/
Pycopy - A better MicroPython https://github.com/pfalcon/micropython
MicroPython standard library for all ports and forks - https://github.com/pfalcon/micropython-lib
More up to date docs - http://pycopy.readthedocs.io/
Re: Array copy m1=m2 works only on the first pass.
I found a math quirk while reviewing my results. Try multiplying:
0.3117148*3.20806
This was supposed to be one in the identity matrix diagonal but showed up as 0.0
Any change in the lowest decimal gives a good answer. Strange bug.
0.3117148*3.20806
This was supposed to be one in the identity matrix diagonal but showed up as 0.0
Any change in the lowest decimal gives a good answer. Strange bug.