Skip to content
This repository has been archived by the owner on Apr 14, 2023. It is now read-only.

#1704/#1705 weighted decision selection #1718

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

sl-slaing
Copy link
Contributor

Description

When a profile contains a decision (if constraint) which refers to weighted set values, currently the generator doesn't take the weightings into account.

Changes

  • Update the decision selection logic to apportion a weighting to each branch of a decision
  • Use this weighting when randomly selecting a value for the decision, so that values are projected as per their weightings

Additional notes

Issue

Resolves #1704
Resolves #1705

Comment on lines 103 to 139
double applicabilityOfThisOption = option.getAtomicConstraints().stream()
.mapToDouble(optionAtomicConstraint -> rootNode.getAtomicConstraints().stream()
.filter(rootAtomicConstraint -> rootAtomicConstraint.getField().equals(optionAtomicConstraint.getField()))
.filter(rootAtomicConstraint -> rootAtomicConstraint instanceof InSetConstraint)
.map(rootAtomicConstraint -> (InSetConstraint)rootAtomicConstraint)
.findFirst()
.map(matchingRootAtomicConstraint -> {
double totalWeighting = matchingRootAtomicConstraint.legalValues.stream()
.mapToDouble(InSetRecord::getWeightValueOrDefault).sum();

double relevantWeighting = matchingRootAtomicConstraint.legalValues.stream()
.filter(legalValue -> optionAtomicConstraint.toFieldSpec().canCombineWithLegalValue(legalValue.getElement()))
.mapToDouble(InSetRecord::getWeightValueOrDefault).sum();

return relevantWeighting / totalWeighting;
})
.orElse(1d))
.sum();

if (applicabilityOfThisOption > 1){
double applicabilityFraction = applicabilityOfThisOption - (int) applicabilityOfThisOption;
applicabilityOfThisOption = applicabilityFraction == 0
? 1
: applicabilityFraction;
}

if (applicabilityOfThisOption == 0){
return new WeightedElement<>(
Merged.contradictory(),
1
);
}

return new WeightedElement<>(
treePruner.pruneConstraintNode(constraintNode, getFields(option)),
applicabilityOfThisOption
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is very complicated. Possibly needs refactored into a few well named methods. Also as its complicated we might need a comment explaining what this thing is doing so someone who isn't familiar with this area can understand it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added some comments to the code and refactored some of the calculations into functions, the complexity is somewhat unavoidable i think.

Comment on lines +109 to +112
.mapToDouble(optionAtomicConstraint -> rootNode.getAtomicConstraints().stream()
.filter(rootAtomicConstraint -> rootAtomicConstraint.getField().equals(optionAtomicConstraint.getField()))
.filter(rootAtomicConstraint -> rootAtomicConstraint instanceof InSetConstraint)
.map(rootAtomicConstraint -> (InSetConstraint)rootAtomicConstraint)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe make this more modular and change this to:
mapToDouble(optionAtomicConstraint -> findMatchingInSetConstraints(optionAtomicConstraint.getField(), rootNode.getAtomicConstraints())

and then define the method:
Stream findMatchingInSetConstraints(fieldtoMatch, atomicConstraints

Comment on lines +115 to +118
double totalWeighting = getWeightOfAllLegalValues(matchingRootAtomicConstraint);
double relevantWeighting = getWeightOfAllPermittedLegalValues(matchingRootAtomicConstraint, optionAtomicConstraint);

return relevantWeighting / totalWeighting;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe encapsulate this in a calculateApplicability method

lastRowSpec = weightedRowSpec;
}

return lastRowSpec.element();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we protect against a nullptr here in case lastRowSpec is null (eg rowSpecCache is empty could cause this). In which case return ??? (ideally some kind of 'empty' row spec rather than null - depends what calling code assumes). Or should we throw an exception as never expect this to be called with empty rowSepcCache.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
2 participants