Skip to content

Instantly share code, notes, and snippets.

@dekrain
Last active July 7, 2018 19:00
Show Gist options
  • Save dekrain/a276741c41bfca44ff3f4dc5a209b4a6 to your computer and use it in GitHub Desktop.
Save dekrain/a276741c41bfca44ff3f4dc5a209b4a6 to your computer and use it in GitHub Desktop.
Python algorithm to find roots of complex function
# Python 3
# This algorithm tries to find a complex solution to the complex function
# Example:
# find_root((lambda n: n**2 + 1), ComplexRect(-2+2j, 2-2j))
# -> [-1j, 1j]
import math
def complex2polar(n):
radius = math.sqrt(n.real**2 + n.imag**2)
angle = math.atan2(n.imag, n.real)
return (radius, angle%(2*math.pi))
class ComplexRect:
def __init__(self, c1, c2):
self.corner1 = c1
self.corner2 = c2
def __repr__(self):
return 'ComplexRect(%r, %r)' % (self.corner1, self.corner2)
class ComplexLine:
def __init__(self, org, off, d):
self.origin = org
self.offset = off
self.direction = d
def getOrgCord(self):
if self.direction == 'R':
return self.origin.real
return self.origin.imag
def getOtherCord(self):
if self.direction == 'R':
return self.origin.imag*1j
return self.origin.real
def getOrgUnit(self):
if self.direction == 'R':
return 1
return 1j
def getOtherUnit(self):
if self.direction == 'R':
return 1j
return 1
def __repr__(self):
return 'ComplexLine(%r, %f, %c)' % (self.origin, self.offset,
self.direction)
def _find_roots_line(func, line, pitch):
roots = []
for n in range(int(line.getOrgCord()), int(line.getOrgCord()+line.offset)):
num = line.getOtherCord()+n*line.getOrgUnit()
if func(num) == 0:
roots.append(num)
return roots
def _find_hue_diff(func, line):
org = func(line.origin)
off = func(line.origin + line.offset*line.getOtherUnit())
return (complex2polar(off)[1] - complex2polar(org)[1])/(2*math.pi)
# returns:
# - complex number(s) which are solutions to the function
# - rect(s) which contain possible roots to the function (if depth is 0)
# args:
# func - a function that a solution is searching for (callable taking one
# complex number and returning complex number)
# rect - a given range to search (ComplexRect interface instance)
# depth - how many iterations this algorithm will search for (positive integer)
# pitch - how big spaces bitween numbers (positive float)
def find_root(func, rect, depth=10, pitch=0.1):
if depth == 0:
return [rect]
lines = [ComplexLine(rect.corner1, rect.corner2.real-rect.corner1.real, 'R'),
ComplexLine(rect.corner1, rect.corner2.imag-rect.corner1.imag, 'I'),
ComplexLine(rect.corner2, rect.corner1.imag-rect.corner2.imag, 'I'),
ComplexLine(rect.corner2, rect.corner1.real-rect.corner2.real, 'R')]
for line in lines:
r = _find_roots_line(func, line, pitch)
if len(r) > 0:
return r
hues = [_find_hue_diff(func, line) for line in lines]
hue = round(math.fsum(hues))
if hue == 0:
return []
split = [ComplexRect(rect.corner1,
(rect.corner2.real+rect.corner1.real)/2 + rect.corner2.imag*1j),
ComplexRect((rect.corner2.real+rect.corner1.real)/2
+ rect.corner1.imag*1j, rect.corner2)]
return (find_root(func, split[0], depth-1, pitch)
+ find_root(func, split[1], depth-1, pitch))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment