1 // OpenNN: Open Neural Networks Library
2 // www.opennn.net
3 //
4 // R E S P O N S E O P T I M I Z A T I O N C L A S S
5 //
6 // Artificial Intelligence Techniques SL
7 // artelnics@artelnics.com
8
9 #include "response_optimization.h"
10
11 namespace OpenNN
12 {
13
14 /// Default constructor.
15 /// It creates a scaling layer object with no scaling neurons.
16
ResponseOptimization()17 ResponseOptimization::ResponseOptimization()
18 {
19 }
20
21
ResponseOptimization(NeuralNetwork * new_neural_network_pointer)22 ResponseOptimization::ResponseOptimization(NeuralNetwork* new_neural_network_pointer)
23 {
24 neural_network_pointer = new_neural_network_pointer;
25
26 const Index inputs_number = neural_network_pointer->get_inputs_number();
27 const Index outputs_number = neural_network_pointer->get_outputs_number();
28 /*
29 inputs_conditions.set(inputs_number, Between);
30 outputs_conditions.set(outputs_number, Minimum);
31 */
32 inputs_minimums = neural_network_pointer->get_scaling_layer_pointer()->get_minimums();
33 inputs_maximums = neural_network_pointer->get_scaling_layer_pointer()->get_maximums();
34
35 outputs_minimums = neural_network_pointer->get_bounding_layer_pointer()->get_lower_bounds();
36 outputs_maximums = neural_network_pointer->get_bounding_layer_pointer()->get_upper_bounds();
37 }
38
39
40 /// Destructor.
41
~ResponseOptimization()42 ResponseOptimization::~ResponseOptimization()
43 {
44 }
45
46
set_evaluations_number(const Index & new_evaluations_number)47 void ResponseOptimization::set_evaluations_number(const Index& new_evaluations_number)
48 {
49 evaluations_number = new_evaluations_number;
50 }
51
52
get_inputs_conditions()53 Tensor<ResponseOptimization::Condition, 1> ResponseOptimization::get_inputs_conditions()
54 {
55 return inputs_conditions;
56 }
57
58
get_outputs_conditions()59 Tensor<ResponseOptimization::Condition, 1> ResponseOptimization::get_outputs_conditions()
60 {
61 return outputs_conditions;
62 }
63
64
get_inputs_minimums()65 Tensor<type, 1> ResponseOptimization::get_inputs_minimums()
66 {
67 return inputs_minimums;
68 }
69
70
get_inputs_maximums()71 Tensor<type, 1> ResponseOptimization::get_inputs_maximums()
72 {
73 return inputs_maximums;
74 }
75
76
get_outputs_minimums()77 Tensor<type, 1> ResponseOptimization::get_outputs_minimums()
78 {
79 return outputs_minimums;
80 }
81
82
get_outputs_maximums()83 Tensor<type, 1> ResponseOptimization::get_outputs_maximums()
84 {
85 return outputs_maximums;
86 }
87
set_input_condition(const string & name,const ResponseOptimization::Condition & condition,const Tensor<type,1> & values)88 void ResponseOptimization::set_input_condition(const string& name, const ResponseOptimization::Condition& condition, const Tensor<type, 1>& values)
89 {
90 const Index index = neural_network_pointer->get_input_index(name);
91
92 set_input_condition(index, condition, values);
93 }
94
95
set_output_condition(const string & name,const ResponseOptimization::Condition & condition,const Tensor<type,1> & values)96 void ResponseOptimization::set_output_condition(const string& name, const ResponseOptimization::Condition& condition, const Tensor<type, 1>& values)
97 {
98 const Index index = neural_network_pointer->get_output_index(name);
99
100 set_output_condition(index, condition, values);
101 }
102
103
set_input_condition(const Index & index,const ResponseOptimization::Condition & condition,const Tensor<type,1> & values)104 void ResponseOptimization::set_input_condition(const Index& index, const ResponseOptimization::Condition& condition, const Tensor<type, 1>& values)
105 {
106 inputs_conditions[index] = condition;
107
108 ostringstream buffer;
109
110 switch(condition)
111 {
112 case Minimum:
113
114 if(values.size() != 0)
115 {
116 buffer << "OpenNN Exception: ResponseOptimization class.\n"
117 << "void set_input_condition() method.\n"
118 << "For Minimum condition, size of values must be 0.\n";
119
120 throw logic_error(buffer.str());
121 }
122
123 return;
124
125 case Maximum:
126
127 if(values.size() != 0)
128 {
129 buffer << "OpenNN Exception: ResponseOptimization class.\n"
130 << "void set_input_condition() method.\n"
131 << "For Maximum condition, size of values must be 0.\n";
132
133 throw logic_error(buffer.str());
134 }
135
136 return;
137
138 case EqualTo:
139
140 if(values.size() != 1)
141 {
142 buffer << "OpenNN Exception: ResponseOptimization class.\n"
143 << "void set_input_condition() method.\n"
144 << "For LessEqualTo condition, size of values must be 1.\n";
145
146 throw logic_error(buffer.str());
147 }
148
149 inputs_minimums[index] = values[0];
150 inputs_maximums[index] = values[0];
151
152 return;
153
154 case LessEqualTo:
155
156 if(values.size() != 1)
157 {
158 buffer << "OpenNN Exception: ResponseOptimization class.\n"
159 << "void set_input_condition() method.\n"
160 << "For LessEqualTo condition, size of values must be 1.\n";
161
162 throw logic_error(buffer.str());
163 }
164
165 inputs_maximums[index] = values[0];
166
167 return;
168
169 case GreaterEqualTo:
170
171 if(values.size() != 1)
172 {
173 buffer << "OpenNN Exception: ResponseOptimization class.\n"
174 << "void set_input_condition() method.\n"
175 << "For LessEqualTo condition, size of values must be 1.\n";
176
177 throw logic_error(buffer.str());
178 }
179
180 inputs_minimums[index] = values[0];
181
182 return;
183
184 case Between:
185
186 if(values.size() != 2)
187 {
188 buffer << "OpenNN Exception: ResponseOptimization class.\n"
189 << "void set_input_condition() method.\n"
190 << "For Between condition, size of values must be 2.\n";
191
192 throw logic_error(buffer.str());
193 }
194
195 inputs_minimums[index] = values[0];
196 inputs_maximums[index] = values[1];
197
198 return;
199 }
200 }
201
202
set_output_condition(const Index & index,const ResponseOptimization::Condition & condition,const Tensor<type,1> & values)203 void ResponseOptimization::set_output_condition(const Index& index, const ResponseOptimization::Condition& condition, const Tensor<type, 1>& values)
204 {
205 outputs_conditions[index] = condition;
206
207 ostringstream buffer;
208
209 switch(condition)
210 {
211 case Minimum:
212
213 if(values.size() != 0)
214 {
215 buffer << "OpenNN Exception: ResponseOptimization class.\n"
216 << "void set_output_condition() method.\n"
217 << "For Minimum condition, size of values must be 0.\n";
218
219 throw logic_error(buffer.str());
220 }
221
222 return;
223
224 case Maximum:
225
226 if(values.size() != 0)
227 {
228 buffer << "OpenNN Exception: ResponseOptimization class.\n"
229 << "void set_output_condition() method.\n"
230 << "For Maximum condition, size of values must be 0.\n";
231
232 throw logic_error(buffer.str());
233 }
234
235 return;
236
237 case EqualTo:
238
239 if(values.size() != 1)
240 {
241 buffer << "OpenNN Exception: ResponseOptimization class.\n"
242 << "void set_output_condition() method.\n"
243 << "For LessEqualTo condition, size of values must be 1.\n";
244
245 throw logic_error(buffer.str());
246 }
247
248 outputs_minimums[index] = values[0];
249 outputs_maximums[index] = values[0];
250
251 return;
252
253 case LessEqualTo:
254
255 if(values.size() != 1)
256 {
257 buffer << "OpenNN Exception: ResponseOptimization class.\n"
258 << "void set_output_condition() method.\n"
259 << "For LessEqualTo condition, size of values must be 1.\n";
260
261 throw logic_error(buffer.str());
262 }
263
264 outputs_maximums[index] = values[0];
265
266 return;
267
268 case GreaterEqualTo:
269
270 if(values.size() != 1)
271 {
272 buffer << "OpenNN Exception: ResponseOptimization class.\n"
273 << "void set_output_condition() method.\n"
274 << "For LessEqualTo condition, size of values must be 1.\n";
275
276 throw logic_error(buffer.str());
277 }
278
279 outputs_minimums[index] = values[0];
280
281 return;
282
283 case Between:
284
285 if(values.size() != 2)
286 {
287 buffer << "OpenNN Exception: ResponseOptimization class.\n"
288 << "void set_output_condition() method.\n"
289 << "For Between condition, size of values must be 2.\n";
290
291 throw logic_error(buffer.str());
292 }
293
294 outputs_minimums[index] = values[0];
295 outputs_maximums[index] = values[1];
296
297 return;
298 }
299 }
300
301
set_inputs_outputs_conditions(const Tensor<string,1> & names,const Tensor<string,1> & conditions_string,const Tensor<type,1> & values)302 void ResponseOptimization::set_inputs_outputs_conditions(const Tensor<string, 1>& names, const Tensor<string, 1>& conditions_string, const Tensor<type, 1>& values)
303 {
304 Tensor<Condition, 1> conditions = get_conditions(conditions_string);
305 Tensor<Tensor<type, 1>, 1> values_conditions = get_values_conditions(conditions, values);
306
307 const Index variables_number = conditions_string.size();
308
309 const Tensor<string, 1> inputs_names = neural_network_pointer->get_inputs_names();
310
311 Index index;
312 /*
313 for(Index i = 0; i < variables_number; i ++)
314 {
315 if(inputs_names.contains(names[i]))
316 {
317 index = neural_network_pointer->get_input_index(names[i]);
318
319 set_input_condition(index, conditions[i], values_conditions[i]);
320 }
321 else
322 {
323 index = neural_network_pointer->get_output_index(names[i]);
324
325 set_output_condition(index, conditions[i], values_conditions[i]);
326 }
327 }
328 */
329 }
330
331
get_conditions(const Tensor<string,1> & conditions_string) const332 Tensor<ResponseOptimization::Condition, 1> ResponseOptimization::get_conditions(const Tensor<string, 1>& conditions_string) const
333 {
334 const Index conditions_size = conditions_string.size();
335
336 Tensor<Condition, 1> conditions(conditions_size);
337
338 for(Index i = 0; i < conditions_size; i++)
339 {
340 if(conditions_string[i] == "Minimize")
341 {
342 conditions[i] = Minimum;
343 }
344 else if(conditions_string[i] == "Maximize")
345 {
346 conditions[i] = Maximum;
347 }
348 else if(conditions_string[i] == "=")
349 {
350 conditions[i] = EqualTo;
351 }
352 else if(conditions_string[i] == "Between")
353 {
354 conditions[i] = Between;
355 }
356 else if(conditions_string[i] == ">="
357 || conditions_string[i] == ">")
358 {
359 conditions[i] = GreaterEqualTo;
360 }
361 else if(conditions_string[i] == "<="
362 || conditions_string[i] == "<")
363 {
364 conditions[i] = LessEqualTo;
365 }
366 }
367
368 return conditions;
369 }
370
371
get_values_conditions(const Tensor<ResponseOptimization::Condition,1> & conditions,const Tensor<type,1> & values) const372 Tensor<Tensor<type, 1>, 1> ResponseOptimization::get_values_conditions(const Tensor<ResponseOptimization::Condition, 1>& conditions, const Tensor<type, 1>& values) const
373 {
374 const Index conditions_size = conditions.size();
375
376 Tensor<Tensor<type, 1>, 1> values_conditions(conditions_size);
377
378 Index index = 0;
379
380 ostringstream buffer;
381
382 for(Index i = 0; i < conditions_size; i++)
383 {
384 Tensor<type, 1> current_values;
385
386 const Condition current_condition = conditions[i];
387
388 switch(current_condition)
389 {
390 case Minimum:
391
392 values_conditions[i].resize(0);
393
394 index++;
395 break;
396
397 case Maximum:
398
399 values_conditions[i].resize(0);
400
401 index++;
402 break;
403
404 case EqualTo:
405
406 current_values.resize(1);
407 current_values[0] = values[index];
408 index++;
409
410 values_conditions[i] = current_values;
411
412 break;
413
414 case LessEqualTo:
415
416 current_values.resize(1);
417 current_values[0] = values[index];
418 index++;
419
420 values_conditions[i] = current_values;
421
422 break;
423
424 case GreaterEqualTo:
425
426 current_values.resize(1);
427 current_values[0] = values[index];
428
429 index++;
430
431 values_conditions[i] = current_values;
432
433 break;
434
435 case Between:
436
437 current_values.resize(2);
438 current_values[0] = values[index];
439 index++;
440 current_values[1] = values[index];
441 index++;
442
443 values_conditions[i] = current_values;
444
445 break;
446 }
447 }
448
449 return values_conditions;
450 }
451
452
calculate_inputs() const453 Tensor<type, 2> ResponseOptimization::calculate_inputs() const
454 {
455 const Index inputs_number = neural_network_pointer->get_inputs_number();
456
457 Tensor<type, 2> inputs(evaluations_number, inputs_number);
458
459 for(Index i = 0; i < evaluations_number; i++)
460 {
461 for(Index j = 0; j < inputs_number; j++)
462 {
463 inputs(i,j) = calculate_random_uniform(inputs_minimums[j], inputs_maximums[j]);
464 }
465 }
466
467 return inputs;
468 }
469
470
calculate_envelope(const Tensor<type,2> & inputs,const Tensor<type,2> & outputs) const471 Tensor<type, 2> ResponseOptimization::calculate_envelope(const Tensor<type, 2>& inputs, const Tensor<type, 2>& outputs) const
472 {
473 const Index inputs_number = neural_network_pointer->get_inputs_number();
474 const Index outputs_number = neural_network_pointer->get_outputs_number();
475 /*
476 Tensor<type, 2> envelope = (inputs.to_matrix()).assemble_columns((outputs.to_matrix()));
477
478 for(Index i = 0; i < outputs_number; i++)
479 {
480 envelope = envelope.filter_column_minimum_maximum(inputs_number+i, outputs_minimums[i], outputs_maximums[i]);
481 }
482
483 return envelope;
484 */
485
486 return Tensor<type, 2>();
487 }
488
489
perform_optimization() const490 ResponseOptimization::Results* ResponseOptimization::perform_optimization() const
491 {
492 Results* results = new Results(neural_network_pointer);
493
494 const Tensor<type, 2> inputs = calculate_inputs();
495
496 const Tensor<type, 2> outputs = neural_network_pointer->calculate_outputs(inputs);
497
498 const Tensor<type, 2> envelope = calculate_envelope(inputs, outputs);
499
500 const Index samples_number = envelope.dimension(0);
501
502 const Index inputs_number = neural_network_pointer->get_inputs_number();
503 const Index outputs_number = neural_network_pointer->get_outputs_number();
504
505 Tensor<type, 1> objective(samples_number);
506
507 for(Index i = 0; i < samples_number; i++)
508 {
509 for(Index j = 0; j < inputs_number; j++)
510 {
511 if(inputs_conditions[j] == Minimum)
512 {
513 objective[i] += envelope(i,j);
514 }
515 else if(inputs_conditions[j] == Maximum)
516 {
517 objective[i] += -envelope(i,j);
518 }
519 }
520
521 for(Index j = 0; j < outputs_number; j++)
522 {
523 if(outputs_conditions[j] == Minimum)
524 {
525 objective[i] += envelope(i, inputs_number+j);
526 }
527 else if(outputs_conditions[j] == Maximum)
528 {
529 objective[i] += -envelope(i, inputs_number+j);
530 }
531 }
532 }
533
534 const Index optimal_index = minimal_index(objective);
535 /*
536 results->optimal_variables = envelope.get_row(optimal_index);
537
538 results->optimum_objective = objective[optimal_index];
539 */
540 return results;
541 }
542
543
calculate_random_uniform(const type & minimum,const type & maximum) const544 type ResponseOptimization::calculate_random_uniform(const type& minimum, const type& maximum) const
545 {
546 const type random = static_cast<type>(rand()/(RAND_MAX + 1.0));
547
548 const type random_uniform = minimum + (maximum - minimum) * random;
549
550 return random_uniform;
551 }
552
553 }
554
555 // OpenNN: Open Neural Networks Library.
556 // Copyright(C) 2005-2020 Artificial Intelligence Techniques, SL.
557 //
558 // This library is free software; you can redistribute it and/or
559 // modify it under the terms of the GNU Lesser General Public
560 // License as published by the Free Software Foundation; either
561 // version 2.1 of the License, or any later version.
562 //
563 // This library is distributed in the hope that it will be useful,
564 // but WITHOUT ANY WARRANTY; without even the implied warranty of
565 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
566 // Lesser General Public License for more details.
567
568 // You should have received a copy of the GNU Lesser General Public
569 // License along with this library; if not, write to the Free Software
570 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
571