ef697b077f5b14c3c77ea2daf71b7eef254d6359
[policy/apex-pdp.git] / examples / examples-adaptive / src / main / java / org / onap / policy / apex / examples / adaptive / model / java / AutoLearnPolicyDecideTaskSelectionLogic.java
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
4  * ================================================================================
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * SPDX-License-Identifier: Apache-2.0
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.apex.examples.adaptive.model.java;
22
23 import java.util.Arrays;
24 import java.util.List;
25 import java.util.Random;
26
27 import org.onap.policy.apex.context.ContextException;
28 import org.onap.policy.apex.core.engine.executor.context.TaskSelectionExecutionContext;
29 import org.onap.policy.apex.examples.adaptive.concepts.AutoLearn;
30
31 /**
32  * The Class AutoLearnPolicyDecideTaskSelectionLogic.
33  */
34 public class AutoLearnPolicyDecideTaskSelectionLogic {
35     // Recurring string constants
36     private static final String AUTO_LEARN_ALBUM = "AutoLearnAlbum";
37     private static final String AUTO_LEARN = "AutoLearn";
38
39     private static final Random RAND = new Random(System.currentTimeMillis());
40     private static final double WANT = 50.0;
41     private int size;
42
43     /**
44      * Gets the task.
45      *
46      * @param executor the executor
47      * @return the task
48      */
49     public boolean getTask(final TaskSelectionExecutionContext executor) {
50         String idString = executor.subject.getId();
51         executor.logger.debug(idString);
52
53         String inFieldsString = executor.inFields.toString();
54         executor.logger.debug(inFieldsString);
55
56         final List<String> tasks = executor.subject.getTaskNames();
57         size = tasks.size();
58
59         try {
60             executor.getContextAlbum(AUTO_LEARN_ALBUM).lockForWriting(AUTO_LEARN);
61         } catch (final ContextException e) {
62             executor.logger.error("Failed to acquire write lock on \"autoLearn\" context", e);
63             return false;
64         }
65
66         // Get the context object
67         AutoLearn autoLearn = (AutoLearn) executor.getContextAlbum(AUTO_LEARN_ALBUM).get(AUTO_LEARN);
68         if (autoLearn == null) {
69             autoLearn = new AutoLearn();
70         }
71
72         // Check the lists are initialized
73         if (!autoLearn.isInitialized()) {
74             autoLearn.init(size);
75         }
76
77         final double now = (Double) (executor.inFields.get("MonitoredValue"));
78         final double diff = now - WANT;
79         final int option = getOption(diff, autoLearn);
80         learn(option, diff, autoLearn);
81
82         executor.getContextAlbum(AUTO_LEARN_ALBUM).put(AUTO_LEARN_ALBUM, autoLearn);
83
84         try {
85             executor.getContextAlbum(AUTO_LEARN_ALBUM).unlockForWriting(AUTO_LEARN);
86         } catch (final ContextException e) {
87             executor.logger.error("Failed to acquire write lock on \"autoLearn\" context", e);
88             return false;
89         }
90
91         executor.subject.getTaskKey(tasks.get(option)).copyTo(executor.selectedTask);
92         return true;
93     }
94
95     /**
96      * Gets the option.
97      *
98      * @param diff the diff
99      * @param autoLearn the auto learn
100      * @return the option
101      */
102     private int getOption(final double diff, final AutoLearn autoLearn) {
103         final Double[] avdiffs = autoLearn.getAvDiffs().toArray(new Double[autoLearn.getAvDiffs().size()]);
104         final int r = RAND.nextInt(size);
105         int closestupi = -1;
106         int closestdowni = -1;
107         double closestup = Double.MAX_VALUE;
108         double closestdown = Double.MIN_VALUE;
109         for (int i = 0; i < size; i++) {
110             if (Double.isNaN(avdiffs[i])) {
111                 return r;
112             }
113             if (avdiffs[i] >= diff && avdiffs[i] <= closestup) {
114                 closestup = avdiffs[i];
115                 closestupi = i;
116             }
117             if (avdiffs[i] <= diff && avdiffs[i] >= closestdown) {
118                 closestdown = avdiffs[i];
119                 closestdowni = i;
120             }
121         }
122         return calculateReturnValue(diff, r, closestupi, closestdowni, closestup, closestdown);
123     }
124
125     /**
126      * Learn.
127      *
128      * @param option the option
129      * @param diff the diff
130      * @param autoLearn the auto learn
131      */
132     private void learn(final int option, final double diff, final AutoLearn autoLearn) {
133         final Double[] avdiffs = autoLearn.getAvDiffs().toArray(new Double[autoLearn.getAvDiffs().size()]);
134         final Long[] counts = autoLearn.getCounts().toArray(new Long[autoLearn.getCounts().size()]);
135         if (option < 0 || option >= avdiffs.length) {
136             throw new IllegalArgumentException("Error: option" + option);
137         }
138         counts[option]++;
139         if (Double.isNaN(avdiffs[option])) {
140             avdiffs[option] = diff;
141         } else {
142             avdiffs[option] = (avdiffs[option] * (counts[option] - 1) + diff) / counts[option];
143         }
144         autoLearn.setAvDiffs(Arrays.asList(avdiffs));
145         autoLearn.setCounts(Arrays.asList(counts));
146     }
147
148     /**
149      * Calculate the return value of the learning.
150      * 
151      * @param diff the difference
152      * @param random the random value
153      * @param closestupi closest to i upwards
154      * @param closestdowni closest to i downwards
155      * @param closestup closest up value
156      * @param closestdown closest down value
157      * @return the return value
158      */
159     private int calculateReturnValue(final double diff, final int random, int closestupi, int closestdowni,
160         double closestup, double closestdown) {
161         if (closestupi == -1 || closestdowni == -1) {
162             return random;
163         }
164         if (closestupi == closestdowni) {
165             return closestupi;
166         }
167         if (Math.abs(closestdown - diff) > Math.abs(closestup - diff)) {
168             return closestupi;
169         } else {
170             return closestdowni;
171         }
172     }
173 }