in_static_equilibrium checks if a 2D static system is in equilibrium (#1062)

* Add files via upload

* Add files via upload

* Create .a

* Add files via upload

* Add files via upload

* Rename static_solver.py to in_static_equilibrium.py

* Delete .a

* Update in_static_equilibrium.py

* Add files via upload

* Add files via upload

* Update in_static_equilibrium.py

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* pyTests added

* Add files via upload

* Delete red_black_tree.py

* Add files via upload
This commit is contained in:
QuantumNovice 2019-07-25 23:38:24 +05:00 committed by Christian Clauss
parent 3c8e9314b6
commit c27bd5144f
4 changed files with 800 additions and 665 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View File

@ -0,0 +1,89 @@
"""
Checks if a system of forces is in static equilibrium.
python/black : true
flake8 : passed
mypy : passed
"""
from numpy import array, cos, sin, radians, cross # type: ignore
from typing import List
def polar_force(
magnitude: float, angle: float, radian_mode: bool = False
) -> List[float]:
"""
Resolves force along rectangular components.
(force, angle) => (force_x, force_y)
>>> polar_force(10, 45)
[7.0710678118654755, 7.071067811865475]
>>> polar_force(10, 3.14, radian_mode=True)
[-9.999987317275394, 0.01592652916486828]
"""
if radian_mode:
return [magnitude * cos(angle), magnitude * sin(angle)]
return [magnitude * cos(radians(angle)), magnitude * sin(radians(angle))]
def in_static_equilibrium(
forces: array, location: array, eps: float = 10 ** -1
) -> bool:
"""
Check if a system is in equilibrium.
It takes two numpy.array objects.
forces ==> [
[force1_x, force1_y],
[force2_x, force2_y],
....]
location ==> [
[x1, y1],
[x2, y2],
....]
>>> force = array([[1, 1], [-1, 2]])
>>> location = array([[1, 0], [10, 0]])
>>> in_static_equilibrium(force, location)
False
"""
# summation of moments is zero
moments: array = cross(location, forces)
sum_moments: float = sum(moments)
return abs(sum_moments) < eps
if __name__ == "__main__":
# Test to check if it works
forces = array(
[
polar_force(718.4, 180 - 30),
polar_force(879.54, 45),
polar_force(100, -90)
])
location = array([[0, 0], [0, 0], [0, 0]])
assert in_static_equilibrium(forces, location)
# Problem 1 in image_data/2D_problems.jpg
forces = array(
[
polar_force(30 * 9.81, 15),
polar_force(215, 180 - 45),
polar_force(264, 90 - 30),
]
)
location = array([[0, 0], [0, 0], [0, 0]])
assert in_static_equilibrium(forces, location)
# Problem in image_data/2D_problems_1.jpg
forces = array([[0, -2000], [0, -1200], [0, 15600], [0, -12400]])
location = array([[0, 0], [6, 0], [10, 0], [12, 0]])
assert in_static_equilibrium(forces, location)
import doctest
doctest.testmod()

View File

@ -1,19 +1,23 @@
"""
python/black : true
flake8 : passed
"""
class RedBlackTree:
"""
A Red-Black tree, which is a self-balancing BST (binary search
tree).
This tree has similar performance to AVL trees, but the balancing is
less strict, so it will perform faster for writing/deleting nodes
and slower for reading in the average case, though, because they're
both balanced binary search trees, both will get the same asymptotic
perfomance.
To read more about them, https://en.wikipedia.org/wiki/Redblack_tree
Unless otherwise specified, all asymptotic runtimes are specified in
terms of the size of the tree.
"""
def __init__(self, label=None, color=0, parent=None, left=None, right=None):
"""Initialize a new Red-Black Tree node with the given values:
label: The value associated with this node
@ -33,7 +37,6 @@ class RedBlackTree:
def rotate_left(self):
"""Rotate the subtree rooted at this node to the left and
returns the new root to this subtree.
Perfoming one rotation can be done in O(1).
"""
parent = self.parent
@ -44,7 +47,7 @@ class RedBlackTree:
self.parent = right
right.left = self
if parent is not None:
if parent.left is self:
if parent.left == self:
parent.left = right
else:
parent.right = right
@ -54,7 +57,6 @@ class RedBlackTree:
def rotate_right(self):
"""Rotate the subtree rooted at this node to the right and
returns the new root to this subtree.
Performing one rotation can be done in O(1).
"""
parent = self.parent
@ -76,7 +78,6 @@ class RedBlackTree:
"""Inserts label into the subtree rooted at self, performs any
rotations necessary to maintain balance, and then returns the
new root to this subtree (likely self).
This is guaranteed to run in O(log(n)) time.
"""
if self.label is None:
@ -194,42 +195,56 @@ class RedBlackTree:
self.parent.rotate_left()
else:
self.parent.rotate_right()
if color(self.parent) == 0 and color(self.sibling) == 0 \
and color(self.sibling.left) == 0 \
and color(self.sibling.right) == 0:
if (
color(self.parent) == 0
and color(self.sibling) == 0
and color(self.sibling.left) == 0
and color(self.sibling.right) == 0
):
self.sibling.color = 1
self.parent._remove_repair()
return
if color(self.parent) == 1 and color(self.sibling) == 0 \
and color(self.sibling.left) == 0 \
and color(self.sibling.right) == 0:
if (
color(self.parent) == 1
and color(self.sibling) == 0
and color(self.sibling.left) == 0
and color(self.sibling.right) == 0
):
self.sibling.color = 1
self.parent.color = 0
return
if (self.is_left()
and color(self.sibling) == 0
and color(self.sibling.right) == 0
and color(self.sibling.left) == 1):
if (
self.is_left()
and color(self.sibling) == 0
and color(self.sibling.right) == 0
and color(self.sibling.left) == 1
):
self.sibling.rotate_right()
self.sibling.color = 0
self.sibling.right.color = 1
if (self.is_right()
and color(self.sibling) == 0
and color(self.sibling.right) == 1
and color(self.sibling.left) == 0):
if (
self.is_right()
and color(self.sibling) == 0
and color(self.sibling.right) == 1
and color(self.sibling.left) == 0
):
self.sibling.rotate_left()
self.sibling.color = 0
self.sibling.left.color = 1
if (self.is_left()
and color(self.sibling) == 0
and color(self.sibling.right) == 1):
if (
self.is_left()
and color(self.sibling) == 0
and color(self.sibling.right) == 1
):
self.parent.rotate_left()
self.grandparent.color = self.parent.color
self.parent.color = 0
self.parent.sibling.color = 0
if (self.is_right()
and color(self.sibling) == 0
and color(self.sibling.left) == 1):
if (
self.is_right()
and color(self.sibling) == 0
and color(self.sibling.left) == 1
):
self.parent.rotate_right()
self.grandparent.color = self.parent.color
self.parent.color = 0
@ -245,7 +260,6 @@ class RedBlackTree:
4. If a node is red, then both its children are black.
5. Every path from any node to all of its descendent NIL nodes
has the same number of black nodes.
This function runs in O(n) time, because properties 4 and 5 take
that long to check.
"""
@ -255,20 +269,20 @@ class RedBlackTree:
# Property 2
if self.color:
# The root was red
print('Property 2')
return False;
print("Property 2")
return False
# Property 3 does not need to be checked, because None is assumed
# to be black and is all the leaves.
# Property 4
if not self.check_coloring():
print('Property 4')
print("Property 4")
return False
# Property 5
if self.black_height() is None:
print('Property 5')
print("Property 5")
return False
# All properties were met
return True
@ -304,14 +318,13 @@ class RedBlackTree:
return None
# Return the black depth of children, plus one if this node is
# black
return left + (1-self.color)
return left + (1 - self.color)
# Here are functions which are general to all binary search trees
def __contains__(self, label):
"""Search through the tree for label, returning True iff it is
found somewhere in the tree.
Guaranteed to run in O(log(n)) time.
"""
return self.search(label) is not None
@ -319,7 +332,6 @@ class RedBlackTree:
def search(self, label):
"""Search through the tree for label, returning its node if
it's found, and None otherwise.
This method is guaranteed to run in O(log(n)) time.
"""
if self.label == label:
@ -337,7 +349,6 @@ class RedBlackTree:
def floor(self, label):
"""Returns the largest element in this tree which is at most label.
This method is guaranteed to run in O(log(n)) time."""
if self.label == label:
return self.label
@ -355,7 +366,6 @@ class RedBlackTree:
def ceil(self, label):
"""Returns the smallest element in this tree which is at least label.
This method is guaranteed to run in O(log(n)) time.
"""
if self.label == label:
@ -374,7 +384,6 @@ class RedBlackTree:
def get_max(self):
"""Returns the largest element in this tree.
This method is guaranteed to run in O(log(n)) time.
"""
if self.right:
@ -385,7 +394,6 @@ class RedBlackTree:
def get_min(self):
"""Returns the smallest element in this tree.
This method is guaranteed to run in O(log(n)) time.
"""
if self.left:
@ -448,7 +456,6 @@ class RedBlackTree:
if self.right:
yield from self.right.inorder_traverse()
def postorder_traverse(self):
if self.left:
yield from self.left.postorder_traverse()
@ -458,11 +465,16 @@ class RedBlackTree:
def __repr__(self):
from pprint import pformat
if self.left is None and self.right is None:
return "'%s %s'" % (self.label, (self.color and 'red') or 'blk')
return pformat({'%s %s' % (self.label, (self.color and 'red') or 'blk'):
(self.left, self.right)},
indent=1)
return "'%s %s'" % (self.label, (self.color and "red") or "blk")
return pformat(
{
"%s %s"
% (self.label, (self.color and "red") or "blk"): (self.left, self.right)
},
indent=1,
)
def __eq__(self, other):
"""Test if two trees are equal."""
@ -471,6 +483,7 @@ class RedBlackTree:
else:
return False
def color(node):
"""Returns the color of a node, allowing for None leaves."""
if node is None:
@ -478,10 +491,13 @@ def color(node):
else:
return node.color
"""
Code for testing the various functions of the red-black tree.
Code for testing the various
functions of the red-black tree.
"""
def test_rotations():
"""Test that the rotate_left and rotate_right functions work."""
# Make a tree to test on
@ -517,6 +533,7 @@ def test_rotations():
return False
return True
def test_insertion_speed():
"""Test that the tree balances inserts to O(log(n)) by doing a lot
of them.
@ -526,6 +543,7 @@ def test_insertion_speed():
tree = tree.insert(i)
return True
def test_insert():
"""Test the insert() method of the tree correctly balances, colors,
and inserts.
@ -546,6 +564,7 @@ def test_insert():
ans.right.right.right = RedBlackTree(12, 1, ans.right.right)
return tree == ans
def test_insert_and_search():
"""Tests searching through the tree for values."""
tree = RedBlackTree(0)
@ -563,6 +582,7 @@ def test_insert_and_search():
return False
return True
def test_insert_delete():
"""Test the insert() and delete() method of the tree, verifying the
insertion and removal of elements, and the balancing of the tree.
@ -586,6 +606,7 @@ def test_insert_delete():
return False
return True
def test_floor_ceil():
"""Tests the floor and ceiling functions in the tree."""
tree = RedBlackTree(0)
@ -601,6 +622,7 @@ def test_floor_ceil():
return False
return True
def test_min_max():
"""Tests the min and max functions in the tree."""
tree = RedBlackTree(0)
@ -614,10 +636,11 @@ def test_min_max():
return False
return True
def test_tree_traversal():
"""Tests the three different tree traversal functions."""
tree = RedBlackTree(0)
tree.insert(-16)
tree = tree.insert(-16)
tree.insert(16)
tree.insert(8)
tree.insert(24)
@ -631,35 +654,58 @@ def test_tree_traversal():
return False
return True
def main():
if test_rotations():
print('Rotating right and left works!')
else:
print('Rotating right and left doesn\'t work. :(')
if test_insert():
print('Inserting works!')
else:
print('Inserting doesn\'t work :(')
if test_insert_and_search():
print('Searching works!')
else:
print('Searching doesn\'t work :(')
if test_insert_delete():
print('Deleting works!')
else:
print('Deleting doesn\'t work :(')
if test_floor_ceil():
print('Floor and ceil work!')
else:
print('Floor and ceil don\'t work :(')
if test_tree_traversal():
print('Tree traversal works!')
else:
print('Tree traversal doesn\'t work :(')
print('Testing tree balancing...')
print('This should only be a few seconds.')
test_insertion_speed()
print('Done!')
if __name__ == '__main__':
def test_tree_chaining():
"""Tests the three different tree chaning functions."""
tree = RedBlackTree(0)
tree = tree.insert(-16).insert(16).insert(8).insert(24).insert(20).insert(22)
if list(tree.inorder_traverse()) != [-16, 0, 8, 16, 20, 22, 24]:
return False
if list(tree.preorder_traverse()) != [0, -16, 16, 8, 22, 20, 24]:
return False
if list(tree.postorder_traverse()) != [-16, 8, 20, 24, 22, 16, 0]:
return False
return True
def print_results(msg: str, passes: bool) -> None:
print(str(msg), "works!" if passes else "doesn't work :(")
def pytests():
assert test_rotations()
assert test_insert()
assert test_insert_and_search()
assert test_insert_delete()
assert test_floor_ceil()
assert test_tree_traversal()
assert test_tree_chaining()
def main():
"""
>>> pytests()
"""
print_results("Rotating right and left", test_rotations())
print_results("Inserting", test_insert())
print_results("Searching", test_insert_and_search())
print_results("Deleting", test_insert_delete())
print_results("Floor and ceil", test_floor_ceil())
print_results("Tree traversal", test_tree_traversal())
print_results("Tree traversal", test_tree_chaining())
print("Testing tree balancing...")
print("This should only be a few seconds.")
test_insertion_speed()
print("Done!")
if __name__ == "__main__":
main()