snp.py 8.66 KB
Newer Older
johann dreo's avatar
johann dreo committed
1
#encoding: utf-8
nojhan's avatar
nojhan committed
2
import math
Johann Dreo's avatar
Johann Dreo committed
3
4
5
import numpy as np
import matplotlib.pyplot as plt

Grégoire GRZECZKOWICZ's avatar
Grégoire GRZECZKOWICZ committed
6
from sho import make, algo, iters, plot, num, bit, pb, temp
Johann Dreo's avatar
Johann Dreo committed
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

########################################################################
# Interface
########################################################################

if __name__=="__main__":
    import argparse

    # Dimension of the search space.
    d = 2

    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,
nojhan's avatar
nojhan committed
24
            help="Sensors' range (as a fraction of domain width, max is √2)")
Johann Dreo's avatar
Johann Dreo committed
25
26

    can.add_argument("-w", "--domain-width", metavar="NB", default=30, type=int,
Johann Dreo's avatar
Johann Dreo committed
27
            help="Domain width (a number of cells). If you change this you will probably need to update `--target` accordingly")
Johann Dreo's avatar
Johann Dreo committed
28
29
30
31
32
33
34

    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)")

Grégoire Grzeczkowicz's avatar
Grégoire Grzeczkowicz committed
35
    solvers = ["num_greedy","bit_greedy","num_simulated_annealing","bit_simulated_annealing","num_genetic","bit_genetic"]
Johann Dreo's avatar
Johann Dreo committed
36
37
38
39
40
41
42
43
44
45
46
47
    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")

johann dreo's avatar
johann dreo committed
48
49
    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)")
Johann Dreo's avatar
Johann Dreo committed
50

Grégoire GRZECZKOWICZ's avatar
Grégoire GRZECZKOWICZ committed
51
52
53
    can.add_argument("-no", "--no-graphical-output", action='store_true', default=False,
            help="Disable graphical output")

54
55
56
    can.add_argument("-o", "--output-file", metavar="NAME", default=None, type=str,
            help="Output file where log are put")

Grégoire Grzeczkowicz's avatar
Grégoire Grzeczkowicz committed
57
58
59
    can.add_argument("-p", "--population-size", metavar="NB", default=10, type=int,
            help="Size of the population for genetic algorithms")

Johann Dreo's avatar
Johann Dreo committed
60
61
62
63
    the = can.parse_args()

    # Minimum checks.
    assert(0 < the.nb_sensors)
nojhan's avatar
nojhan committed
64
    assert(0 < the.sensor_range <= math.sqrt(2))
Johann Dreo's avatar
Johann Dreo committed
65
66
67
68
69
70
71
72
73
74
    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)

75
76
77
78
    # Default filename
    if the.output_file == None:
        the.output_file = the.solver

Johann Dreo's avatar
Johann Dreo committed
79
80
81
82
83
84
85
86
87

    # Common termination and checkpointing.
    history = []
    iters = make.iter(
                iters.several,
                agains = [
                    make.iter(iters.max,
                        nb_it = the.iters),
                    make.iter(iters.save,
88
                        filename = the.output_file+".csv",
Grégoire Grzeczkowicz's avatar
Grégoire Grzeczkowicz committed
89
                        fmt = "{it} ; {val}\n"),
Johann Dreo's avatar
Johann Dreo committed
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
                    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))

    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,
johann dreo's avatar
johann dreo committed
109
110
                    sensor_range = the.sensor_range,
                    dim = d * the.nb_sensors),
Grégoire Grzeczkowicz's avatar
Grégoire Grzeczkowicz committed
111
                make.init(num.unif,
Johann Dreo's avatar
Johann Dreo committed
112
113
114
                    dim = d * the.nb_sensors,
                    scale = the.domain_width),
                make.neig(num.neighb_square,
johann dreo's avatar
johann dreo committed
115
                    scale = the.variation_scale,
Johann Dreo's avatar
Johann Dreo committed
116
117
118
119
120
121
122
123
124
                    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,
johann dreo's avatar
johann dreo committed
125
126
                    sensor_range = the.sensor_range,
                    dim = d * the.nb_sensors),
Grégoire Grzeczkowicz's avatar
Grégoire Grzeczkowicz committed
127
                make.init(bit.unif,
Johann Dreo's avatar
Johann Dreo committed
128
129
                    domain_width = the.domain_width,
                    nb_sensors = the.nb_sensors),
130
131
132
133
134
135
136
137
138
139
140
141
142
                make.neig(bit.neighb_square,
                    scale = the.variation_scale,
                    domain_width = the.domain_width),
                iters
            )
        sensors = bit.to_sensors(sol)

    elif the.solver == "num_simulated_annealing":
        val,sol = algo.simulated_annealing(
                make.func(num.cover_sum,
                    domain_width = the.domain_width,
                    sensor_range = the.sensor_range,
                    dim = d * the.nb_sensors),
Grégoire Grzeczkowicz's avatar
Grégoire Grzeczkowicz committed
143
                make.init(num.unif,
144
145
146
147
148
                    dim = d * the.nb_sensors,
                    scale = the.domain_width),
                make.neig(num.neighb_square,
                    scale = the.variation_scale,
                    domain_width = the.domain_width),
Grégoire GRZECZKOWICZ's avatar
Grégoire GRZECZKOWICZ committed
149
                temp.continus(100,0.99),
150
151
152
153
154
155
156
157
158
159
                iters
            )
        sensors = num.to_sensors(sol)

    elif the.solver == "bit_simulated_annealing":
        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),
Grégoire Grzeczkowicz's avatar
Grégoire Grzeczkowicz committed
160
                make.init(bit.unif,
161
162
                    domain_width = the.domain_width,
                    nb_sensors = the.nb_sensors),
Johann Dreo's avatar
Johann Dreo committed
163
                make.neig(bit.neighb_square,
johann dreo's avatar
johann dreo committed
164
                    scale = the.variation_scale,
Johann Dreo's avatar
Johann Dreo committed
165
                    domain_width = the.domain_width),
Grégoire GRZECZKOWICZ's avatar
Grégoire GRZECZKOWICZ committed
166
                temp.continus(100,0.99),
Johann Dreo's avatar
Johann Dreo committed
167
168
169
170
                iters
            )
        sensors = bit.to_sensors(sol)

Grégoire Grzeczkowicz's avatar
Grégoire Grzeczkowicz committed
171
172
173
174
175
176
177
178
179
    elif the.solver == "num_genetic":
        val,sol = algo.genetic(
                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),
Grégoire Grzeczkowicz's avatar
Grégoire Grzeczkowicz committed
180
                num.split_crossover,
Grégoire Grzeczkowicz's avatar
Grégoire Grzeczkowicz committed
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
                make.neig(num.neighb_square,
                    scale = the.variation_scale,
                    domain_width = the.domain_width),
                the.population_size,
                iters
            )
        sensors = num.to_sensors(sol)

    elif the.solver == "bit_genetic":
        val,sol = algo.genetic(
                make.func(bit.cover_sum,
                    domain_width = the.domain_width,
                    sensor_range = the.sensor_range,
                    dim = d * the.nb_sensors),
                make.init(bit.unif,
                    domain_width = the.domain_width,
                    nb_sensors = the.nb_sensors),
198
                bit.split_crossover,
Grégoire Grzeczkowicz's avatar
Grégoire Grzeczkowicz committed
199
200
201
202
203
204
205
206
                make.neig(bit.neighb_square,
                    scale = the.variation_scale,
                    domain_width = the.domain_width),
                the.population_size,
                iters
            )
        sensors = bit.to_sensors(sol)

Johann Dreo's avatar
Johann Dreo committed
207
208
209
    # Fancy output.
    print("\n{} : {}".format(val,sensors))

Grégoire GRZECZKOWICZ's avatar
Grégoire GRZECZKOWICZ committed
210
211
212
    if the.no_graphical_output is False:

        shape=(the.domain_width, the.domain_width)
Johann Dreo's avatar
Johann Dreo committed
213

Grégoire GRZECZKOWICZ's avatar
Grégoire GRZECZKOWICZ committed
214
        fig = plt.figure()
Johann Dreo's avatar
Johann Dreo committed
215

Grégoire GRZECZKOWICZ's avatar
Grégoire GRZECZKOWICZ committed
216
217
218
        if the.nb_sensors ==1 and the.domain_width <= 50:
            ax1 = fig.add_subplot(121, projection='3d')
            ax2 = fig.add_subplot(122)
Johann Dreo's avatar
Johann Dreo committed
219

Grégoire GRZECZKOWICZ's avatar
Grégoire GRZECZKOWICZ committed
220
221
222
223
224
225
226
            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)
Johann Dreo's avatar
Johann Dreo committed
227

Grégoire GRZECZKOWICZ's avatar
Grégoire GRZECZKOWICZ committed
228
229
230
231
232
        domain = np.zeros(shape)
        domain = pb.coverage(domain, sensors,
                the.sensor_range * the.domain_width)
        domain = plot.highlight_sensors(domain, sensors)
        ax2.imshow(domain)
Johann Dreo's avatar
Johann Dreo committed
233

Grégoire GRZECZKOWICZ's avatar
Grégoire GRZECZKOWICZ committed
234
        plt.show()