@Test public void sanityCheckWhenEntireRequestedUpdatesAreAlwaysAppliedUnconditionally() { for (ConditionalWeightUpdater weightUpdate : Arrays.asList( new ConditionalWeightUpdater(1.0, 4, false), new ConditionalWeightUpdater(0.1, 1, false))) { ArrayList<Domain> domainArray = new ArrayList<>(Arrays.asList(d1, d2, d3)); Random rand = new Random(0); for (int i = 0; i < 1000; i++) { Domain randomDomain = domainArray.get(rand.nextInt(domainArray.size())); String randomFeature = "f" + rand.nextInt(10); double randomUpdate = (rand.nextDouble() - 0.5) * 100; assertEquals(randomUpdate, weightUpdate.calcWeightUpdate(randomFeature, randomDomain, randomUpdate), EPSILON); } } }
public double calcWeightUpdate(String featureName, Domain domain, double requestedUpdate) { double unconditionalUpdate = requestedUpdate * unconditionalWeightUpdateFraction; addUpdateToAggregationMap(featureToSumOfAbsUnconditionalUpdatesSoFar, featureName, unconditionalUpdate); SafeMap<Domain, Double> domainToPendingUpdate = featureToDomainToPendingUpdate.safeGet(featureName); if (domainToPendingUpdate == null) { domainToPendingUpdate = new SafeHashMap<>(); featureToDomainToPendingUpdate.put(featureName, domainToPendingUpdate); } Double previousPendingUpdate = domainToPendingUpdate.safeGet(domain); if (previousPendingUpdate == null) previousPendingUpdate = 0.0; double newPendingUpdate = previousPendingUpdate + requestedUpdate; domainToPendingUpdate.put(domain, newPendingUpdate); double result = unconditionalUpdate; if (Math.signum(requestedUpdate) == Math.signum(newPendingUpdate) && domainToPendingUpdate.size() >= domainsNumberRequired) { ArrayList<Double> pendingUpdatesOfAllDomains = domainToPendingUpdate.values().stream() .sorted() .collect(Collectors.toCollection(ArrayList::new)); int indexOfUpdateToApply = requestedUpdate > 0 ? pendingUpdatesOfAllDomains.size() - domainsNumberRequired : domainsNumberRequired - 1; double pendingUpdateToApply = pendingUpdatesOfAllDomains.get(indexOfUpdateToApply); if (Math.signum(requestedUpdate) == Math.signum(pendingUpdateToApply) && Math.abs(pendingUpdateToApply) > Math.abs(unconditionalUpdate)) { result = pendingUpdateToApply; } } domainToPendingUpdate.put(domain, newPendingUpdate - result); double signOfResult = Math.signum(result); double finalResult = result; domainToPendingUpdate.entrySet().stream() .filter(entry->!entry.getKey().equals(domain)) .filter(entry->Math.signum(entry.getValue()) == signOfResult) .forEach(entry->entry.setValue(reduceOrClipToZero(entry.getValue(), finalResult))); List<Domain> domainsToRemove = domainToPendingUpdate.entrySet().stream() .filter(entry->Math.abs(entry.getValue()) < MIN_PENDING_UPDATE_ABS_VALUE_TO_KEEP) .map(Map.Entry::getKey) .collect(Collectors.toList()); for (Domain d : domainsToRemove) domainToPendingUpdate.safeRemove(d); if (domainToPendingUpdate.isEmpty()) featureToDomainToPendingUpdate.safeRemove(featureName); addUpdateToAggregationMap(featureToSumOfAbsUpdatesSoFar, featureName, result); return result; }
ConditionalWeightUpdater { public double calcWeightUpdate(String featureName, Domain domain, double requestedUpdate) { double unconditionalUpdate = requestedUpdate * unconditionalWeightUpdateFraction; addUpdateToAggregationMap(featureToSumOfAbsUnconditionalUpdatesSoFar, featureName, unconditionalUpdate); SafeMap<Domain, Double> domainToPendingUpdate = featureToDomainToPendingUpdate.safeGet(featureName); if (domainToPendingUpdate == null) { domainToPendingUpdate = new SafeHashMap<>(); featureToDomainToPendingUpdate.put(featureName, domainToPendingUpdate); } Double previousPendingUpdate = domainToPendingUpdate.safeGet(domain); if (previousPendingUpdate == null) previousPendingUpdate = 0.0; double newPendingUpdate = previousPendingUpdate + requestedUpdate; domainToPendingUpdate.put(domain, newPendingUpdate); double result = unconditionalUpdate; if (Math.signum(requestedUpdate) == Math.signum(newPendingUpdate) && domainToPendingUpdate.size() >= domainsNumberRequired) { ArrayList<Double> pendingUpdatesOfAllDomains = domainToPendingUpdate.values().stream() .sorted() .collect(Collectors.toCollection(ArrayList::new)); int indexOfUpdateToApply = requestedUpdate > 0 ? pendingUpdatesOfAllDomains.size() - domainsNumberRequired : domainsNumberRequired - 1; double pendingUpdateToApply = pendingUpdatesOfAllDomains.get(indexOfUpdateToApply); if (Math.signum(requestedUpdate) == Math.signum(pendingUpdateToApply) && Math.abs(pendingUpdateToApply) > Math.abs(unconditionalUpdate)) { result = pendingUpdateToApply; } } domainToPendingUpdate.put(domain, newPendingUpdate - result); double signOfResult = Math.signum(result); double finalResult = result; domainToPendingUpdate.entrySet().stream() .filter(entry->!entry.getKey().equals(domain)) .filter(entry->Math.signum(entry.getValue()) == signOfResult) .forEach(entry->entry.setValue(reduceOrClipToZero(entry.getValue(), finalResult))); List<Domain> domainsToRemove = domainToPendingUpdate.entrySet().stream() .filter(entry->Math.abs(entry.getValue()) < MIN_PENDING_UPDATE_ABS_VALUE_TO_KEEP) .map(Map.Entry::getKey) .collect(Collectors.toList()); for (Domain d : domainsToRemove) domainToPendingUpdate.safeRemove(d); if (domainToPendingUpdate.isEmpty()) featureToDomainToPendingUpdate.safeRemove(featureName); addUpdateToAggregationMap(featureToSumOfAbsUpdatesSoFar, featureName, result); return result; } }
ConditionalWeightUpdater { public double calcWeightUpdate(String featureName, Domain domain, double requestedUpdate) { double unconditionalUpdate = requestedUpdate * unconditionalWeightUpdateFraction; addUpdateToAggregationMap(featureToSumOfAbsUnconditionalUpdatesSoFar, featureName, unconditionalUpdate); SafeMap<Domain, Double> domainToPendingUpdate = featureToDomainToPendingUpdate.safeGet(featureName); if (domainToPendingUpdate == null) { domainToPendingUpdate = new SafeHashMap<>(); featureToDomainToPendingUpdate.put(featureName, domainToPendingUpdate); } Double previousPendingUpdate = domainToPendingUpdate.safeGet(domain); if (previousPendingUpdate == null) previousPendingUpdate = 0.0; double newPendingUpdate = previousPendingUpdate + requestedUpdate; domainToPendingUpdate.put(domain, newPendingUpdate); double result = unconditionalUpdate; if (Math.signum(requestedUpdate) == Math.signum(newPendingUpdate) && domainToPendingUpdate.size() >= domainsNumberRequired) { ArrayList<Double> pendingUpdatesOfAllDomains = domainToPendingUpdate.values().stream() .sorted() .collect(Collectors.toCollection(ArrayList::new)); int indexOfUpdateToApply = requestedUpdate > 0 ? pendingUpdatesOfAllDomains.size() - domainsNumberRequired : domainsNumberRequired - 1; double pendingUpdateToApply = pendingUpdatesOfAllDomains.get(indexOfUpdateToApply); if (Math.signum(requestedUpdate) == Math.signum(pendingUpdateToApply) && Math.abs(pendingUpdateToApply) > Math.abs(unconditionalUpdate)) { result = pendingUpdateToApply; } } domainToPendingUpdate.put(domain, newPendingUpdate - result); double signOfResult = Math.signum(result); double finalResult = result; domainToPendingUpdate.entrySet().stream() .filter(entry->!entry.getKey().equals(domain)) .filter(entry->Math.signum(entry.getValue()) == signOfResult) .forEach(entry->entry.setValue(reduceOrClipToZero(entry.getValue(), finalResult))); List<Domain> domainsToRemove = domainToPendingUpdate.entrySet().stream() .filter(entry->Math.abs(entry.getValue()) < MIN_PENDING_UPDATE_ABS_VALUE_TO_KEEP) .map(Map.Entry::getKey) .collect(Collectors.toList()); for (Domain d : domainsToRemove) domainToPendingUpdate.safeRemove(d); if (domainToPendingUpdate.isEmpty()) featureToDomainToPendingUpdate.safeRemove(featureName); addUpdateToAggregationMap(featureToSumOfAbsUpdatesSoFar, featureName, result); return result; } ConditionalWeightUpdater(double unconditionalWeightUpdateFraction, int domainsNumberRequired,
                                    boolean collectAggregatedAnalysisData); }
ConditionalWeightUpdater { public double calcWeightUpdate(String featureName, Domain domain, double requestedUpdate) { double unconditionalUpdate = requestedUpdate * unconditionalWeightUpdateFraction; addUpdateToAggregationMap(featureToSumOfAbsUnconditionalUpdatesSoFar, featureName, unconditionalUpdate); SafeMap<Domain, Double> domainToPendingUpdate = featureToDomainToPendingUpdate.safeGet(featureName); if (domainToPendingUpdate == null) { domainToPendingUpdate = new SafeHashMap<>(); featureToDomainToPendingUpdate.put(featureName, domainToPendingUpdate); } Double previousPendingUpdate = domainToPendingUpdate.safeGet(domain); if (previousPendingUpdate == null) previousPendingUpdate = 0.0; double newPendingUpdate = previousPendingUpdate + requestedUpdate; domainToPendingUpdate.put(domain, newPendingUpdate); double result = unconditionalUpdate; if (Math.signum(requestedUpdate) == Math.signum(newPendingUpdate) && domainToPendingUpdate.size() >= domainsNumberRequired) { ArrayList<Double> pendingUpdatesOfAllDomains = domainToPendingUpdate.values().stream() .sorted() .collect(Collectors.toCollection(ArrayList::new)); int indexOfUpdateToApply = requestedUpdate > 0 ? pendingUpdatesOfAllDomains.size() - domainsNumberRequired : domainsNumberRequired - 1; double pendingUpdateToApply = pendingUpdatesOfAllDomains.get(indexOfUpdateToApply); if (Math.signum(requestedUpdate) == Math.signum(pendingUpdateToApply) && Math.abs(pendingUpdateToApply) > Math.abs(unconditionalUpdate)) { result = pendingUpdateToApply; } } domainToPendingUpdate.put(domain, newPendingUpdate - result); double signOfResult = Math.signum(result); double finalResult = result; domainToPendingUpdate.entrySet().stream() .filter(entry->!entry.getKey().equals(domain)) .filter(entry->Math.signum(entry.getValue()) == signOfResult) .forEach(entry->entry.setValue(reduceOrClipToZero(entry.getValue(), finalResult))); List<Domain> domainsToRemove = domainToPendingUpdate.entrySet().stream() .filter(entry->Math.abs(entry.getValue()) < MIN_PENDING_UPDATE_ABS_VALUE_TO_KEEP) .map(Map.Entry::getKey) .collect(Collectors.toList()); for (Domain d : domainsToRemove) domainToPendingUpdate.safeRemove(d); if (domainToPendingUpdate.isEmpty()) featureToDomainToPendingUpdate.safeRemove(featureName); addUpdateToAggregationMap(featureToSumOfAbsUpdatesSoFar, featureName, result); return result; } ConditionalWeightUpdater(double unconditionalWeightUpdateFraction, int domainsNumberRequired,
                                    boolean collectAggregatedAnalysisData); double calcWeightUpdate(String featureName, Domain domain, double requestedUpdate); String getAggregatedAnalysisDataString(); @Override String toString(); }
ConditionalWeightUpdater { public double calcWeightUpdate(String featureName, Domain domain, double requestedUpdate) { double unconditionalUpdate = requestedUpdate * unconditionalWeightUpdateFraction; addUpdateToAggregationMap(featureToSumOfAbsUnconditionalUpdatesSoFar, featureName, unconditionalUpdate); SafeMap<Domain, Double> domainToPendingUpdate = featureToDomainToPendingUpdate.safeGet(featureName); if (domainToPendingUpdate == null) { domainToPendingUpdate = new SafeHashMap<>(); featureToDomainToPendingUpdate.put(featureName, domainToPendingUpdate); } Double previousPendingUpdate = domainToPendingUpdate.safeGet(domain); if (previousPendingUpdate == null) previousPendingUpdate = 0.0; double newPendingUpdate = previousPendingUpdate + requestedUpdate; domainToPendingUpdate.put(domain, newPendingUpdate); double result = unconditionalUpdate; if (Math.signum(requestedUpdate) == Math.signum(newPendingUpdate) && domainToPendingUpdate.size() >= domainsNumberRequired) { ArrayList<Double> pendingUpdatesOfAllDomains = domainToPendingUpdate.values().stream() .sorted() .collect(Collectors.toCollection(ArrayList::new)); int indexOfUpdateToApply = requestedUpdate > 0 ? pendingUpdatesOfAllDomains.size() - domainsNumberRequired : domainsNumberRequired - 1; double pendingUpdateToApply = pendingUpdatesOfAllDomains.get(indexOfUpdateToApply); if (Math.signum(requestedUpdate) == Math.signum(pendingUpdateToApply) && Math.abs(pendingUpdateToApply) > Math.abs(unconditionalUpdate)) { result = pendingUpdateToApply; } } domainToPendingUpdate.put(domain, newPendingUpdate - result); double signOfResult = Math.signum(result); double finalResult = result; domainToPendingUpdate.entrySet().stream() .filter(entry->!entry.getKey().equals(domain)) .filter(entry->Math.signum(entry.getValue()) == signOfResult) .forEach(entry->entry.setValue(reduceOrClipToZero(entry.getValue(), finalResult))); List<Domain> domainsToRemove = domainToPendingUpdate.entrySet().stream() .filter(entry->Math.abs(entry.getValue()) < MIN_PENDING_UPDATE_ABS_VALUE_TO_KEEP) .map(Map.Entry::getKey) .collect(Collectors.toList()); for (Domain d : domainsToRemove) domainToPendingUpdate.safeRemove(d); if (domainToPendingUpdate.isEmpty()) featureToDomainToPendingUpdate.safeRemove(featureName); addUpdateToAggregationMap(featureToSumOfAbsUpdatesSoFar, featureName, result); return result; } ConditionalWeightUpdater(double unconditionalWeightUpdateFraction, int domainsNumberRequired,
                                    boolean collectAggregatedAnalysisData); double calcWeightUpdate(String featureName, Domain domain, double requestedUpdate); String getAggregatedAnalysisDataString(); @Override String toString();  }