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