refactor everything as operators of an iterative search
This commit is contained in:
parent
27b52fef6c
commit
05822d8a42
1 changed files with 144 additions and 25 deletions
169
sho/snp.py
169
sho/snp.py
|
|
@ -1,38 +1,157 @@
|
|||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
import copy
|
||||
|
||||
def x(p):
|
||||
return p[0]
|
||||
########################################################################
|
||||
# Utilities
|
||||
########################################################################
|
||||
|
||||
def y(p):
|
||||
return p[1]
|
||||
def x(a):
|
||||
return a[0]
|
||||
|
||||
def y(a):
|
||||
return a[1]
|
||||
|
||||
def distance(a,b):
|
||||
return np.sqrt( (x(a)-x(b))**2 + (y(a)-y(b))**2 )
|
||||
|
||||
def count(domain_shape, sensors_positions, radius, output_domain = None):
|
||||
s = 0
|
||||
Y,X = domain_shape
|
||||
for y in range(Y):
|
||||
for x in range(X):
|
||||
p = (x,y)
|
||||
t = 0
|
||||
for sensor in sensors_positions:
|
||||
if distance( p, sensor ) < radius:
|
||||
t += 1
|
||||
# break
|
||||
if output_domain is not None:
|
||||
output_domain[y][x] = t
|
||||
s += t
|
||||
return s
|
||||
|
||||
########################################################################
|
||||
# Objective functions
|
||||
########################################################################
|
||||
|
||||
def coverage(domain,sensors,sensor_range):
|
||||
for py in range(len(domain)):
|
||||
for px in range(len(domain[py])):
|
||||
p = (px,py)
|
||||
for x in sensors:
|
||||
if distance(x,p) < sensor_range:
|
||||
domain[py][px] = 1
|
||||
break
|
||||
return domain
|
||||
|
||||
def cover_bit(sol,domain_width,sensor_range):
|
||||
domain = np.zeros((domain_width,domain_width))
|
||||
sensors = []
|
||||
for i in range(domain_width):
|
||||
for j in range(domain_width):
|
||||
if sol[i][j] == 1:
|
||||
sensors.append( (j,i) )
|
||||
return np.sum(coverage(domain, sensors, sensor_range))
|
||||
|
||||
def cover_num(sol,domain_width,sensor_range):
|
||||
domain = np.zeros((domain_width,domain_width))
|
||||
sensors = []
|
||||
for i in range(0,len(sol),2):
|
||||
sensors.append( (sol[i],sol[i+1]) )
|
||||
return np.sum(coverage(domain, sensors, sensor_range))
|
||||
|
||||
def make_func(cover,**kwargs):
|
||||
def f(sol):
|
||||
return cover(sol,**kwargs)
|
||||
return f
|
||||
|
||||
|
||||
########################################################################
|
||||
# Initialization
|
||||
########################################################################
|
||||
|
||||
def rand_num(dim):
|
||||
return np.random.random(dim)
|
||||
|
||||
def rand_bit(domain_width,nb_sensors):
|
||||
domain = np.zeros((domain_width,domain_width))
|
||||
for x,y in np.random.randint(0,domain_width,(nb_sensors,2)):
|
||||
domain[y][x] = 1
|
||||
return domain
|
||||
|
||||
def make_init(init,**kwargs):
|
||||
def f():
|
||||
return init(**kwargs)
|
||||
return f
|
||||
|
||||
|
||||
########################################################################
|
||||
# Neighborhood
|
||||
########################################################################
|
||||
|
||||
def neighb_num_rect(sol, scale):
|
||||
return np.random.random(len(sol)) * scale - scale/2
|
||||
|
||||
def neighb_bit_rect(sol, scale):
|
||||
# Copy, because Python pass by reference.
|
||||
new = copy.copy(sol)
|
||||
for yy in range(len(sol)):
|
||||
for xx in range(len(sol[yy])):
|
||||
if sol[yy][xx] == 1:
|
||||
new[yy][xx] = 0
|
||||
d = np.random.randint(-scale//2,scale//2,2)
|
||||
new[yy+y(d)][xx+x(d)] = 1
|
||||
return new
|
||||
|
||||
def make_neig(neighb,**kwargs):
|
||||
def f(sol):
|
||||
return neighb(sol, **kwargs)
|
||||
return f
|
||||
|
||||
|
||||
########################################################################
|
||||
# Stopping criterions
|
||||
########################################################################
|
||||
|
||||
def iters_nb(val,sol,nb_it):
|
||||
for i in range(nb_it):
|
||||
yield i
|
||||
yield i
|
||||
|
||||
def make_iter(iters,nb_it):
|
||||
def cont(val,sol):
|
||||
return iters(val,sol,nb_it)
|
||||
return cont
|
||||
|
||||
|
||||
########################################################################
|
||||
# Algorithms
|
||||
########################################################################
|
||||
|
||||
def search(func, init, neighb, iters):
|
||||
best_sol = init()
|
||||
best_val = func(best_sol)
|
||||
for i in iters(best_val, best_sol):
|
||||
sol = neighb(best_sol)
|
||||
val = func(sol)
|
||||
if val > best_val:
|
||||
best_val = val
|
||||
best_sol = sol
|
||||
return val,sol
|
||||
|
||||
if __name__=="__main__":
|
||||
|
||||
domain = np.zeros( (100,100) )
|
||||
d = 2
|
||||
nb_sensors = 3
|
||||
sensor_range = 2
|
||||
domain_width = 10
|
||||
|
||||
sensors = np.round(np.random.random( (3,2) ) * 100)
|
||||
# domain = np.zeros((domain_width,domain_width))
|
||||
# domain = coverage(domain,[(10,50),(40,80)],50)
|
||||
# plt.imshow(domain)
|
||||
# plt.show()
|
||||
|
||||
s = count(domain.shape, sensors, 40, domain)
|
||||
print(
|
||||
search(
|
||||
make_func(cover_num, domain_width=domain_width, sensor_range=sensor_range),
|
||||
make_init(rand_num, dim=d * nb_sensors),
|
||||
make_neig(neighb_num_rect, scale=domain_width/10),
|
||||
make_iter(iters_nb,10)
|
||||
)
|
||||
)
|
||||
|
||||
print(
|
||||
search(
|
||||
make_func(cover_bit, domain_width=domain_width, sensor_range=sensor_range),
|
||||
make_init(rand_bit, domain_width=domain_width, nb_sensors=nb_sensors),
|
||||
make_neig(neighb_bit_rect, scale=3),
|
||||
make_iter(iters_nb,10)
|
||||
)
|
||||
)
|
||||
|
||||
plt.imshow(domain)
|
||||
plt.show()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue