From ce190c568165c93bfa4c0073e1ba350912502f39 Mon Sep 17 00:00:00 2001 From: nojhan Date: Sat, 14 Dec 2019 10:50:13 +0100 Subject: [PATCH] fix: bad range management in bit.py - use sensor_range * domain_width - add asserts - cleaner bit.neighborhood --- sho/bit.py | 31 +++++++++++++++++++------------ sho/num.py | 11 +++++++++-- snp.py | 7 ++++--- 3 files changed, 32 insertions(+), 17 deletions(-) diff --git a/sho/bit.py b/sho/bit.py index e6a38f5..806f398 100644 --- a/sho/bit.py +++ b/sho/bit.py @@ -1,3 +1,4 @@ +import math import numpy as np import copy @@ -9,9 +10,15 @@ from . import x,y,pb def cover_sum(sol, domain_width, sensor_range): """Compute the coverage quality of the given array of bits.""" + assert(0 < sensor_range <= math.sqrt(2)) + assert(0 < domain_width) + assert(len(sol)>0) domain = np.zeros((domain_width,domain_width)) sensors = to_sensors(sol) - return np.sum(pb.coverage(domain, sensors, sensor_range)) + cov = pb.coverage(domain, sensors, sensor_range*domain_width) + s = np.sum(cov) + assert(s >= len(sensors)) + return s def to_sensors(sol): @@ -21,6 +28,7 @@ def to_sensors(sol): >>> to_sensors([[1,0],[1,0]]) [(0, 0), (0, 1)] """ + assert(len(sol)>0) sensors = [] for i in range(len(sol)): for j in range(len(sol[i])): @@ -46,23 +54,22 @@ def rand(domain_width, nb_sensors): ######################################################################## def neighb_square(sol, scale, domain_width): - """Draw a random array by moving ones to adjacent cells.""" + """Draw a random array by moving every ones to adjacent cells.""" # Copy, because Python pass by reference # and we may not want to alter the original solution. new = copy.copy(sol) for py in range(len(sol)): for px in range(len(sol[py])): + # Indices order is (y,x) in order to match + # coordinates of images (row,col). if sol[py][px] == 1: new[py][px] = 0 # Remove original position. - d = np.random.randint(-scale//2,scale//2,2) - if py+y(d) < 0 : - d[1] = np.random.randint(-py,scale//2) - if py+y(d) >= domain_width : - d[1] = np.random.randint(-scale//2,domain_width-py) - if px+y(d) < 0 : - d[0] = np.random.randint(0,scale//2) - if px+x(d) >= domain_width : - d[0] = np.random.randint(-scale//2,domain_width-px) - new[py+y(d)][px+x(d)] = 1 + # Add a one somewhere around. + w = scale//2 * domain_width + ny = np.random.randint(py-w,py+w) + nx = np.random.randint(px-w,px+w) + ny = min(max(0,ny),domain_width-1) + nx = min(max(0,nx),domain_width-1) + new[ny][nx] = 1 return new diff --git a/sho/num.py b/sho/num.py index c989954..504b3e9 100644 --- a/sho/num.py +++ b/sho/num.py @@ -1,3 +1,4 @@ +import math import numpy as np from . import pb @@ -13,6 +14,7 @@ def to_sensors(sol): >>> to_sensors([0,1,2,3]) [(0, 1), (2, 3)] """ + assert(len(sol)>0) sensors = [] for i in range(0,len(sol),2): sensors.append( ( int(round(sol[i])), int(round(sol[i+1])) ) ) @@ -21,9 +23,15 @@ def to_sensors(sol): def cover_sum(sol, domain_width, sensor_range): """Compute the coverage quality of the given vector.""" + assert(0 < sensor_range <= math.sqrt(2)) + assert(0 < domain_width) + assert(len(sol)>0) domain = np.zeros((domain_width,domain_width)) sensors = to_sensors(sol) - return np.sum(pb.coverage(domain, sensors, sensor_range)) + cov = pb.coverage(domain, sensors, sensor_range*domain_width) + s = np.sum(cov) + assert(s >= len(sensors)) + return s ######################################################################## @@ -42,7 +50,6 @@ def rand(dim, scale): def neighb_square(sol, scale, domain_width): """Draw a random vector in a square of witdh `scale` around the given one.""" - # TODO handle constraints new = sol + (np.random.random(len(sol)) * scale - scale/2) return new diff --git a/snp.py b/snp.py index 4c060c0..3c2d438 100644 --- a/snp.py +++ b/snp.py @@ -1,3 +1,4 @@ +import math import numpy as np import matplotlib.pyplot as plt @@ -19,7 +20,7 @@ if __name__=="__main__": help="Number of sensors") can.add_argument("-r", "--sensor-range", metavar="RATIO", default=0.3, type=float, - help="Sensors' range (as a fraction of domain width)") + help="Sensors' range (as a fraction of domain width, max is √2)") can.add_argument("-w", "--domain-width", metavar="NB", default=30, type=int, help="Domain width (a number of cells)") @@ -48,7 +49,7 @@ if __name__=="__main__": # Minimum checks. assert(0 < the.nb_sensors) - assert(0 < the.sensor_range <= 1) + assert(0 < the.sensor_range <= math.sqrt(2)) assert(0 < the.domain_width) assert(0 < the.iters) @@ -89,7 +90,7 @@ if __name__=="__main__": val,sol = algo.greedy( make.func(num.cover_sum, domain_width = the.domain_width, - sensor_range = the.sensor_range * the.domain_width), + sensor_range = the.sensor_range), make.init(num.rand, dim = d * the.nb_sensors, scale = the.domain_width),