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