Commit e2a6cdc8 authored by Julien Lin's avatar Julien Lin
Browse files

format code

parent e6b32d0b
......@@ -52,7 +52,7 @@ def neighb_square(sol, scale, domain_width):
"""Draw a random vector in a square of witdh `scale` in [0,1]
as a fraction of the domain width around the given solution."""
assert(0 < scale <= 1)
side = domain_width * scale;
side = domain_width * scale
new = sol + (np.random.random(len(sol)) * side - side/2)
return new
#encoding: utf-8
# encoding: utf-8
import math
from typing import Any
import numpy as np
import matplotlib.pyplot as plt
......@@ -9,7 +10,7 @@ from sho import make, algo, iters, plot, num, bit, pb
# Interface
########################################################################
if __name__=="__main__":
if __name__ == "__main__":
import argparse
# Dimension of the search space.
......@@ -17,95 +18,176 @@ if __name__=="__main__":
can = argparse.ArgumentParser()
can.add_argument("-n", "--nb-sensors", metavar="NB", default=3, type=int,
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, max is √2)")
can.add_argument("-w", "--domain-width", metavar="NB", default=30, type=int,
help="Domain width (a number of cells). If you change this you will probably need to update `--target` accordingly")
can.add_argument("-i", "--iters", metavar="NB", default=100, type=int,
help="Maximum number of iterations")
can.add_argument("-s", "--seed", metavar="VAL", default=None, type=int,
help="Random pseudo-generator seed (none for current epoch)")
solvers = ["num_greedy","bit_greedy"]
can.add_argument("-m", "--solver", metavar="NAME", choices=solvers, default="num_greedy",
help="Solver to use, among: "+", ".join(solvers))
can.add_argument("-t", "--target", metavar="VAL", default=30*30, type=float,
help="Objective function value target")
can.add_argument("-y", "--steady-delta", metavar="NB", default=50, type=float,
help="Stop if no improvement after NB iterations")
can.add_argument("-e", "--steady-epsilon", metavar="DVAL", default=0, type=float,
help="Stop if the improvement of the objective function value is lesser than DVAL")
can.add_argument("-a", "--variation-scale", metavar="RATIO", default=0.3, type=float,
help="Scale of the variation operators (as a ration of the domain width)")
can.add_argument(
"-n",
"--nb-sensors",
metavar="NB",
default=3,
type=int,
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, max is √2)",
)
can.add_argument(
"-w",
"--domain-width",
metavar="NB",
default=30,
type=int,
help="Domain width (a number of cells). If you change this you will probably need to update `--target` accordingly",
)
can.add_argument(
"-i",
"--iters",
metavar="NB",
default=100,
type=int,
help="Maximum number of iterations",
)
can.add_argument(
"-s",
"--seed",
metavar="VAL",
default=None,
type=int,
help="Random pseudo-generator seed (none for current epoch)",
)
solvers = ["num_greedy", "bit_greedy", "num_sim_anneal", "bit_sim_anneal"]
can.add_argument(
"-m",
"--solver",
metavar="NAME",
choices=solvers,
default="num_greedy",
help="Solver to use, among: " + ", ".join(solvers),
)
can.add_argument(
"-t",
"--target",
metavar="VAL",
default=30 * 30,
type=float,
help="Objective function value target",
)
can.add_argument(
"-y",
"--steady-delta",
metavar="NB",
default=50,
type=float,
help="Stop if no improvement after NB iterations",
)
can.add_argument(
"-e",
"--steady-epsilon",
metavar="DVAL",
default=0,
type=float,
help="Stop if the improvement of the objective function value is lesser than DVAL",
)
can.add_argument(
"-a",
"--variation-scale",
metavar="RATIO",
default=0.3,
type=float,
help="Scale of the variation operators (as a ration of the domain width)",
)
the = can.parse_args()
# Minimum checks.
assert(0 < the.nb_sensors)
assert(0 < the.sensor_range <= math.sqrt(2))
assert(0 < the.domain_width)
assert(0 < the.iters)
assert 0 < the.nb_sensors
assert 0 < the.sensor_range <= math.sqrt(2)
assert 0 < the.domain_width
assert 0 < the.iters
# Do not forget the seed option,
# in case you would start "runs" in parallel.
np.random.seed(the.seed)
# Weird numpy way to ensure single line print of array.
np.set_printoptions(linewidth = np.inf)
np.set_printoptions(linewidth=np.inf)
# Common termination and checkpointing.
history = []
history: list[Any] = []
iters = make.iter(
iters.several,
agains = [
make.iter(iters.max,
nb_it = the.iters),
make.iter(iters.save,
filename = the.solver+".csv",
fmt = "{it} ; {val} ; {sol}\n"),
make.iter(iters.log,
fmt="\r{it} {val}"),
make.iter(iters.history,
history = history),
make.iter(iters.target,
target = the.target),
iters.steady(the.steady_delta, the.steady_epsilon)
]
)
iters.several,
agains=[
make.iter(iters.max, nb_it=the.iters),
make.iter(
iters.save, filename=the.solver + ".csv", fmt="{it} ; {val} ; {sol}\n"
),
make.iter(iters.log, fmt="\r{it} {val}"),
make.iter(iters.history, history=history),
make.iter(iters.target, target=the.target),
iters.steady(the.steady_delta, the.steady_epsilon),
],
)
# Erase the previous file.
with open(the.solver+".csv", 'w') as fd:
fd.write("# {} {}\n".format(the.solver,the.domain_width))
with open(the.solver + ".csv", "w") as fd:
fd.write("# {} {}\n".format(the.solver, the.domain_width))
val,sol,sensors = None,None,None
val, sol, sensors = None, None, None
if the.solver == "num_greedy":
val,sol = algo.greedy(
make.func(num.cover_sum,
domain_width = the.domain_width,
sensor_range = the.sensor_range,
dim = d * the.nb_sensors),
make.init(num.rand,
dim = d * the.nb_sensors,
scale = the.domain_width),
make.neig(num.neighb_square,
scale = the.variation_scale,
domain_width = the.domain_width),
iters
)
val, sol = algo.greedy(
make.func(
num.cover_sum,
domain_width=the.domain_width,
sensor_range=the.sensor_range,
dim=d * the.nb_sensors,
),
make.init(
num.rand,
dim=d * the.nb_sensors,
scale=the.domain_width,
),
make.neig(
num.neighb_square,
scale=the.variation_scale,
domain_width=the.domain_width,
),
iters,
)
sensors = num.to_sensors(sol)
elif the.solver == "bit_greedy":
val, sol = algo.greedy(
make.func(
bit.cover_sum,
domain_width=the.domain_width,
sensor_range=the.sensor_range,
dim=d * the.nb_sensors,
),
make.init(
bit.rand,
domain_width=the.domain_width,
nb_sensors=the.nb_sensors,
),
make.neig(
bit.neighb_square,
scale=the.variation_scale,
domain_width=the.domain_width,
),
iters,
)
sensors = bit.to_sensors(sol)
elif the.solver == "num_sim_anneal":
def temp_generator(lamda):
......@@ -150,31 +232,73 @@ if __name__=="__main__":
)
sensors = num.to_sensors(sol)
)
elif the.solver == "bit_sim_anneal":
def temp_generator(lamda):
def f(T):
return lamda * T
return f
def proba():
def f(delta_energy, temp):
return np.exp(-delta_energy / temp)
return f
def rand():
def f():
return np.random.rand()
return f
val, sol = algo.simulated_annealing(
make.func(
bit.cover_sum,
domain_width=the.domain_width,
sensor_range=the.sensor_range,
dim=d * the.nb_sensors,
),
make.init(
bit.rand,
domain_width=d * the.nb_sensors,
nb_sensors=the.nb_sensors,
),
make.neig(
bit.neighb_square,
scale=the.variation_scale,
domain_width=the.domain_width,
),
temp_generator(0.99),
proba(),
rand(),
iters,
)
sensors = bit.to_sensors(sol)
# Fancy output.
print("\n{} : {}".format(val,sensors))
print("\n{} : {}".format(val, sensors))
shape=(the.domain_width, the.domain_width)
shape = (the.domain_width, the.domain_width)
fig = plt.figure()
if the.nb_sensors ==1 and the.domain_width <= 50:
ax1 = fig.add_subplot(121, projection='3d')
if the.nb_sensors == 1 and the.domain_width <= 50:
ax1 = fig.add_subplot(121, projection="3d")
ax2 = fig.add_subplot(122)
f = make.func(num.cover_sum,
domain_width = the.domain_width,
sensor_range = the.sensor_range * the.domain_width)
f = make.func(
num.cover_sum,
domain_width=the.domain_width,
sensor_range=the.sensor_range * the.domain_width,
)
plot.surface(ax1, shape, f)
plot.path(ax1, shape, history)
else:
ax2=fig.add_subplot(111)
ax2 = fig.add_subplot(111)
domain = np.zeros(shape)
domain = pb.coverage(domain, sensors,
the.sensor_range * the.domain_width)
domain = pb.coverage(domain, sensors, the.sensor_range * the.domain_width)
domain = plot.highlight_sensors(domain, sensors)
ax2.imshow(domain)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment