Advertisement
Guest User

derivatives

a guest
Jan 6th, 2024
58
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 17.10 KB | None | 0 0
  1. import collections
  2. import math
  3. import re
  4.  
  5. class Tree:
  6. class Position:
  7. def element(self):
  8. raise NotImplementedError('must be implemented by subclass')
  9.  
  10. def __eq__(self, other):
  11. raise NotImplementedError('must be implemented by subclass')
  12.  
  13. def __ne__(self, other):
  14. return not (self == other)
  15.  
  16. def root(self):
  17. raise NotImplementedError('must be implemented by subclass')
  18.  
  19. def parent(self, p):
  20. raise NotImplementedError('must be implemented by subclass')
  21.  
  22. def num_children(self, p):
  23. raise NotImplementedError('must be implemented by subclass')
  24.  
  25. def children(self, p):
  26. raise NotImplementedError('must be implemented by subclass')
  27.  
  28. def __len__(self):
  29. raise NotImplementedError('must be implemented by subclass')
  30.  
  31. def is_root(self, p):
  32. return self.root() == p
  33.  
  34. def is_leaf(self, p):
  35. return self.num_children(p) == 0
  36.  
  37. def is_empty(self):
  38. return len(self) == 0
  39.  
  40. def depth(self, p):
  41. if self.is_root(p):
  42. return 0
  43. else:
  44. return 1 + self.depth(self.parent(p))
  45.  
  46. def _height1(self):
  47. return max(self.depth(p) for p in self.positions() if self.is_leaf(p))
  48.  
  49. def _height2(self, p):
  50. if self.is_leaf(p):
  51. return 0
  52. else:
  53. return 1 + max(self._height2(c) for c in self.children(p))
  54.  
  55. def height(self, p=None):
  56. if p is None:
  57. p = self.root()
  58. return self._height2(p)
  59.  
  60. def __iter__(self):
  61. for p in self.positions():
  62. yield p.element()
  63.  
  64. def positions(self):
  65. return self.preorder()
  66.  
  67. def preorder(self):
  68. if not self.is_empty():
  69. for p in self._subtree_preorder(self.root()):
  70. yield p
  71.  
  72. def _subtree_preorder(self, p):
  73. yield p
  74. for c in self.children(p):
  75. for other in self._subtree_preorder(c):
  76. yield other
  77.  
  78. def postorder(self):
  79. if not self.is_empty():
  80. for p in self._subtree_postorder(self.root()):
  81. yield p
  82.  
  83. def _subtree_postorder(self, p):
  84. for c in self.children(p):
  85. for other in self._subtree_postorder(c):
  86. yield other
  87. yield p
  88.  
  89. class BinaryTree(Tree):
  90. def left(self, p):
  91. raise NotImplementedError('must be implemented by subclass')
  92.  
  93. def right(self, p):
  94. raise NotImplementedError('must be implemented by subclass')
  95.  
  96. def sibling(self, p):
  97. parent = self.parent(p)
  98. if parent is None:
  99. return None
  100. else:
  101. if p == self.left(parent):
  102. return self.right(parent)
  103. else:
  104. return self.left(parent)
  105.  
  106. def children(self, p):
  107. if self.left(p) is not None:
  108. yield self.left(p)
  109. if self.right(p) is not None:
  110. yield self.right(p)
  111.  
  112. def inorder(self):
  113. if not self.is_empty():
  114. for p in self._subtree_inorder(self.root()):
  115. yield p
  116.  
  117. def _subtree_inorder(self, p):
  118. if self.left(p) is not None:
  119. for other in self._subtree_inorder(self.left(p)):
  120. yield other
  121. yield p
  122. if self.right(p) is not None:
  123. for other in self._subtree_inorder(self.right(p)):
  124. yield other
  125.  
  126. def positions(self):
  127. return self.inorder()
  128.  
  129. class LinkedBinaryTree(BinaryTree):
  130. class _Node:
  131. __slots__ = '_element', '_parent', '_left', '_right'
  132.  
  133. def __init__(self, element, parent=None, left=None, right=None):
  134. self._element = element
  135. self._parent = parent
  136. self._left = left
  137. self._right = right
  138.  
  139. class Position(BinaryTree.Position):
  140. def __init__(self, container, node):
  141. self._container = container
  142. self._node = node
  143.  
  144. def element(self):
  145. return self._node._element
  146.  
  147. def __eq__(self, other):
  148. return type(other) is type(self) and other._node is self._node
  149.  
  150. def _validate(self, p):
  151. if not isinstance(p, self.Position):
  152. raise TypeError('p must be proper Position type')
  153. if p._container is not self:
  154. raise ValueError('p does not belong to this container')
  155. if p._node._parent is p._node: # convention for deprecated nodes
  156. raise ValueError('p is no longer valid')
  157. return p._node
  158.  
  159. def _make_position(self, node):
  160. return self.Position(self, node) if node is not None else None
  161.  
  162. # -------------------------- konstruktor drzewa --------------------------
  163. def __init__(self):
  164. self._root = None
  165. self._size = 0
  166.  
  167. def __len__(self):
  168. return self._size
  169.  
  170. def root(self):
  171. return self._make_position(self._root)
  172.  
  173. def parent(self, p):
  174. node = self._validate(p)
  175. return self._make_position(node._parent)
  176.  
  177. def left(self, p):
  178. node = self._validate(p)
  179. return self._make_position(node._left)
  180.  
  181. def right(self, p):
  182. node = self._validate(p)
  183. return self._make_position(node._right)
  184.  
  185. def num_children(self, p):
  186. node = self._validate(p)
  187. count = 0
  188. if node._left is not None:
  189. count += 1
  190. if node._right is not None:
  191. count += 1
  192. return count
  193.  
  194. def _add_root(self, e):
  195. if self._root is not None:
  196. raise ValueError('Root exists')
  197. self._size = 1
  198. self._root = self._Node(e)
  199. return self._make_position(self._root)
  200.  
  201. def _add_left(self, p, e):
  202. node = self._validate(p)
  203. if node._left is not None:
  204. raise ValueError('Left child exists')
  205. self._size += 1
  206. node._left = self._Node(e, node)
  207. return self._make_position(node._left)
  208.  
  209. def _add_right(self, p, e):
  210. node = self._validate(p)
  211. if node._right is not None:
  212. raise ValueError('Right child exists')
  213. self._size += 1
  214. node._right = self._Node(e, node)
  215. return self._make_position(node._right)
  216. def _replace(self, p, e):
  217. node = self._validate(p)
  218. old = node._element
  219. node._element = e
  220. return old
  221.  
  222. def _delete(self, p):
  223. node = self._validate(p)
  224. if self.num_children(p) == 2:
  225. raise ValueError('Position has two children')
  226. child = node._left if node._left else node._right # might be None
  227. if child is not None:
  228. child._parent = node._parent # child's grandparent becomes parent
  229. if node is self._root:
  230. self._root = child # child becomes root
  231. else:
  232. parent = node._parent
  233. if node is parent._left:
  234. parent._left = child
  235. else:
  236. parent._right = child
  237. self._size -= 1
  238. node._parent = node # convention for deprecated node
  239. return node._element
  240.  
  241. def _attach(self, p, t1, t2):
  242. node = self._validate(p)
  243. if not self.is_leaf(p):
  244. raise ValueError('position must be leaf')
  245.  
  246. if t1 is not None:
  247. if not isinstance(t1, type(self)):
  248. t1 = self._convert_tree(t1)
  249. self._size += len(t1)
  250. if not t1.is_empty():
  251. t1._root._parent = node
  252. node._left = t1._root
  253. t1._root = None
  254. t1._size = 0
  255.  
  256. if t2 is not None:
  257. if not isinstance(t2, type(self)):
  258. t2 = self._convert_tree(t2)
  259. self._size += len(t2)
  260. if not t2.is_empty():
  261. t2._root._parent = node
  262. node._right = t2._root
  263. t2._root = None
  264. t2._size = 0
  265.  
  266.  
  267. def _convert_tree(self, other_tree):
  268. """Konwersja drzewa do bieżącego typu drzewa."""
  269. new_tree = None
  270. for p in other_tree.positions():
  271. # Przejdź przez pozycje w innym drzewie i skopiuj je do nowego drzewa
  272. if other_tree.is_root(p):
  273. new_tree = type(self)(p.element())
  274. else:
  275. parent_pos = new_tree.positions()[other_tree.depth(p)-1]
  276. parent_node = self._validate(parent_pos)
  277. if other_tree.left(other_tree.parent(p)) == p:
  278. new_tree._add_left(parent_node, p.element())
  279. else:
  280. new_tree._add_right(parent_node, p.element())
  281. return new_tree
  282.  
  283.  
  284. def _clone_node(self, other_node, tree_class):
  285. """Klonuje pojedynczy węzeł do bieżącego typu drzewa."""
  286. if other_node is None:
  287. return None
  288. return tree_class(other_node.element())
  289.  
  290.  
  291. class ExpressionTree(LinkedBinaryTree):
  292. def __init__(self, token, left=None, right=None):
  293. super().__init__()
  294. if not isinstance(token, str):
  295. raise TypeError('Token must be a string')
  296.  
  297. # Dodaj korzeń drzewa
  298. self._add_root(token)
  299.  
  300. # Jeśli left i right są podane, dołącz je jako poddrzewa
  301. if left is not None or right is not None:
  302. # Konwertuj left i right na ExpressionTree, jeśli są stringami
  303. if left is not None and not isinstance(left, ExpressionTree):
  304. left = ExpressionTree(left)
  305. if right is not None and not isinstance(right, ExpressionTree):
  306. right = ExpressionTree(right)
  307.  
  308. self._attach(self.root(), left, right)
  309.  
  310. def __str__(self):
  311. pieces = []
  312. self._parenthesize_recur(self.root(), pieces)
  313. return ''.join(pieces)
  314.  
  315. def _parenthesize_recur(self, p, result):
  316. if self.is_leaf(p):
  317. result.append(str(p.element()))
  318. else:
  319. result.append('(')
  320. self._parenthesize_recur(self.left(p), result)
  321. result.append(p.element())
  322. self._parenthesize_recur(self.right(p), result)
  323. result.append(')')
  324.  
  325. class ExtendedExpressionTree(ExpressionTree):
  326. def __init__(self, token, left=None, right=None):
  327. super().__init__(token, left, right)
  328. self._extended_operators = {'sin', 'cos', 'exp', 'ln'}
  329.  
  330. def evaluate_recur(self, p):
  331. if p.element() in self._extended_operators:
  332. if p.element() == 'sin':
  333. return math.sin(self.evaluate_recur(self.left(p)))
  334. elif p.element() == 'cos':
  335. return math.cos(self.evaluate_recur(self.left(p)))
  336. elif p.element() == 'exp':
  337. return math.exp(self.evaluate_recur(self.left(p)))
  338. elif p.element() == 'ln':
  339. return math.log(self.evaluate_recur(self.left(p)))
  340. else:
  341. return super().evaluate_recur(p)
  342.  
  343. def tokenize(raw):
  344. SYMBOLS = set('+-*/^() ')
  345. FUNCTIONS = {'sin', 'cos', 'exp', 'log'}
  346. tokens = []
  347. n = len(raw)
  348. i = 0
  349. while i < n:
  350. if raw[i] in SYMBOLS:
  351. if raw[i] != ' ':
  352. tokens.append(raw[i])
  353. i += 1
  354. else:
  355. if raw[i:i+3] in FUNCTIONS:
  356. j = raw.find('(', i)
  357. if j != -1:
  358. end = raw.find(')', j)
  359. if end != -1:
  360. tokens.append(raw[i:end+1])
  361. i = end + 1
  362. continue
  363. j = i
  364. while j < n and raw[j] not in SYMBOLS:
  365. j += 1
  366. tokens.append(raw[i:j])
  367. i = j
  368. return tokens
  369.  
  370.  
  371.  
  372. def build_expression_tree(tokens):
  373. S = []
  374. for t in tokens:
  375. if t in '+-*/':
  376. S.append(t) # Dodaj operator do stosu
  377. elif t not in '()':
  378. # Jeśli to nie operator i nie nawias, utwórz drzewo z pojedynczym węzłem
  379. S.append(ExpressionTree(t))
  380. elif t == ')':
  381. right = S.pop() # Zdejmij prawe poddrzewo
  382. op = S.pop() # Zdejmij operator
  383. left = S.pop() # Zdejmij lewe poddrzewo
  384.  
  385. # Sprawdź, czy operator jest ciągiem znaków
  386. if not isinstance(op, str):
  387. print("Stos:", S)
  388. print("Oczekiwano operatora, ale otrzymano:", op)
  389. raise TypeError("Operator must be a string")
  390.  
  391. # Utwórz nowe drzewo z lewym i prawym poddrzewem
  392. S.append(ExpressionTree(op, left, right))
  393. return S.pop()
  394.  
  395.  
  396.  
  397.  
  398.  
  399. def _derivative_recur(tree, node, var, tree_class):
  400. if tree.is_leaf(node):
  401. if node.element() == var:
  402. return tree_class('1')
  403. else:
  404. return tree_class('0')
  405.  
  406. op = node.element()
  407. left = tree.left(node) if tree.left(node) else None
  408. right = tree.right(node) if tree.right(node) else None
  409.  
  410. if op == '+':
  411. left_derivative = _derivative_recur(tree, left, var, tree_class) if left else None
  412. right_derivative = _derivative_recur(tree, right, var, tree_class) if right else None
  413. return tree_class('+', left_derivative, right_derivative)
  414.  
  415. elif op == '-':
  416. left_derivative = _derivative_recur(tree, left, var, tree_class) if left else None
  417. right_derivative = _derivative_recur(tree, right, var, tree_class) if right else None
  418. return tree_class('-', left_derivative, right_derivative)
  419.  
  420. elif op == '*':
  421. left_derivative = _derivative_recur(tree, left, var, tree_class) if left else None
  422. right_derivative = _derivative_recur(tree, right, var, tree_class) if right else None
  423. return tree_class('+',
  424. tree_class('*', left_derivative, tree._clone_node(right, tree_class)),
  425. tree_class('*', tree._clone_node(left, tree_class), right_derivative))
  426.  
  427. elif op == '/':
  428. left_derivative = _derivative_recur(tree, left, var, tree_class) if left else None
  429. right_derivative = _derivative_recur(tree, right, var, tree_class) if right else None
  430. num = tree_class('-',
  431. tree_class('*', left_derivative, tree._clone_node(right, tree_class)),
  432. tree_class('*', tree._clone_node(left, tree_class), right_derivative))
  433. den = tree_class('^', tree._clone_node(right, tree_class), '2')
  434. return tree_class('/', num, den)
  435.  
  436. elif op == '^':
  437. if right and tree.is_leaf(right) and right.element().isdigit():
  438. new_exponent = str(int(right.element()) - 1)
  439. left_derivative = _derivative_recur(tree, left, var, tree_class)
  440. return tree_class('*',
  441. tree_class('*', right, left_derivative),
  442. tree_class('^', tree._clone_node(left, tree_class), new_exponent))
  443.  
  444. elif op in {'sin', 'cos', 'exp', 'ln'} and isinstance(tree, ExtendedExpressionTree):
  445. left_derivative = _derivative_recur(tree, left, var, tree_class)
  446. if op == 'sin':
  447. return tree_class('*', tree_class('cos', tree._clone_node(left, tree_class)), left_derivative)
  448. elif op == 'cos':
  449. return tree_class('*', tree_class('-', tree_class('0'), tree_class('sin', tree._clone_node(left, tree_class))), left_derivative)
  450. elif op == 'exp':
  451. return tree_class('*', tree_class('exp', tree._clone_node(left, tree_class)), left_derivative)
  452. elif op == 'ln':
  453. return tree_class('*', tree_class('/', tree_class('1'), tree._clone_node(left, tree_class)), left_derivative)
  454.  
  455. else:
  456. return None # Dla nierozpoznanych przypadków
  457.  
  458. return None
  459.  
  460.  
  461.  
  462.  
  463. def derivative_of_tree(tree, var='x'):
  464. root = tree.root()
  465. tree_class = type(tree)
  466. derivative = _derivative_recur(tree, root, var, tree_class)
  467.  
  468. # Sprawdź, czy drzewo pochodnej nie jest puste
  469. if derivative.is_empty():
  470. return derivative
  471. else:
  472. # Tworzymy nowe drzewo z elementami, a nie z pozycjami
  473. left_element = derivative.left(derivative.root()).element() if derivative.left(derivative.root()) else None
  474. right_element = derivative.right(derivative.root()).element() if derivative.right(derivative.root()) else None
  475. return tree_class(derivative.root().element(),
  476. ExpressionTree(left_element) if left_element is not None else None,
  477. ExpressionTree(right_element) if right_element is not None else None)
  478.  
  479.  
  480. def tree_to_string(tree):
  481. def _to_string(node):
  482. if tree.is_leaf(node):
  483. return node.element()
  484. left = _to_string(tree.left(node)) if tree.left(node) else ""
  485. right = _to_string(tree.right(node)) if tree.right(node) else ""
  486. return f"({left}{node.element()}{right})" if left or right else node.element()
  487.  
  488. return _to_string(tree.root())
  489.  
  490.  
  491. expression = "((x/2)-y)"
  492. tokens = tokenize(expression)
  493. expr_tree = build_expression_tree(tokens)
  494. derivative_tree = derivative_of_tree(expr_tree)
  495. derivative_expression = tree_to_string(derivative_tree)
  496. print("Expression:", expression)
  497. print("Pochodna:", derivative_expression)
  498.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement