Fix branches.
This commit is contained in:
parent
0553d80379
commit
08c4b1f790
|
@ -191,3 +191,4 @@ plt.plot(res_xs, res_ys)
|
|||
plt.plot(xs, ys, 'ro')
|
||||
plt.show()
|
||||
|
||||
|
||||
|
|
108
h2/mbc.py
108
h2/mbc.py
|
@ -1,21 +1,109 @@
|
|||
import random
|
||||
import statistics
|
||||
from collections import namedtuple
|
||||
from typing import List, Set
|
||||
from enum import Enum, auto
|
||||
from typing import Set
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
from scipy.optimize import linprog
|
||||
|
||||
Point = namedtuple('Point', 'x y')
|
||||
|
||||
|
||||
def mbc_ch(points: Set[Point]):
|
||||
def gen_point(lower: int, upper: int) -> Point:
|
||||
a = random.uniform(lower, upper)
|
||||
b = random.uniform(lower, upper)
|
||||
|
||||
x_i = random.uniform(lower, upper)
|
||||
p_i = Point(x_i, a * x_i + b)
|
||||
p_i = Point(a, b)
|
||||
return p_i
|
||||
|
||||
|
||||
def display(points: Set[Point], hull: Set[Point]):
|
||||
x = [point.x for point in points]
|
||||
y = [point.y for point in points]
|
||||
|
||||
h_x = [point.x for point in hull]
|
||||
h_y = [point.y for point in hull]
|
||||
|
||||
plt.plot(h_x, h_y, 'ro')
|
||||
|
||||
plt.scatter(x, y)
|
||||
plt.show()
|
||||
|
||||
|
||||
def display_line_only(points: Set[Point], slope: int, intercept: int, line_points: Set[Point]):
|
||||
x = [point.x for point in points]
|
||||
y = [point.y for point in points]
|
||||
|
||||
plt.scatter(x, y)
|
||||
|
||||
# Plot a line from slope and intercept
|
||||
axes = plt.gca()
|
||||
x_vals = np.array(axes.get_xlim())
|
||||
y_vals = intercept + slope * x_vals
|
||||
|
||||
for point in line_points:
|
||||
plt.plot(point.x, point.y, 'go')
|
||||
|
||||
plt.plot(x_vals, y_vals, '--')
|
||||
|
||||
plt.show()
|
||||
|
||||
|
||||
class Side(Enum):
|
||||
ON = auto()
|
||||
ABOVE = auto()
|
||||
BELOW = auto()
|
||||
|
||||
|
||||
def sidedness(slope: int, intersection: int, p3: Point, linprog_flipper: callable, eps=0.0000001) -> Side:
|
||||
# finds where a point is in regards to a line
|
||||
if linprog_flipper(p3.y) - eps <= linprog_flipper(slope * p3.x + intersection) <= linprog_flipper(p3.y) + eps:
|
||||
return Side.ON
|
||||
elif p3.y > slope * p3.x + intersection:
|
||||
return Side.ABOVE
|
||||
return Side.BELOW
|
||||
|
||||
|
||||
def mbc_ch(points: Set[Point], linprog_flipper: callable) -> Set[Point]:
|
||||
if len(points) <= 2:
|
||||
return points
|
||||
|
||||
# Find the point with median x-coordinate, and partition the points on this point
|
||||
pm = statistics.median_high(points)
|
||||
med_x = statistics.median(p.x for p in points)
|
||||
|
||||
pl = {point
|
||||
for point in points
|
||||
if point.x < pm.x}
|
||||
|
||||
pr = {point
|
||||
for point in points
|
||||
if point.x >= pm.x}
|
||||
# Find left and right points in regards to median
|
||||
pl = {p for p in points if p.x < med_x}
|
||||
pr = {p for p in points if p.x >= med_x}
|
||||
|
||||
# Find the bridge over the vertical line in pm
|
||||
c = [linprog_flipper(med_x), linprog_flipper(1)]
|
||||
A = [[linprog_flipper(-p.x), linprog_flipper(-1)] for p in points]
|
||||
b = [linprog_flipper(-p.y) for p in points]
|
||||
|
||||
result = linprog(c, A, b, bounds=[(None, None), (None, None)], options={"tol": 0.00001})
|
||||
slope, intercept = result.x[0], result.x[1]
|
||||
|
||||
# Find the two points which are on the line, should work
|
||||
left_point = next(p for p in pl if sidedness(slope, intercept, p, linprog_flipper) == Side.ON)
|
||||
right_point = next(p for p in pr if sidedness(slope, intercept, p, linprog_flipper) == Side.ON)
|
||||
|
||||
|
||||
|
||||
|
||||
# Prune the points between the two line points
|
||||
pl = {p for p in pl if p.x <= left_point.x}
|
||||
pr = {p for p in pr if p.x >= right_point.x}
|
||||
|
||||
return set.union(mbc_ch(pl, linprog_flipper), {left_point, right_point}, mbc_ch(pr, linprog_flipper))
|
||||
|
||||
|
||||
points = {gen_point(1, 10) for _ in range(20)}
|
||||
|
||||
upper_hull_points = mbc_ch(points, lambda x: x)
|
||||
lower_hull_points = mbc_ch(points, lambda x: -x)
|
||||
|
||||
display(points, upper_hull_points.union(lower_hull_points))
|
||||
|
|
Loading…
Reference in New Issue
Block a user