diff --git a/eraser-base/src/main/jastadd/DecisionTree.jrag b/eraser-base/src/main/jastadd/DecisionTree.jrag index f50ca0562a920844e46a838c0f655f97bf804a01..22d94464f86fe8ab7876b4f870e4b32a5eb30521 100644 --- a/eraser-base/src/main/jastadd/DecisionTree.jrag +++ b/eraser-base/src/main/jastadd/DecisionTree.jrag @@ -3,21 +3,21 @@ aspect DecisionTree { // let DecisionTreeLeaf implement Leaf public class DecisionTreeLeaf implements Leaf { } - //--- classify --- - syn DecisionTreeLeaf DecisionTreeRoot.classify() { - return getRootRule().classify(); + //--- internalClassify --- + syn DecisionTreeLeaf DecisionTreeRoot.internalClassify() { + return getRootRule().internalClassify(); } - syn DecisionTreeLeaf DecisionTreeElement.classify(); + syn DecisionTreeLeaf DecisionTreeElement.internalClassify(); - syn DecisionTreeLeaf DecisionTreeRule.classify(); + syn DecisionTreeLeaf DecisionTreeRule.internalClassify(); - syn DecisionTreeLeaf ItemStateCheckRule.classify() { + syn DecisionTreeLeaf ItemStateCheckRule.internalClassify() { boolean chooseLeft = getItemStateCheck().holds(); - return (chooseLeft ? getLeft() : getRight()).classify(); + return (chooseLeft ? getLeft() : getRight()).internalClassify(); } - syn DecisionTreeLeaf DecisionTreeLeaf.classify() = this; + syn DecisionTreeLeaf DecisionTreeLeaf.internalClassify() = this; //--- holds --- syn boolean ItemStateCheck.holds() = holdsFor(getItem()); @@ -47,19 +47,19 @@ aspect DecisionTree { } //--- computePreferences --- - syn List<ItemPreference> DecisionTreeLeaf.computePreferences() { + syn MachineLearningResult DecisionTreeLeaf.computePreferences() { // iterate over preference of this leaf, and all its parents and ancestors - List<ItemPreference> result = new ArrayList<>(); + MachineLearningResult result = new MachineLearningResult(); Set<Item> seenItems = new HashSet<>(); List<DecisionTreeElement> ancestors = ancestors(); for (ItemPreference pref : getPreferenceList()) { - result.add(pref); + result.addItemPreference(pref); seenItems.add(pref.getItem()); } for (DecisionTreeElement ancestor : ancestors) { for (ItemPreference pref : ancestor.getPreferenceList()) { if (!seenItems.contains(pref.getItem())) { - result.add(pref); + result.addItemPreference(pref); seenItems.add(pref.getItem()); } } diff --git a/eraser-base/src/main/jastadd/Item.jrag b/eraser-base/src/main/jastadd/Item.jrag index 0b370142cf57c377775294bb6c758dafa7db036f..97ebec744146ae2b884602bc183b75bb25df7905 100644 --- a/eraser-base/src/main/jastadd/Item.jrag +++ b/eraser-base/src/main/jastadd/Item.jrag @@ -401,7 +401,6 @@ aspect ItemHandling { //--- ItemPreference.apply --- public abstract void ItemPreference.apply(); public void ItemPreferenceColor.apply() { - logger.debug("Apply color preference {} -> {}", getItem().getID(), getPreferredHSB()); getItem().setStateFromColor(getPreferredHSB()); getItem().freeze(); for (Item controller : getItem().getControlledByList()) { @@ -409,8 +408,8 @@ aspect ItemHandling { } getItem().unfreeze(); } + //--- ItemPreference.apply --- public void ItemPreferenceDouble.apply() { - logger.debug("Apply double preference {} -> {}", getItem().getID(), getPreferredValue()); getItem().setStateFromDouble(getPreferredValue()); getItem().freeze(); for (Item controller : getItem().getControlledByList()) { @@ -419,6 +418,14 @@ aspect ItemHandling { getItem().unfreeze(); } + //--- ItemPreference.describe --- + syn String ItemPreference.describe() = getItem().getID() + " -> " + getNewStateAsString(); + + //--- ItemPreference.getNewStateAsString --- + syn String ItemPreference.getNewStateAsString(); + eq ItemPreferenceColor.getNewStateAsString() = getPreferredHSB().toString(); + eq ItemPreferenceDouble.getNewStateAsString() = Double.toString(getPreferredValue()); + // // override Item.init$Children from JastAdd's own ASTNode aspect // refine ASTNode public void Item.init$Children() { // refined(); diff --git a/eraser-base/src/main/jastadd/MachineLearning.jrag b/eraser-base/src/main/jastadd/MachineLearning.jrag index c4e03ccbbf4d803b66ed38b092cbf1772932b2ee..d838c2cba4a6dde215cb9d3afd65f373cb5fc456 100644 --- a/eraser-base/src/main/jastadd/MachineLearning.jrag +++ b/eraser-base/src/main/jastadd/MachineLearning.jrag @@ -8,10 +8,10 @@ aspect MachineLearning { public interface Leaf { String getLabel(); int getActivityIdentifier(); - List<ItemPreference> computePreferences(); + MachineLearningResult computePreferences(); } - syn Leaf InternalMachineLearningModel.classify(); + syn Leaf InternalMachineLearningModel.internalClassify(); //--- currentActivityName --- syn String Root.currentActivityName() = JavaUtils.ifPresentOrElseReturn( @@ -31,8 +31,8 @@ aspect MachineLearning { return (int) ((ItemPreferenceDouble) preferences.get(0)).getPreferredValue(); } - //--- currentPreferences --- - syn List<ItemPreference> Root.currentPreferences() = getMachineLearningRoot().getPreferenceLearning().getDecoder().classify().getPreferences(); +// //--- currentPreferences --- +// syn List<ItemPreference> Root.currentPreferences() = getMachineLearningRoot().getPreferenceLearning().getDecoder().classify().getItemPreferences(); //--- canSetActivity --- syn boolean MachineLearningModel.canSetActivity() = false; @@ -45,7 +45,7 @@ aspect MachineLearning { } //--- DummyMachineLearningModel.classify --- - eq DummyMachineLearningModel.classify() { + eq DummyMachineLearningModel.internalClassify() { if (logger.isInfoEnabled() && getItemList().size() > 0) { logger.info("Dummy classification of {}, values of connected items: {}", mlKind(), @@ -167,6 +167,43 @@ aspect MachineLearning { return this.decoder; } + //--- classify --- + public MachineLearningResult MachineLearningModel.classify() { + MachineLearningResult result = getDecoder().classify(); + setLastPreference(result); + return result; + } + + //--- equals --- + public boolean MachineLearningResult.equals(Object other) { + if (!(other instanceof MachineLearningResult)) { + return false; + } + MachineLearningResult otherResult = (MachineLearningResult) other; + if (getNumItemPreference() != otherResult.getNumItemPreference()) { + return false; + } + for (int i = 0; i < getNumItemPreference(); i++) { + if (!getItemPreference(i).equals(otherResult.getItemPreference(i))) { + return false; + } + } + return true; + } + + public abstract boolean ItemPreference.equals(Object other); + public boolean ItemPreferenceDouble.equals(Object other) { + if (!(other instanceof ItemPreferenceDouble)) { + return false; + } + return getItem() == ((ItemPreferenceDouble) other).getItem() && getPreferredValue() == ((ItemPreferenceDouble) other).getPreferredValue(); + } + public boolean ItemPreferenceColor.equals(Object other) { + if (!(other instanceof ItemPreferenceColor)) { + return false; + } + return getItem() == ((ItemPreferenceColor) other).getItem() && getPreferredHSB() == ((ItemPreferenceColor) other).getPreferredHSB(); + } } aspect ChangeEvents { @@ -177,19 +214,30 @@ aspect ChangeEvents { RecognitionEvent result = new RecognitionEvent(); result.initChangeEvent(); for (Item relevantItem : modelOfRecognition.getRelevantItems()) { - result.addChangedItem(ChangedItem.newFromItem(relevantItem)); + result.addRelevantItem(ChangedItem.newFrom(relevantItem)); + } + for (ItemPreference preference : modelOfRecognition.getLastPreference().getItemPreferences()) { + result.addChangedItem(ChangedItem.newFrom(preference)); } return result; } - //--- newFromItem --- - public static ChangedItem ChangedItem.newFromItem(Item source) { + //--- newFrom Item --- + public static ChangedItem ChangedItem.newFrom(Item source) { ChangedItem result = new ChangedItem(); result.setItem(source); result.setNewStateAsString(source.getStateAsString()); return result; } + //--- newFrom ItemPreference --- + public static ChangedItem ChangedItem.newFrom(ItemPreference update) { + ChangedItem result = new ChangedItem(); + result.setItem(update.getItem()); + result.setNewStateAsString(update.getNewStateAsString()); + return result; + } + //--- initChangeEvent --- protected void ChangeEvent.initChangeEvent() { this.setCreated(Instant.now()); diff --git a/eraser-base/src/main/jastadd/MachineLearning.relast b/eraser-base/src/main/jastadd/MachineLearning.relast index 906d344b8f123fca5d617b174078dcfa56f7f4c8..c53ab3cc3394309afd18287d6c575497aa80933b 100644 --- a/eraser-base/src/main/jastadd/MachineLearning.relast +++ b/eraser-base/src/main/jastadd/MachineLearning.relast @@ -10,10 +10,11 @@ rel ChangedItem.Item -> Item ; RecognitionEvent : ChangeEvent ; rel RecognitionEvent.Activity -> Activity ; +rel RecognitionEvent.RelevantItem* -> ChangedItem ; ManualChangeEvent : ChangeEvent ; -abstract MachineLearningModel ::= ; +abstract MachineLearningModel ::= LastPreference:MachineLearningResult ; rel MachineLearningModel.RelevantItem* <-> Item.RelevantInMachineLearningModel* ; rel MachineLearningModel.TargetItem* <-> Item.TargetInMachineLearningModel* ; @@ -21,6 +22,8 @@ ExternalMachineLearningModel : MachineLearningModel ; abstract InternalMachineLearningModel : MachineLearningModel ::= <OutputApplication:DoubleDoubleFunction> ; +MachineLearningResult ::= ItemPreference* ; + abstract ItemPreference ::= ; rel ItemPreference.Item -> Item ; diff --git a/eraser-base/src/main/jastadd/NeuralNetwork.jrag b/eraser-base/src/main/jastadd/NeuralNetwork.jrag index 999031dd8ad2260fff1db1cdfa2ec69579a706a2..c9035025c77943cabf4f93fead3d9f56ecffea2b 100644 --- a/eraser-base/src/main/jastadd/NeuralNetwork.jrag +++ b/eraser-base/src/main/jastadd/NeuralNetwork.jrag @@ -18,17 +18,19 @@ aspect NeuralNetwork { public int getActivityIdentifier() { return (int) number; } - public List<ItemPreference> computePreferences() { - return Collections.singletonList(new ItemPreferenceDouble(affectedItem, number)); + public MachineLearningResult computePreferences() { + MachineLearningResult result = new MachineLearningResult(); + result.addItemPreference(new ItemPreferenceDouble(affectedItem, number)); + return result; } } - //--- classify --- - syn DoubleNumber NeuralNetworkRoot.classify() { - return getOutputLayer().classify(); + //--- internalClassify --- + syn DoubleNumber NeuralNetworkRoot.internalClassify() { + return getOutputLayer().internalClassify(); } - syn DoubleNumber OutputLayer.classify() { + syn DoubleNumber OutputLayer.internalClassify() { double[] inputs = new double[getNumOutputNeuron()]; for (int i = 0; i < getNumOutputNeuron(); ++i) { OutputNeuron n = getOutputNeuron(i); diff --git a/eraser-base/src/main/java/de/tudresden/inf/st/eraser/jastadd/model/InternalMachineLearningHandler.java b/eraser-base/src/main/java/de/tudresden/inf/st/eraser/jastadd/model/InternalMachineLearningHandler.java index 75d2a1d8cfc28c0293f1d55cc4e6714a6e37818a..a04db3e06454e47ecccb63b7231b0c11c13ea1d6 100644 --- a/eraser-base/src/main/java/de/tudresden/inf/st/eraser/jastadd/model/InternalMachineLearningHandler.java +++ b/eraser-base/src/main/java/de/tudresden/inf/st/eraser/jastadd/model/InternalMachineLearningHandler.java @@ -48,8 +48,7 @@ public class InternalMachineLearningHandler implements MachineLearningEncoder, M @Override public MachineLearningResult classify() { - List<ItemPreference> preferences = model.classify().computePreferences(); - return new InternalMachineLearningResult(preferences); + return model.internalClassify().computePreferences(); } @Override diff --git a/eraser-base/src/main/java/de/tudresden/inf/st/eraser/jastadd/model/InternalMachineLearningResult.java b/eraser-base/src/main/java/de/tudresden/inf/st/eraser/jastadd/model/InternalMachineLearningResult.java deleted file mode 100644 index 087020b383fee89ea839b2056e22072af799a9f3..0000000000000000000000000000000000000000 --- a/eraser-base/src/main/java/de/tudresden/inf/st/eraser/jastadd/model/InternalMachineLearningResult.java +++ /dev/null @@ -1,21 +0,0 @@ -package de.tudresden.inf.st.eraser.jastadd.model; - -import java.util.List; - -/** - * Result of a classification returned by an internally held machine learning model. - * - * @author rschoene - Initial contribution - */ -public class InternalMachineLearningResult implements MachineLearningResult { - private final List<ItemPreference> preferences; - - InternalMachineLearningResult(List<ItemPreference> preferences) { - this.preferences = preferences; - } - - @Override - public List<ItemPreference> getPreferences() { - return this.preferences; - } -} diff --git a/eraser-base/src/main/java/de/tudresden/inf/st/eraser/jastadd/model/MachineLearningResult.java b/eraser-base/src/main/java/de/tudresden/inf/st/eraser/jastadd/model/MachineLearningResult.java deleted file mode 100644 index eebd16d3679c1531cb02d1ba1abd0c1610303668..0000000000000000000000000000000000000000 --- a/eraser-base/src/main/java/de/tudresden/inf/st/eraser/jastadd/model/MachineLearningResult.java +++ /dev/null @@ -1,25 +0,0 @@ -package de.tudresden.inf.st.eraser.jastadd.model; - -import de.tudresden.inf.st.eraser.jastadd.model.ItemPreference; - -import java.util.List; - -/** - * Representation of a classification result using a MachineLearningModel. - * - * @author rschoene - Initial contribution - */ -@SuppressWarnings("unused") -public interface MachineLearningResult { - - // Object rawClass(); - - // double rawConfidence(); - - // can be used for both activity and preferences - /** - * Get the result as a list of item preferences, i.e., new states to be set for those items. - * @return the classification result as item preferences - */ - List<ItemPreference> getPreferences(); -} diff --git a/eraser-base/src/test/java/de/tudresden/inf/st/eraser/DecisionTreeTest.java b/eraser-base/src/test/java/de/tudresden/inf/st/eraser/DecisionTreeTest.java index fa93e0691d782030d2e45c385f9327a57c9e1ae4..9ffee83b3a16695fd392efa6e123e7d9754a2fe1 100644 --- a/eraser-base/src/test/java/de/tudresden/inf/st/eraser/DecisionTreeTest.java +++ b/eraser-base/src/test/java/de/tudresden/inf/st/eraser/DecisionTreeTest.java @@ -25,17 +25,17 @@ public class DecisionTreeTest { dtroot.setRootRule(newRule(isLessThanFour, isFourOrGreater, "check item1", check)); // current value is four, so return value should be "four or greater" - Leaf leaf = dtroot.classify(); + Leaf leaf = dtroot.internalClassify(); Assert.assertEquals(isFourOrGreater, leaf); // change value to 5, so return value should still be "four or greater" mai.item.setState(5); - leaf = dtroot.classify(); + leaf = dtroot.internalClassify(); Assert.assertEquals(isFourOrGreater, leaf); // change value to 2, so return value should now be "less than four" mai.item.setState(2); - leaf = dtroot.classify(); + leaf = dtroot.internalClassify(); Assert.assertEquals(isLessThanFour, leaf); } @@ -64,17 +64,17 @@ public class DecisionTreeTest { dtroot.setRootRule(newRule(rule25, rule75, "50-item1", check50)); // current value is 20, so return value should be "less than 25" - Leaf leaf = dtroot.classify(); + Leaf leaf = dtroot.internalClassify(); Assert.assertEquals(isLessThan25, leaf); // change value to 25, so return value should still be "25 or greater" mai.item.setState(25); - leaf = dtroot.classify(); + leaf = dtroot.internalClassify(); Assert.assertEquals(is25OrGreater, leaf); // change value to 100, so return value should now be "greater than 75" mai.item.setState(100); - leaf = dtroot.classify(); + leaf = dtroot.internalClassify(); Assert.assertEquals(is75OrGreater, leaf); } @@ -139,7 +139,7 @@ public class DecisionTreeTest { for (TestResult result : testResults) { mai.item.setState(Math.round(result.value)); - Leaf leaf = dtroot.classify(); + Leaf leaf = dtroot.internalClassify(); Assert.assertEquals(result.chooseLeft ? leaf : right, leaf); } } diff --git a/eraser-base/src/test/java/de/tudresden/inf/st/eraser/NeuralNetworkTest.java b/eraser-base/src/test/java/de/tudresden/inf/st/eraser/NeuralNetworkTest.java index 0eb593fd0fc6c3cb3401f315afe33d550e4b3658..d4549f59ed2e50d1c2e0db2d3e0b3dd5303e8ed0 100644 --- a/eraser-base/src/test/java/de/tudresden/inf/st/eraser/NeuralNetworkTest.java +++ b/eraser-base/src/test/java/de/tudresden/inf/st/eraser/NeuralNetworkTest.java @@ -50,17 +50,17 @@ public class NeuralNetworkTest { neuralNetworkRoot.setOutputLayer(outputLayer); // Current value is 1, so return value is 1 * 4 * 0.6 = 2.4, 1 * 4 * 0.4 = 1.6, both are less than 4. so 0. - Leaf leaf = neuralNetworkRoot.classify(); + Leaf leaf = neuralNetworkRoot.internalClassify(); assertLeafEqual(0, leaf); // Current value is 2, so return value is 2 * 4 * 0.6 = 4.8, 2 * 4 * 0.4 = 3.2, first is less than 4. so 1. mai.item.setState(2); - leaf = neuralNetworkRoot.classify(); + leaf = neuralNetworkRoot.internalClassify(); assertLeafEqual(1, leaf); // Current value is 5, so return value is 5 * 4 * 0.6 = 12, 5 * 4 * 0.4 = 8, both are greater than 4. so 3. mai.item.setState(5); - leaf = neuralNetworkRoot.classify(); + leaf = neuralNetworkRoot.internalClassify(); assertLeafEqual(3, leaf); } diff --git a/feedbackloop.analyze/src/main/java/de/tudresden/inf/st/eraser/feedbackloop/analyze/AnalyzeImpl.java b/feedbackloop.analyze/src/main/java/de/tudresden/inf/st/eraser/feedbackloop/analyze/AnalyzeImpl.java index 5e9f8cfb5476ae25219cebd704e17e2e2b78cb9d..b3d3a3d4b61c23cccd18a6939920a473a614d1f7 100644 --- a/feedbackloop.analyze/src/main/java/de/tudresden/inf/st/eraser/feedbackloop/analyze/AnalyzeImpl.java +++ b/feedbackloop.analyze/src/main/java/de/tudresden/inf/st/eraser/feedbackloop/analyze/AnalyzeImpl.java @@ -3,6 +3,8 @@ package de.tudresden.inf.st.eraser.feedbackloop.analyze; import de.tudresden.inf.st.eraser.feedbackloop.api.Analyze; import de.tudresden.inf.st.eraser.feedbackloop.api.Plan; import de.tudresden.inf.st.eraser.jastadd.model.Activity; +import de.tudresden.inf.st.eraser.jastadd.model.ItemPreference; +import de.tudresden.inf.st.eraser.jastadd.model.MachineLearningResult; import de.tudresden.inf.st.eraser.jastadd.model.Root; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -17,10 +19,12 @@ public class AnalyzeImpl implements Analyze { private Root knowledgeBase; private Plan plan; private Activity mostRecentActivity; + private MachineLearningResult mostRecentPreferences; private Logger logger = LogManager.getLogger(AnalyzeImpl.class); public AnalyzeImpl() { this.mostRecentActivity = null; + this.mostRecentPreferences = null; } @Override @@ -40,17 +44,32 @@ public class AnalyzeImpl implements Analyze { @Override public void analyzeLatestChanges() { + MachineLearningResult recognitionResult = knowledgeBase.getMachineLearningRoot().getActivityRecognition().getDecoder().classify(); + recognitionResult.getItemPreferences().forEach(ItemPreference::apply); knowledgeBase.currentActivity().ifPresent(activity -> { + MachineLearningResult newMLResult = knowledgeBase.getMachineLearningRoot().getPreferenceLearning().classify(); + // check if activity has changed if (!activity.equals(mostRecentActivity)) { // new! inform plan! logger.info("Found new activity '{}'", activity.getLabel()); - mostRecentActivity = activity; try { informPlan(activity); } catch (Exception e) { logger.catching(e); } + } else { + // if no change, also check, if preferences have changed + if (!newMLResult.equals(mostRecentPreferences)) { + logger.info("Preferences have changed for same activity '{}'", activity.getLabel()); + try { + informPlan(activity); + } catch (Exception e) { + logger.catching(e); + } + } } + mostRecentActivity = activity; + mostRecentPreferences = newMLResult; }); } } diff --git a/feedbackloop.api/src/main/java/de/tudresden/inf/st/eraser/feedbackloop/api/Execute.java b/feedbackloop.api/src/main/java/de/tudresden/inf/st/eraser/feedbackloop/api/Execute.java index c7ecb57d535b832d59d76d9840813a6d8a72ca2d..0592bdcedb4980e4e66e357690c5312f1c92202e 100644 --- a/feedbackloop.api/src/main/java/de/tudresden/inf/st/eraser/feedbackloop/api/Execute.java +++ b/feedbackloop.api/src/main/java/de/tudresden/inf/st/eraser/feedbackloop/api/Execute.java @@ -22,7 +22,7 @@ public interface Execute { void setKnowledgeBase(Root knowledgeBase); /** - * <b>Deprecated</b>: Use {@link #updateItems(List)} instead. + * <b>Deprecated</b>: Use {@link #updateItems(Iterable)} instead. * @param brightnessAndRgbForItems Map, keys are item names, values are RGB and brightness values */ @Deprecated @@ -32,5 +32,5 @@ public interface Execute { * Updates items according to given preferences * @param preferences tuples containing item and its new HSB value */ - void updateItems(List<ItemPreference> preferences); + void updateItems(Iterable<ItemPreference> preferences); } diff --git a/feedbackloop.api/src/main/java/de/tudresden/inf/st/eraser/feedbackloop/api/Plan.java b/feedbackloop.api/src/main/java/de/tudresden/inf/st/eraser/feedbackloop/api/Plan.java index 8c237d06d64684d6386e1bc8de5a73146d7a1485..eae690c1390b8f14dd776c9fb58d0e5343b692a6 100644 --- a/feedbackloop.api/src/main/java/de/tudresden/inf/st/eraser/feedbackloop/api/Plan.java +++ b/feedbackloop.api/src/main/java/de/tudresden/inf/st/eraser/feedbackloop/api/Plan.java @@ -21,7 +21,7 @@ public interface Plan { void planToMatchPreferences(Activity activity); - default void informExecute(List<ItemPreference> preferences) { + default void informExecute(Iterable<ItemPreference> preferences) { getExecute().updateItems(preferences); } } diff --git a/feedbackloop.execute/src/main/java/de/tudresden/inf/st/eraser/feedbackloop/execute/ExecuteImpl.java b/feedbackloop.execute/src/main/java/de/tudresden/inf/st/eraser/feedbackloop/execute/ExecuteImpl.java index 489956ca9807110328b740b77fe4412e0f00fda3..90baaff24e042423b4abf8b4958223bfe63f6086 100644 --- a/feedbackloop.execute/src/main/java/de/tudresden/inf/st/eraser/feedbackloop/execute/ExecuteImpl.java +++ b/feedbackloop.execute/src/main/java/de/tudresden/inf/st/eraser/feedbackloop/execute/ExecuteImpl.java @@ -54,7 +54,7 @@ public class ExecuteImpl implements Execute { } @Override - public void updateItems(List<ItemPreference> preferences) { + public void updateItems(Iterable<ItemPreference> preferences) { for (ItemPreference preference : preferences) { preference.apply(); } diff --git a/feedbackloop.learner/src/main/java/de/tudresden/inf/st/eraser/feedbackloop/learner/Main.java b/feedbackloop.learner/src/main/java/de/tudresden/inf/st/eraser/feedbackloop/learner/Main.java index 0d4983c47112462224aa5595942aa23cf738ad8b..d1d56afaa351eecb9c7b79464a7c5ad25e648e71 100644 --- a/feedbackloop.learner/src/main/java/de/tudresden/inf/st/eraser/feedbackloop/learner/Main.java +++ b/feedbackloop.learner/src/main/java/de/tudresden/inf/st/eraser/feedbackloop/learner/Main.java @@ -226,7 +226,7 @@ public class Main { List<String> output = new ArrayList<>(); Function<DoubleNumber, String> leafToString = classification -> Double.toString(classification.number); - Function<NeuralNetworkRoot, DoubleNumber> classify = NeuralNetworkRoot::classify; + Function<NeuralNetworkRoot, DoubleNumber> classify = NeuralNetworkRoot::internalClassify; DoubleNumber classification = classify.apply(nn); output.add(leafToString.apply(classification)); System.out.println(output); diff --git a/feedbackloop.learner_backup/src/main/java/de/tudresden/inf/st/eraser/feedbackloop.learner_backup/MachineLearningImpl.java b/feedbackloop.learner_backup/src/main/java/de/tudresden/inf/st/eraser/feedbackloop.learner_backup/MachineLearningImpl.java index f536026f95b47dab38c1acb695284bd31b5728ea..158ebd642bcddbe8c511a9e35714423c6cef1093 100644 --- a/feedbackloop.learner_backup/src/main/java/de/tudresden/inf/st/eraser/feedbackloop.learner_backup/MachineLearningImpl.java +++ b/feedbackloop.learner_backup/src/main/java/de/tudresden/inf/st/eraser/feedbackloop.learner_backup/MachineLearningImpl.java @@ -160,21 +160,27 @@ public class MachineLearningImpl implements MachineLearningDecoder, MachineLearn @Override public MachineLearningResult classify() { + MachineLearningResult result = new MachineLearningResult(); switch (this.goal) { case GOAL_ACTIVITY_PHONE_AND_WATCH: String activityStringValue = activity_result; + if (activityStringValue == null) { + return result; + } Item activityItem = resolve(this.root.getSmartHomeEntityModel(), "activity"); //activityItem.setStateFromString(activityStringValue); // FIXME how to translate activityStringValue to a number? or should activity item state better be a String? - for (int i=0; i< activites.length;i++){ - if(activites[i].equals(activityStringValue)){ - activityItem.setStateFromString(String.valueOf(i)); - ItemPreference classifiedActivity = new ItemPreferenceDouble(activityItem,i); - return new MachineLearningResultImpl(classifiedActivity); + ItemPreference classifiedActivity = null; + for (Activity activity : this.root.getMachineLearningRoot().getActivityList()) { + if (activity.getLabel().equals(activityStringValue)) { + classifiedActivity = new ItemPreferenceDouble(activityItem, activity.getIdentifier()); } logger.debug("Classify would return activity: {}", activityStringValue); } - + if (classifiedActivity != null) { + result.addItemPreference(classifiedActivity); + } + return result; case GOAL_PREFERENCE_BRIGHTNESS_IRIS: // String[] preference = {result[1], result[2]}; // FIXME what is the meaning of result[1] and result[2] @@ -185,11 +191,11 @@ public class MachineLearningImpl implements MachineLearningDecoder, MachineLearn color = Math.round(Float.valueOf(preference_result[0])); brightness = Math.round(Float.valueOf(preference_result[1])); } - ItemPreference classifiedPreference = new ItemPreferenceColor(iris1, TupleHSB.of(color, 100, brightness)); - return new MachineLearningResultImpl(classifiedPreference); + result.addItemPreference(new ItemPreferenceColor(iris1, TupleHSB.of(color, 100, brightness))); + return result; default: logger.error("Unknown goal value ({}) set in classify", this.goal); - return new EmptyMachineLearningResult(); + return result; } } @@ -202,12 +208,4 @@ public class MachineLearningImpl implements MachineLearningDecoder, MachineLearn learner.preference_train(filenameOfCsv); } - class EmptyMachineLearningResult implements MachineLearningResult { - - @Override - public List<ItemPreference> getPreferences() { - return Collections.emptyList(); - } - } - } diff --git a/feedbackloop.learner_backup/src/main/java/de/tudresden/inf/st/eraser/feedbackloop.learner_backup/MachineLearningResultImpl.java b/feedbackloop.learner_backup/src/main/java/de/tudresden/inf/st/eraser/feedbackloop.learner_backup/MachineLearningResultImpl.java deleted file mode 100644 index 61d483a566255d51ce424d23adb014df1eec8109..0000000000000000000000000000000000000000 --- a/feedbackloop.learner_backup/src/main/java/de/tudresden/inf/st/eraser/feedbackloop.learner_backup/MachineLearningResultImpl.java +++ /dev/null @@ -1,26 +0,0 @@ -package de.tudresden.inf.st.eraser.feedbackloop.learner_backup; - -import de.tudresden.inf.st.eraser.jastadd.model.ItemPreference; -import de.tudresden.inf.st.eraser.jastadd.model.MachineLearningResult; - -import java.util.Collections; -import java.util.List; - -/** - * TODO: Add description. - * - * @author rschoene - Initial contribution - */ -public class MachineLearningResultImpl implements MachineLearningResult { - - private final ItemPreference preference; - - MachineLearningResultImpl(ItemPreference preference) { - this.preference = preference; - } - - @Override - public List<ItemPreference> getPreferences() { - return Collections.singletonList(preference); - } -} diff --git a/feedbackloop.plan/src/main/java/de/tudresden/inf/st/eraser/feedbackloop/plan/PlanImpl.java b/feedbackloop.plan/src/main/java/de/tudresden/inf/st/eraser/feedbackloop/plan/PlanImpl.java index e7f256b2928dfbbdd35e48b2dbf5b1797eee727d..4647c26ba6d54107c014e90cd34afdb8e733d1fb 100644 --- a/feedbackloop.plan/src/main/java/de/tudresden/inf/st/eraser/feedbackloop/plan/PlanImpl.java +++ b/feedbackloop.plan/src/main/java/de/tudresden/inf/st/eraser/feedbackloop/plan/PlanImpl.java @@ -37,14 +37,18 @@ public class PlanImpl implements Plan { @Override public void planToMatchPreferences(Activity activity) { logger.info("Plan got new activity [{}]: {}", activity.getIdentifier(), activity.getLabel()); - List<ItemPreference> preferences = knowledgeBase.currentPreferences(); - knowledgeBase.getMachineLearningRoot().addChangeEvent(createRecognitionEvent(activity)); - informExecute(preferences); + MachineLearningResult mlResult = knowledgeBase.getMachineLearningRoot().getPreferenceLearning().getLastPreference(); + knowledgeBase.getMachineLearningRoot().addChangeEvent(createRecognitionEvent(activity, mlResult.getItemPreferences())); + knowledgeBase.getMachineLearningRoot().getChangeEventList(); + informExecute(mlResult.getItemPreferences()); } - private ChangeEvent createRecognitionEvent(Activity activity) { + private ChangeEvent createRecognitionEvent(Activity activity, Iterable<ItemPreference> preferences) { RecognitionEvent result = RecognitionEvent.createRecognitionEvent(knowledgeBase.getMachineLearningRoot().getActivityRecognition()); result.setActivity(activity); + for (ItemPreference preference : preferences) { + result.addChangedItem(ChangedItem.newFrom(preference)); + } return result; } } diff --git a/ml_test/src/main/java/de/tudresden/inf/st/eraser/ml_test/Main.java b/ml_test/src/main/java/de/tudresden/inf/st/eraser/ml_test/Main.java index 75fd6d205d96cfe43bdd27176c21ac7e7155473a..535321b63883c8f37cb122b787a6ba3cb70b0fb7 100644 --- a/ml_test/src/main/java/de/tudresden/inf/st/eraser/ml_test/Main.java +++ b/ml_test/src/main/java/de/tudresden/inf/st/eraser/ml_test/Main.java @@ -158,7 +158,7 @@ public class Main { hiddenNeuron.connectTo(output, 1.0/pr.hiddenNeurons.length); } - classifyTimed(pr.nn, NeuralNetworkRoot::classify, + classifyTimed(pr.nn, NeuralNetworkRoot::internalClassify, classification -> Double.toString(classification.number)); } @@ -183,7 +183,7 @@ public class Main { } } - classifyTimed(pr.nn, NeuralNetworkRoot::classify, + classifyTimed(pr.nn, NeuralNetworkRoot::internalClassify, classification -> Double.toHexString(classification.number)); // long before = System.nanoTime();