Seite 1 von 1

Code funktioniert nicht

Verfasst: Dienstag 7. Juni 2016, 09:12
von Brando
In folgendem Code wandle ich eine smypy Matrix in eine numpy Matrix um, und will dann die Methode np.linalg.det darauf loslassen.

Code: Alles auswählen

from sympy.matrices import *
from sympy.printing import *
from IPython.display import display, HTML, Math, Latex, clear_output
from ipywidgets import widgets
from random import randint
import numpy as np
from builtins import str
 
text1 = widgets.Text()
 
button1 = widgets.Button(description="Auswerten")
button2 = widgets.Button(description="Neue Aufgabe")
 
#x = np.arange(9).reshape(3,3)
#y = np.arange(3).reshape(3,1)
x=Matrix()
y=Matrix()
latexWidget = widgets.Latex()
 
taskWidget = widgets.HTML()
taskWidget.value = "<b>Berechnen Sie:</b>"
 
mhbox1 = widgets.HBox((taskWidget, latexWidget))
mhbox2 = widgets.HBox((button1, button2))
 
def init_vectors(b):
        global x, y, text1
        x=zeros(3,3)
        y=zeros(3,1)
        for i in range(3):
            for j in range(3):
             x[j,i]=randint(-10,10)

        for i in range(1):
            for j in range(3):
               y[j,i]=randint(-10,10)
        
        #n_matrix_x=np.eye(3)
        n_matrix_x=np.matrix(x)
        
        gefunden=False
        if np.linalg.det(n_matrix_x)==0:
            init_vectors(b)
        else: 
            A,B=np.linalg.eig(n_matrix_x)
            for i in range(3):
               if A[i].real==0 or A[i].imag!=0:
                 gefunden=True
                 break
            if gefunden:
                 init_vectors(b)
            
                 
        text1.value = ""
        display_task()
 
def display_task():
        global x, y, latexWidget
 
        clear_output()
 
        a1 = latex(x)
        a2 = latex(y)
 
        a1 = a1.replace("left[", "left(")
        a2 = a2.replace("left[", "left(")
        a1 = a1.replace("right]", "right)")
        a2 = a2.replace("right]", "right)")
 
        str1 = "$\langle" + a1 + ", " + a2 + "\\rangle$"
        latexWidget.value = str1
 
def evaluate(b):
        global x, y, text1
        n_matrix_x=np.array(x)
        n_matrix_y=np.array(y)
        z = np.linalg.solve(n_matrix_x,n_matrix_y)
        w=widgets.Textarea(Description='Lösung GLS',
                 value=str(z)
                 )
        display(w)
 
        clear_output()
        display_task()
 
        if "{0}".format(z) == text1.value:
                display(HTML("<b><font color='green'>Richtig</font></b>"))
        else:
                display(HTML("<b><font color='red'>Falsch</font></b>"))
 
 
def exec_la_scalar_1():
        init_vectors(button2)
        button2.on_click(init_vectors)
        button1.on_click(evaluate)
        display(widgets.VBox((mhbox1, text1, mhbox2)))
Allerdings erhalte ich für diese Methode die Fehlermeldung: No loop matching the specified signature and casting
was found for ufunc det

Warum funktioniert det nicht?

Re: Code funktioniert nicht

Verfasst: Dienstag 7. Juni 2016, 09:23
von BlackJack
@Brando: *Wo* genau tritt das auf? Wie sieht der komplette Traceback aus? Und kannst Du das auf das nötigste zusammenschrumpfen so dass man möglichst wenige Abhängigkeiten benötigt? Ich vermute zum Beispiel mal das IPython und HTML-Zeugs nichts mit dem Problem zu tun haben. Nicht jeder verwendet IPython-Notebooks um seine Programme laufen zu lassen. Ich wette einige Leser wüssten nicht mal wie sie den Quelltext zum laufen bekommen.

Re: Code funktioniert nicht

Verfasst: Dienstag 7. Juni 2016, 09:28
von Brando
Der Fehler tritt in Zeile 42 auf, also dort, wo die Determinante zu einer Matrix berechnet wird.

Re: Code funktioniert nicht

Verfasst: Dienstag 7. Juni 2016, 09:56
von Sirius3
@Brando: Du mußt die Matrix erst in Zahlen umwandeln, sonst arbeitet numpy mit einem Array von Python-Objekten, was nicht wirklich sinnvoll ist:

Code: Alles auswählen

numpy_matrix = numpy.array(sympy_matrix).astype(float)
Zum Code:
1. vergiss, dass es global gibt, Werte betreten eine Funktion über ihre Argumente und verlassen sie über ihren Rückgabewert.
2. vergiss, dass es import * gibt. Bei Deinem Code weiß man nicht, woher die einzelnen Namen stammen, vor allem weil viele Namen in numpy und sympy gleich sind, aber total verschieden funktionieren. Dass das keine gute Idee ist, sieht man auch schon daran, dass Du "str" aus builtins rückimportieren mußt, weil str von sympy.printing.str überschrieben wird.
Eingerückt wird immer mit 4 Leerzeichen pro Ebene! Und nicht nur, wenn man Code von woanders kopiert.

Warum verwendest Du überhaupt sympy in init_vectors, wenn Du doch sowieso nur Zahlen verwendest?
Wenn man for-Schleifen über numpy-Arrays schreibt, macht man ziemlich oft etwas falsch, weil es auch einen direkten weg gibt, in Zeile 46ff z.B. any

Re: Code funktioniert nicht

Verfasst: Dienstag 7. Juni 2016, 10:01
von Brando
Danke, funktioniert!

Re: Code funktioniert nicht

Verfasst: Dienstag 7. Juni 2016, 10:02
von BlackJack
@Brando: Und der Traceback? Lass Dir doch nicht alles aus der Nase ziehen. Ein lauffähiges Beispiel und die komplette Fehlerinformation sind üblicherweise sehr hilfreich beim helfen.

Ich kann das nicht laufen lassen weil ich nicht weiss wie. Ich habe Jupyter-Notebooks bisher nur interaktiv benutzt. Wober mir nicht mal klar ist ob das nun ein Jupyter Notebook ist, oder ob es damit irgendwie laufen soll, oder vielleicht etwas anderes als Umgebung braucht (SageMath?).

Ich habe jetzt einfach mal folgendes ausprobiert:

Code: Alles auswählen

In [28]: import numpy as np

In [29]: x=zeros(3,3)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-29-95ddc33a3de8> in <module>()
----> 1 x=zeros(3,3)

NameError: name 'zeros' is not defined

In [30]: x=sympy.zeros(3,3)

In [31]: np.matrix(x)
Out[31]: 
matrix([[0, 0, 0],
        [0, 0, 0],
        [0, 0, 0]], dtype=object)

In [32]: n_matrix_x=np.matrix(x)

In [33]: np.linalg.det(n_matrix_x)
Out[33]: 0.0

In [34]: %cpaste
Pasting code; enter '--' alone on the line to stop or use Ctrl-D.
:for i in range(3):
:            for j in range(3):
:             x[j,i]=randint(-10,10)
:--
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-34-eac1b6a37323> in <module>()
      1 for i in range(3):
      2             for j in range(3):
----> 3              x[j,i]=randint(-10,10)

NameError: name 'randint' is not defined

In [35]: from random import randint

In [36]: %cpaste
Pasting code; enter '--' alone on the line to stop or use Ctrl-D.
:from random import randint
:for i in range(3):
:            for j in range(3):
:             x[j,i]=randint(-10,10)
:--

In [37]: n_matrix_x=np.matrix(x)

In [38]: n_matrix_x
Out[38]: 
matrix([[9, 5, 4],
        [-10, -9, 4],
        [4, -3, 0]], dtype=object)

In [39]: np.linalg.det(n_matrix_x)
Out[39]: 452.00000000000017
So liess sich Dein Problem also nicht nachvollziehen. Und mein Spieltrieb ist damit erschöpft. Zeig doch mal ein einfaches Skript ohne ”GUI” oder ”exotische” Umgebungen das jeder der `sympy` und `numpy` installiert hat, ganz einfach laufen lassen kann, und wo man das Problem nachvollziehen kann. Denn theoretisch, im Kopf ein Programm nachzuvollziehen, das globale Variablen und Rekursion verwendet, und eine Umgebung die sicher nicht alle kennen, ist nicht wirklich einfach.

Re: Code funktioniert nicht

Verfasst: Dienstag 7. Juni 2016, 10:06
von Sirius3
@Brando: bezweifle, dass Du alle Anmerkungen in 5 Minuten umsetzen konntest. Funktionierender Code ist getestet, einfach, leicht zu verstehen, modular, erweiterbar, hält sich an alle Konventionen und funktioniert auch noch, wenn nächste Woche Du oder jemand anderes draufschaut.