Created
December 10, 2017 21:19
-
-
Save seovchinnikov/3dffbd86a8c1d3c6d8e2096250ba7448 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import cv2 | |
import pickle | |
import math | |
import random | |
import copy | |
PKL = 'points.pkl' | |
IMG_NAME = 'graphen.png' | |
LINKS = ((0, 1, 2, 3, 4, 5, 6), (1, 7, 8, 9, 10, 2), (8, 11, 12, 13, 14, 9), (12, 15, 16, 17, 18, 19, 13), | |
(3, 2, 10, 25, 21, 20), (10, 9, 14, 32, 29, 26, 25), (14, 13, 19, 36, 33, 32), (24, 20, 21, 22, 23), | |
(21, 25, 26, 27, 28, 22), (26, 29, 30, 31, 27), (29, 32, 33, 34, 35, 30), (33, 36, 37, 38, 34), | |
(42, 23, 22, 28, 39, 40, 41, 42), (28, 27, 31, 43, 44, 39), (31, 30, 35, 45, 46, 43), | |
(35, 34, 38, 47, 48, 49, 45),) | |
class Point: | |
x = -1 | |
y = -1 | |
id = -1 | |
plus = 0 | |
links = None | |
def __init__(self, id, x=-1, y=-1, links = [], plus=0): | |
self.x = x | |
self.y = y | |
self.id = id | |
self.links = [] | |
self.links.extend(links) | |
self.plus = plus | |
class Config: | |
points = None | |
signs = None | |
betta=1 | |
def __init__(self, points, betta=1., signs=None): | |
self.points = points | |
if signs is None: | |
signs = {} | |
for point in points: | |
signs[point.id] = random.choice([1, -1]) | |
self.signs = signs | |
self.betta = betta | |
def clone(self): | |
conf_new = Config(self.points, self.betta) | |
conf_new.signs = copy.deepcopy(self.signs) | |
return conf_new | |
def computeEnergy(self): | |
summ = 0 | |
i = 0 | |
for point in self.points: | |
for link in point.links: | |
if point.id<self.points[link].id: | |
summ += self.signs[point.id]*self.signs[self.points[link].id] | |
i+=1 | |
summ= math.exp(summ * self.betta) | |
print(i) | |
return summ | |
# def compute_dif_energy(self, num): | |
# potential_cand = self.points[num] | |
# new_conf = self.clone() | |
# new_conf.signs[num] = - new_conf.signs[num] | |
# new_energy = new_conf.computeEnergy() | |
# old_energy = self.computeEnergy() | |
# diff = new_energy - old_energy | |
# return (diff, new_conf) | |
def compute_sum_diff(self, num): | |
potential_cand = self.points[num] | |
summ = 0 | |
for link in potential_cand.links: | |
summ += self.signs[self.points[link].id] | |
summ*=self.signs[num] | |
return summ | |
def try_to_move(self, num): | |
diff = self.compute_sum_diff(num) | |
p = min(1, math.exp(-2.*self.betta*diff)) | |
move_success = random.random() < p | |
if move_success: | |
new_conf = self.clone() | |
new_conf.signs[num] = - new_conf.signs[num] | |
#print 'transition' | |
return (True, new_conf) | |
return (False, self) | |
def pointsMark(): | |
res = [] | |
img = cv2.imread(IMG_NAME) | |
count = [0] | |
def drawPoints(event,x,y,flags,param): | |
if event == cv2.EVENT_LBUTTONDBLCLK: | |
cv2.circle(img, (x, y), 5, (255, 0, 0), -1) | |
cv2.putText(img, str(count[0]), (x+5, y+5), cv2.FONT_HERSHEY_SIMPLEX, 1, 255) | |
print(count[0], x,y) | |
res.append(Point(count[0], x, y)) | |
count[0] += 1 | |
cv2.namedWindow('image') | |
cv2.setMouseCallback('image', drawPoints) | |
while (1): | |
cv2.imshow('image', img) | |
k = cv2.waitKey(20) & 0xFF | |
if k == 27: | |
break | |
elif k == ord('a'): | |
break | |
cv2.imwrite('points.png', img) | |
return res | |
def startAndSafePoints(): | |
res = pointsMark() | |
with open(PKL, 'wb') as output: | |
pickle.dump(res, output, pickle.HIGHEST_PROTOCOL) | |
print(len(res)) | |
def loadPoints(): | |
with open(PKL, 'rb') as input: | |
points = pickle.load(input) | |
return points | |
def fillLinks(points): | |
links = LINKS | |
for link_set in links: | |
for i in range(len(link_set)): | |
this_el = link_set[(i) % len(link_set)] | |
neighb = link_set[(i+1) % len(link_set)] | |
if neighb not in points[this_el].links: | |
points[this_el].links.append(neighb) | |
if this_el not in points[neighb].links: | |
points[neighb].links.append(this_el) | |
def drawPointsAndLinks(points): | |
img = cv2.imread(IMG_NAME) | |
for point in points: | |
cv2.circle(img, (point.x, point.y), 5, (255, 0, 0), -1) | |
cv2.putText(img, str(point.id), (point.x + 5, point.y + 5), cv2.FONT_HERSHEY_SIMPLEX, 1, 255) | |
for link in point.links: | |
neigb = points[link] | |
cv2.line(img, (point.x, point.y), (neigb.x, neigb.y), (0, 255, 0), 2) | |
cv2.imshow('image', img) | |
cv2.waitKey() | |
def drawConf(conf): | |
points = conf.points | |
img = cv2.imread(IMG_NAME) | |
for point in points: | |
for link in point.links: | |
neigb = points[link] | |
cv2.line(img, (point.x, point.y), (neigb.x, neigb.y), (122, 122, 122), 2) | |
cv2.circle(img, (point.x, point.y), 5, (255, 0, 0) if conf.signs[point.id] == -1 else (0, 0, 255), -1) | |
cv2.putText(img, str(point.id), (point.x + 5, point.y + 5), cv2.FONT_HERSHEY_SIMPLEX, 1, 255) | |
cv2.imshow('image', img) | |
cv2.waitKey() | |
# def resave_points(points): | |
# for point in points: | |
# point.links = [] | |
# with open('points_.pkl', 'wb') as output: | |
# pickle.dump(points, output, pickle.HIGHEST_PROTOCOL) | |
def start_improve_model(start, max): | |
cnt = 0 | |
new_model = start | |
while cnt < max: | |
new_pos = random.choice(new_model.signs.keys()) | |
succ, new_model = new_model.try_to_move(new_pos) | |
if succ: | |
cnt+=1 | |
return new_model | |
points = loadPoints() | |
#resave_points(points) | |
fillLinks(points) | |
#drawPointsAndLinks(points) | |
conf = Config(points, betta=0.6) | |
last = start_improve_model(conf, 10000) | |
drawConf(last) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment