多分Scipyとかにあるんだろうけど、Quotanion(四元数)の演算をプログラムでできるようにPythonでクラスを定義してみた*1。
証明とか手で計算していると間違いまくるので、簡単な式変換ならプログラムにやってもらおうという。。
演算子のオーバーロード(?)等を活用すると、q1.mul(q2)とせずとも、q1 * q2 とクールに書けるんだろうけど、そのあたり不勉強なので、愚直にメソッドを呼んで計算させる。
注意:強烈なバグが残っている
#!/usr/bin/python3 # # class Quotanion: def __init__(this,a,b,c,d): this.term = { "1" : a , "i" : b , "j" : c , "k" : d } this.keys = ("1", "i", "j", "k") def mul(this,arg): exp = [] term = { "1" : "", "i" : "" , "j" : "" , "k" : "" } for key1 in this.keys: for key2 in arg.keys: new_term = this.term[key1] + arg.term[key2] imagNumber = key1 + key2 if imagNumber == "11": imagNumber = None elif imagNumber == "1i" or imagNumber == "i1" : imagNumber = "i" elif imagNumber == "1j" or imagNumber == "j1" : imagNumber = "j" elif imagNumber == "1k" or imagNumber == "k1" : imagNumber = "k" elif imagNumber == "ij": imagNumber = "k" elif imagNumber == "ji": imagNumber = "-k" elif imagNumber == "jk": imagNumber = "i" elif imagNumber == "kj": imagNumber = "-i" elif imagNumber == "ki": imagNumber = "j" elif imagNumber == "ik": imagNumber = "-j" if not imagNumber: term["1"] += new_term elif "i" in imagNumber: if "-" in imagNumber: term["i"] += "-" + new_term else: term["i"] += "+" + new_term elif "j" in imagNumber: if "-" in imagNumber: term["j"] += "-" + new_term else: term["j"] += "+" + new_term elif "k" in imagNumber: if "-" in imagNumber: term["k"] += "-" + new_term else: term["k"] += "+" + new_term q = Quotanion(term["1"], term["i"], term["j"], term["k"]) return(q) def print(this): for key in this.keys[:-1]: if key == "1": print(f"{this.term[key]} + ",end="") else: print(f"({this.term[key]}){key} + ",end="") key = this.keys[-1] print(f"({this.term[key]}){key}") q1 = Quotanion('a','b','c','d') q1.print() q2 = Quotanion('x','y','z','w') q2.print() q3 = q1.mul(q2) q3.print() # $ python3 qota.py # a + (b)i + (c)j + (d)k # x + (y)i + (z)j + (w)k # ax + (+ay+bx+by+cw-dz)i + (+az-bw+cx+cz+dy)j + (+aw+bz-cy+dx+dw)k
内積はおかしいが、少し改良版。虚数同士の計算はできるが、係数が(a+b)iといった式だとまとに動かない。表面的な実装だとこれぐらいが限界で、式を解釈できるように構文解析が必要だ。lispのS式だったら構文解析なんて面倒な処理いらんけど、pythonベースだからしょうがない。
#!/usr/bin/python3 # # # flag for debug print DBG = False class Quotanion: def __init__(this,a,b,c,d): this.term = { "1" : a , "i" : b , "j" : c , "k" : d } this.type = "Quotanion" def set_type(this,type): this.type = type def size(this): exp = "sqrt(" for key in this.term.keys()[:-1]: exp += f"{this.term[key]} + " key = this.term.keys()[-1] exp += f"{this.term[key]}" exp += ")" return(exp) def conjugate(this): term = { "1" : "", "i" : "" , "j" : "" , "k" : "" } term["1"] = this.term["1"] for key in ("i","j","k"): if "-" in this.term[key]: term[key] = this.term[key].replace("-","") else: term[key] = "-" + this.term[key] q = Quotanion(term["1"], term["i"], term["j"], term["k"]) return(q) def iprod(this,arg): term = { "1" : "", "i" : "" , "j" : "" , "k" : "" } term["1"] = this.term["1"] + arg.term["1"] term["i"] = this.term["i"] + arg.term["i"] term["j"] = this.term["j"] + arg.term["j"] term["k"] = this.term["k"] + arg.term["k"] q = Quotanion(term["1"], term["i"], term["j"], term["k"]) q.set_type("innerProduct") return(q) def add(this,arg): exp = [] term = { "1" : "", "i" : "" , "j" : "" , "k" : "" } for key in term.keys(): new_term = this.term[key] if "-" in arg.term[key]: new_term += arg.term[key] else: new_term += "+" + arg.term[key] term[key] = new_term q = Quotanion(term["1"], term["i"], term["j"], term["k"]) return(q) def mul(this,arg): exp = [] term = { "1" : "", "i" : "" , "j" : "" , "k" : "" } for key1 in this.term.keys(): for key2 in arg.term.keys(): if DBG: print(f"{this.term[key1]}{key1} * {arg.term[key2]}{key2} -> ",end="") negaFlag = False if "-" in this.term[key1]: negaFlag = not negaFlag new_term = this.term[key1].replace("-","") else: new_term = this.term[key1] if "-" in arg.term[key2]: negaFlag = not negaFlag new_term += arg.term[key2].replace("-","") else: new_term += arg.term[key2] image_number = key1 + key2 if image_number == "11": image_number = None elif image_number == "1i" or image_number == "i1" : image_number = "i" elif image_number == "1j" or image_number == "j1" : image_number = "j" elif image_number == "1k" or image_number == "k1" : image_number = "k" elif image_number == "ij": image_number = "k" elif image_number == "ji": negaFlag = not negaFlag image_number = "k" elif image_number == "jk": image_number = "i" elif image_number == "kj": negaFlag = not negaFlag image_number = "i" elif image_number == "ki": image_number = "j" elif image_number == "ik": negaFlag = not negaFlag image_number = "j" elif image_number == "ii" or image_number == "jj" or image_number == "kk": image_number = None negaFlag = not negaFlag if DBG: if negaFlag: print(f"-{new_term}{image_number}") else: print(f"{new_term}{image_number}") if not image_number: if negaFlag: term["1"] += "-" + new_term else: term["1"] += "+" + new_term elif image_number == "i": if negaFlag: term["i"] += "-" + new_term else: term["i"] += "+" + new_term elif image_number == "j": if negaFlag: term["j"] += "-" + new_term else: term["j"] += "+" + new_term elif image_number == "k": if negaFlag: term["k"] += "-" + new_term else: term["k"] += "+" + new_term q = Quotanion(term["1"], term["i"], term["j"], term["k"]) return(q) def print(this): keys = ("1","i","j","k") if this.type == "innerProduct": print("sqrt(",end="") for key in keys[:-1]: print(f"{this.term[key]} + ",end="") key = keys[-1] print(f"{this.term[key]}",end="") print(")") else: for key in keys[:-1]: if key == "1": print(f"{this.term[key]} + ",end="") else: print(f"({this.term[key]}){key} + ",end="") key = keys[-1] print(f"({this.term[key]}){key}") # # test # q1 = Quotanion('a','b','c','d') #q1.print() q2 = Quotanion('x','y','z','w') #q2.print() if False: print("-----add----") q1.print() q2.print() print("-------------") q3 = q1.add(q2) print("-----ans----") q3.print() if False: print("-----multi----") q1.print() q2.print() print("-------------") q3 = q1.mul(q2) print("-----ans----") q3.print() #q4 = q1.iprod(q2) #q4.print() #print(q1.size()) #print(q2.size()) if False: print("----q1----") q1.print() print("----conjugate of q1----") q1c = q1.conjugate() q1c.print() if False: q1c = q1.conjugate() print("-----multi----") q1.print() q1c.print() print("-------------") qq = q1.mul(q1c) print("-----ans----") qq.print() a = Quotanion('a','b','c','d') ac = a.conjugate() b = Quotanion('x','y','z','w') bc = b.conjugate() if False: print("--- a(~b) + (b)(~a) -------") a.mul(bc).add(b.mul(ac)).print() #+ax+by+cz+dw++xa+yb+zc+wd + (-ay+bx-cw+dz-xb+ya-zd+wc)i + (-az+bw+cx-dy-xc+yd+za-wb)j + (-aw-bz+cy+dx-xd-yc+zb+wa)k # 2ax + 2by + 2cz + 2dw