Fix branches.
This commit is contained in:
parent
0553d80379
commit
08c4b1f790
|
@ -1,193 +1,194 @@
|
|||
|
||||
import matplotlib.pyplot as plt
|
||||
import collections
|
||||
from enum import Enum, auto
|
||||
from random import randint
|
||||
|
||||
Point = collections.namedtuple("Point", "x y")
|
||||
|
||||
class Side(Enum):
|
||||
ON = auto()
|
||||
ABOVE = auto()
|
||||
BELOW = auto()
|
||||
|
||||
|
||||
def sidedness(slope, intersection, p3, eps=0.0000001):
|
||||
print(slope * p3[0] + intersection )
|
||||
""" finds where a point is in regards to a line """
|
||||
if p3[1] - eps <= slope * p3[0] + intersection <= p3[1] + eps or p3[0] - eps <= (p3[1] - intersection)/slope <= p3[0] + eps:
|
||||
return Side.ON
|
||||
elif p3[1] > slope * p3[0] + intersection:
|
||||
return Side.ABOVE
|
||||
return Side.BELOW
|
||||
|
||||
def diplay_prune_points(points, p1, p2):
|
||||
xs = [p[0] for p in points]
|
||||
ys = [p[1] for p in points]
|
||||
|
||||
plt.plot(xs, ys, 'ro')
|
||||
plt.plot([p1[0], p2[0]], [p1[1], p2[1]])
|
||||
plt.show()
|
||||
|
||||
|
||||
def solve1D(points, xm, iteration_num):
|
||||
#print("iter:", iteration_num)
|
||||
point = points[iteration_num]
|
||||
|
||||
if iteration_num == 0:
|
||||
return -float('Inf'), -float('Inf')
|
||||
|
||||
# lad point[1] = point[0] * a + b <=> y = x * a + b
|
||||
# isolere b og sæt ind i constraints
|
||||
a = None
|
||||
b = point[1] - point[0] # * a
|
||||
|
||||
# minimere xm*a + b, hvor b har ny værdi
|
||||
# Vi regner kun med koefficienterne
|
||||
# obj_fun = (xm - point[0]) + points[1] = (xm*a - xi*a) + y
|
||||
|
||||
# max eller min
|
||||
#print("XM og point[0]:", xm, point[0])
|
||||
a = xm - point[0]
|
||||
#print("a lige her:", a)
|
||||
|
||||
a_constraint_list = []
|
||||
# looping over the i constraints
|
||||
for p in points[:iteration_num]:
|
||||
# we can't make a straigt vertical line
|
||||
if p[0] == point[0]:
|
||||
if p[1] > point[1]:
|
||||
p[0] = p[0] + 0.0001
|
||||
else:
|
||||
point[0] = point[0] + 0.0001
|
||||
|
||||
print(p, point)
|
||||
# Spring over den i'te constraint
|
||||
if p != point:
|
||||
# y_j - yi
|
||||
c = p[1] - point[1]
|
||||
# x_j * a - xi * a
|
||||
a_diff = p[0] - point[0]
|
||||
|
||||
print(c, a_diff, c/a_diff)
|
||||
# det her er forkert og skal fikses
|
||||
if a >= 0 and a_diff < 0:
|
||||
a_constraint_list.append(-float('Inf'))
|
||||
else:
|
||||
a_constraint_list.append(c/a_diff)
|
||||
|
||||
# hvis a > 0 så min
|
||||
# hvis a < 0 så max.
|
||||
if a >= 0:
|
||||
v1 = max(a_constraint_list)
|
||||
v2 = point[1] - point[0] * v1
|
||||
v = (v1, v2)
|
||||
elif a < 0:
|
||||
v1 = min(a_constraint_list)
|
||||
v2 = point[1] - point[0] * v1
|
||||
v = (v1, v2)
|
||||
|
||||
return v
|
||||
|
||||
|
||||
|
||||
def findBridge(points, xm):
|
||||
if xm > 0:
|
||||
v = (-float('Inf'), -float('Inf'))
|
||||
elif xm < 0:
|
||||
4 # noget
|
||||
else:
|
||||
# TODO: xm == 0
|
||||
4
|
||||
# looping over constraints
|
||||
for point in points:
|
||||
# checking for violation
|
||||
if not point[1] <= point[0] * v[0] + v[1]:
|
||||
v = solve1D(points, xm, points.index(point))
|
||||
#print("HER OVER: ", v)
|
||||
|
||||
slope = v[0]
|
||||
intercept = v[1]
|
||||
|
||||
line_points = [p for p in points if sidedness(slope, intercept, p) == Side.ON]
|
||||
|
||||
if len(line_points) > 3:
|
||||
print("Halli HAllo")
|
||||
print(line_points)
|
||||
|
||||
return line_points[0], line_points[1]
|
||||
|
||||
|
||||
def find_median(points):
|
||||
if len(points) % 2 == 0:
|
||||
first_med_idx = int(len(points) / 2 - 1)
|
||||
second_med_idx = int(len(points) / 2)
|
||||
return (points[first_med_idx][0] + points[second_med_idx][0]) / 2
|
||||
else:
|
||||
idx = int((len(points)-1) / 2)
|
||||
return points[idx][0]
|
||||
|
||||
|
||||
def upperHull(points, all_points):
|
||||
print("Punkter:", points)
|
||||
if len(points) < 2:
|
||||
return []
|
||||
xm = find_median(points)
|
||||
|
||||
# end-points of bridge
|
||||
(xi, yi), (xj, yj) = findBridge(points, xm)
|
||||
|
||||
#print(xm)
|
||||
print((xi, yi), (xj, yj))
|
||||
prune_points = [p for p in points if p[0] < xi or xj < p[0]] + [(xi, yi), (xj, yj)]
|
||||
|
||||
# Neden for er mest for visualisering
|
||||
prune_all_points = [p for p in all_points if p[0] < xi or xj < p[0]] + [(xi, yi), (xj, yj)]
|
||||
diplay_prune_points(prune_all_points, (xi, yi), (xj, yj))
|
||||
|
||||
Pl = [p for p in prune_points if p[0] < xm]
|
||||
Pr = [p for p in prune_points if p[0] >= xm]
|
||||
#print("Pl:", Pl, "Pr", Pr)
|
||||
|
||||
print("\n")
|
||||
# recurse results and return
|
||||
ret = [(xi, yi), (xj, yj)]
|
||||
ret = ret + [p for p in upperHull(Pl, prune_all_points) if p not in ret]
|
||||
ret = ret + [p for p in upperHull(Pr, prune_all_points) if p not in ret]
|
||||
return ret
|
||||
|
||||
|
||||
|
||||
p1 = (2, 1)
|
||||
p2 = (3, 4)
|
||||
p3 = (5, 2)
|
||||
p4 = (6, 5)
|
||||
|
||||
list_of_points = []
|
||||
|
||||
list_of_points.append(p1)
|
||||
list_of_points.append(p2)
|
||||
list_of_points.append(p3)
|
||||
list_of_points.append(p4)
|
||||
|
||||
|
||||
|
||||
|
||||
xs = [p[0] for p in list_of_points]
|
||||
ys = [p[1] for p in list_of_points]
|
||||
|
||||
plt.plot(xs, ys, 'ro')
|
||||
plt.show()
|
||||
|
||||
result = list(sorted(upperHull(list_of_points, list_of_points)))
|
||||
|
||||
result
|
||||
res_xs = [p[0] for p in result]
|
||||
res_ys = [p[1] for p in result]
|
||||
|
||||
|
||||
#print("result", result)
|
||||
plt.plot(res_xs, res_ys)
|
||||
plt.plot(xs, ys, 'ro')
|
||||
plt.show()
|
||||
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import collections
|
||||
from enum import Enum, auto
|
||||
from random import randint
|
||||
|
||||
Point = collections.namedtuple("Point", "x y")
|
||||
|
||||
class Side(Enum):
|
||||
ON = auto()
|
||||
ABOVE = auto()
|
||||
BELOW = auto()
|
||||
|
||||
|
||||
def sidedness(slope, intersection, p3, eps=0.0000001):
|
||||
print(slope * p3[0] + intersection )
|
||||
""" finds where a point is in regards to a line """
|
||||
if p3[1] - eps <= slope * p3[0] + intersection <= p3[1] + eps or p3[0] - eps <= (p3[1] - intersection)/slope <= p3[0] + eps:
|
||||
return Side.ON
|
||||
elif p3[1] > slope * p3[0] + intersection:
|
||||
return Side.ABOVE
|
||||
return Side.BELOW
|
||||
|
||||
def diplay_prune_points(points, p1, p2):
|
||||
xs = [p[0] for p in points]
|
||||
ys = [p[1] for p in points]
|
||||
|
||||
plt.plot(xs, ys, 'ro')
|
||||
plt.plot([p1[0], p2[0]], [p1[1], p2[1]])
|
||||
plt.show()
|
||||
|
||||
|
||||
def solve1D(points, xm, iteration_num):
|
||||
#print("iter:", iteration_num)
|
||||
point = points[iteration_num]
|
||||
|
||||
if iteration_num == 0:
|
||||
return -float('Inf'), -float('Inf')
|
||||
|
||||
# lad point[1] = point[0] * a + b <=> y = x * a + b
|
||||
# isolere b og sæt ind i constraints
|
||||
a = None
|
||||
b = point[1] - point[0] # * a
|
||||
|
||||
# minimere xm*a + b, hvor b har ny værdi
|
||||
# Vi regner kun med koefficienterne
|
||||
# obj_fun = (xm - point[0]) + points[1] = (xm*a - xi*a) + y
|
||||
|
||||
# max eller min
|
||||
#print("XM og point[0]:", xm, point[0])
|
||||
a = xm - point[0]
|
||||
#print("a lige her:", a)
|
||||
|
||||
a_constraint_list = []
|
||||
# looping over the i constraints
|
||||
for p in points[:iteration_num]:
|
||||
# we can't make a straigt vertical line
|
||||
if p[0] == point[0]:
|
||||
if p[1] > point[1]:
|
||||
p[0] = p[0] + 0.0001
|
||||
else:
|
||||
point[0] = point[0] + 0.0001
|
||||
|
||||
print(p, point)
|
||||
# Spring over den i'te constraint
|
||||
if p != point:
|
||||
# y_j - yi
|
||||
c = p[1] - point[1]
|
||||
# x_j * a - xi * a
|
||||
a_diff = p[0] - point[0]
|
||||
|
||||
print(c, a_diff, c/a_diff)
|
||||
# det her er forkert og skal fikses
|
||||
if a >= 0 and a_diff < 0:
|
||||
a_constraint_list.append(-float('Inf'))
|
||||
else:
|
||||
a_constraint_list.append(c/a_diff)
|
||||
|
||||
# hvis a > 0 så min
|
||||
# hvis a < 0 så max.
|
||||
if a >= 0:
|
||||
v1 = max(a_constraint_list)
|
||||
v2 = point[1] - point[0] * v1
|
||||
v = (v1, v2)
|
||||
elif a < 0:
|
||||
v1 = min(a_constraint_list)
|
||||
v2 = point[1] - point[0] * v1
|
||||
v = (v1, v2)
|
||||
|
||||
return v
|
||||
|
||||
|
||||
|
||||
def findBridge(points, xm):
|
||||
if xm > 0:
|
||||
v = (-float('Inf'), -float('Inf'))
|
||||
elif xm < 0:
|
||||
4 # noget
|
||||
else:
|
||||
# TODO: xm == 0
|
||||
4
|
||||
# looping over constraints
|
||||
for point in points:
|
||||
# checking for violation
|
||||
if not point[1] <= point[0] * v[0] + v[1]:
|
||||
v = solve1D(points, xm, points.index(point))
|
||||
#print("HER OVER: ", v)
|
||||
|
||||
slope = v[0]
|
||||
intercept = v[1]
|
||||
|
||||
line_points = [p for p in points if sidedness(slope, intercept, p) == Side.ON]
|
||||
|
||||
if len(line_points) > 3:
|
||||
print("Halli HAllo")
|
||||
print(line_points)
|
||||
|
||||
return line_points[0], line_points[1]
|
||||
|
||||
|
||||
def find_median(points):
|
||||
if len(points) % 2 == 0:
|
||||
first_med_idx = int(len(points) / 2 - 1)
|
||||
second_med_idx = int(len(points) / 2)
|
||||
return (points[first_med_idx][0] + points[second_med_idx][0]) / 2
|
||||
else:
|
||||
idx = int((len(points)-1) / 2)
|
||||
return points[idx][0]
|
||||
|
||||
|
||||
def upperHull(points, all_points):
|
||||
print("Punkter:", points)
|
||||
if len(points) < 2:
|
||||
return []
|
||||
xm = find_median(points)
|
||||
|
||||
# end-points of bridge
|
||||
(xi, yi), (xj, yj) = findBridge(points, xm)
|
||||
|
||||
#print(xm)
|
||||
print((xi, yi), (xj, yj))
|
||||
prune_points = [p for p in points if p[0] < xi or xj < p[0]] + [(xi, yi), (xj, yj)]
|
||||
|
||||
# Neden for er mest for visualisering
|
||||
prune_all_points = [p for p in all_points if p[0] < xi or xj < p[0]] + [(xi, yi), (xj, yj)]
|
||||
diplay_prune_points(prune_all_points, (xi, yi), (xj, yj))
|
||||
|
||||
Pl = [p for p in prune_points if p[0] < xm]
|
||||
Pr = [p for p in prune_points if p[0] >= xm]
|
||||
#print("Pl:", Pl, "Pr", Pr)
|
||||
|
||||
print("\n")
|
||||
# recurse results and return
|
||||
ret = [(xi, yi), (xj, yj)]
|
||||
ret = ret + [p for p in upperHull(Pl, prune_all_points) if p not in ret]
|
||||
ret = ret + [p for p in upperHull(Pr, prune_all_points) if p not in ret]
|
||||
return ret
|
||||
|
||||
|
||||
|
||||
p1 = (2, 1)
|
||||
p2 = (3, 4)
|
||||
p3 = (5, 2)
|
||||
p4 = (6, 5)
|
||||
|
||||
list_of_points = []
|
||||
|
||||
list_of_points.append(p1)
|
||||
list_of_points.append(p2)
|
||||
list_of_points.append(p3)
|
||||
list_of_points.append(p4)
|
||||
|
||||
|
||||
|
||||
|
||||
xs = [p[0] for p in list_of_points]
|
||||
ys = [p[1] for p in list_of_points]
|
||||
|
||||
plt.plot(xs, ys, 'ro')
|
||||
plt.show()
|
||||
|
||||
result = list(sorted(upperHull(list_of_points, list_of_points)))
|
||||
|
||||
result
|
||||
res_xs = [p[0] for p in result]
|
||||
res_ys = [p[1] for p in result]
|
||||
|
||||
|
||||
#print("result", result)
|
||||
plt.plot(res_xs, res_ys)
|
||||
plt.plot(xs, ys, 'ro')
|
||||
plt.show()
|
||||
|
||||
|
||||
|
|
110
h2/mbc.py
110
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