Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

76 irvcomparisonaudit #138

Merged
merged 13 commits into from
Jun 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ public BigDecimal riskMeasurement() {
@Override
public void removeDiscrepancy(final CVRAuditInfo theRecord, final int theType) {
final String contestName = getContestName();
final String prefix = String.format("[riskMeasurement] IRVComparisonAudit ID %d for " +
final String prefix = String.format("[removeDiscrepancy] IRVComparisonAudit ID %d for " +
"contest %s:", id(), contestName);

// Check that the IRVComparisonAudit's assertions have been initialised. This will throw
Expand All @@ -455,8 +455,7 @@ public void removeDiscrepancy(final CVRAuditInfo theRecord, final int theType) {
recordTypeCheck(prefix, theRecord, theType);

try {
LOGGER.debug(
String.format("%s removing discrepancy associated with CVR %d (maximum type %d).",
LOGGER.debug(String.format("%s removing discrepancy associated with CVR %d (maximum type %d).",
prefix, theRecord.cvr().id(), theType));
// Remove the discrepancy associated with the given CVRAuditInfo (CVR/ACVR pair), if one
// exists, in each of the audit's assertions.
Expand All @@ -471,13 +470,21 @@ public void removeDiscrepancy(final CVRAuditInfo theRecord, final int theType) {
if(removed) {
super.removeDiscrepancy(theRecord, theType);
}
else{
// There is an argument that this should actually be a case where an exception should be
// thrown -- where the audit logic is telling the audit to remove discrepancies that have
// not been prior computed and recorded.
LOGGER.warn(String.format("%s no discrepancies removed.", prefix));
}

LOGGER.debug(String.format("%s total number of overstatements (%f), optimistic sample " +
"recalculate needed (%s), estimated sample recalculate needed (%s),", prefix,
getOverstatements(), my_optimistic_recalculate_needed, my_estimated_recalculate_needed));

} catch(Exception e){
final String msg = String.format("%s an error arose in the removal of discrepancies " +
"associated with CVR %d (maximum type %d).", prefix, theRecord.cvr().id(), theType);
"associated with CVR %d (maximum type %d). %s", prefix, theRecord.cvr().id(), theType,
e.getMessage());
LOGGER.error(msg);
throw new RuntimeException(msg);
}
Expand All @@ -494,8 +501,9 @@ public void removeDiscrepancy(final CVRAuditInfo theRecord, final int theType) {
*
* @param theRecord The CVRAuditInfo record that generated the discrepancy.
* @param theType The type of discrepancy to remove.
* @exception IllegalArgumentException if an invalid discrepancy type is specified, or a null
* CVRAuditInfo record is provided.
* @exception IllegalArgumentException if an invalid discrepancy type is specified, a null
* CVRAuditInfo record is provided, or 'theType' is not the maximum discrepancy associated with
* the given record and this audit's assertions.
*/
@Override
public void recordDiscrepancy(final CVRAuditInfo theRecord, final int theType) {
Expand All @@ -511,31 +519,65 @@ public void recordDiscrepancy(final CVRAuditInfo theRecord, final int theType) {
// IllegalArgumentException if they are not.
recordTypeCheck(prefix, theRecord, theType);

LOGGER.debug(String.format("%s recording discrepancies for CVR ID %d, max type %d.", prefix,
theRecord.id(), theType));

// Check that 'theType' is indeed the maximum discrepancy associated with an assertion in
// this audit and the CVR referred to in 'theRecord'. If it is not, or if there are no
// discrepancies associated with the record and an assertion, then an IllegalArgumentException
// will be thrown.
List<Integer> types = new ArrayList<>();
for(Assertion a : assertions){
OptionalInt d = a.getDiscrepancy(theRecord.id());
if(d.isPresent()) {
types.add(d.getAsInt());
}
}
if(types.isEmpty() || max(types) != theType){
final String msg = String.format("%s %d is not the maximum discrepancy type for CVR %d " +
"across assertions.", prefix, theType, theRecord.id());
LOGGER.error(msg);
throw new IllegalArgumentException(msg);
}

// The next check is whether the base classes isCovering(theRecord.id()) method holds. If it
// doesn't, throw an exception. This valid discrepancy is not going to be counted in the
// base class counts (as isCovering()) does not hold, yet there is a discrepancy.
if(!isCovering(theRecord.id())){
final String msg = String.format("%s We have computed a discrepancy for contest %s, CVR %d, " +
"but that CVR is not meant to cover the contest.", prefix, contestName, theRecord.id());
LOGGER.error(msg);
throw new RuntimeException(msg);
}

try {
// Note if we get to this point, then discrepancies are present against the given CVR
// in at least one assertion, with 'theType' being the maximum type of these discrepancies.

// Iterate over the assertions for this audit, check that the CVR in the CVRAuditInfo is
// listed in their discrepancy map, and if so, record it as a discrepancy in its internal
// totals. Note that the CVR may represent a different type of discrepancy from assertion to
// assertion (not necessarily of type 'theType'). The parameter 'theType' will represent the
// maximum discrepancy associated with CVR/ACVR pair and one of this audit's assertions. Note
// that a given CVR/ACVR pair can only be associated with a single discrepancy per assertion.
boolean recorded = false;
// Before we call each assertion's recordDiscrepancy(), we check that 'theType' is actually
// the maximum discrepancy that appears across the assertions for this CVR/ACVR.
for (Assertion a : assertions) {
recorded = recorded || a.recordDiscrepancy(theRecord);
a.recordDiscrepancy(theRecord);
}

// Update the discrepancy tallies in the base ComparisonAudit class, for reporting purposes,
// and the flag for indicating that a sample size recalculation is needed, *if* we did
// record a discrepancy against at least one of this audit's assertions.
if(recorded) {
super.recordDiscrepancy(theRecord, theType);
}
// and the flag for indicating that a sample size recalculation is needed.
super.recordDiscrepancy(theRecord, theType);

LOGGER.debug(String.format("%s total number of overstatements (%f), optimistic sample " +
"recalculate needed (%s), estimated sample recalculate needed (%s),", prefix,
getOverstatements(), my_optimistic_recalculate_needed, my_estimated_recalculate_needed));

} catch(Exception e){
final String msg = String.format("%s an error arose in the recording of discrepancies " +
"associated with CVR %d (maximum type %d).", prefix, theRecord.cvr().id(), theType);
"associated with CVR %d (maximum type %d). %s", prefix, theRecord.cvr().id(), theType,
e.getMessage());
LOGGER.error(msg);
throw new RuntimeException(msg);
}
Expand Down Expand Up @@ -597,4 +639,5 @@ private void recordTypeCheck(final String prefix, final CVRAuditInfo theRecord,
throw new IllegalArgumentException(msg);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,21 @@ public Map<Long,Integer> getCvrDiscrepancy(){
return Collections.unmodifiableMap(cvrDiscrepancy);
}

/**
* Returns the value of the discrepancy, if any, that has been computed against the CVR with
* the given ID, as an OptionalInt. An empty OptionalInt will be returned if no discrepancy
* has been computed against the CVR for this assertion.
* @param cvrID CVR ID
* @return The value of the disrepancy, if one exists, computed against the given CVR for this
* assertion.
*/
public OptionalInt getDiscrepancy(long cvrID){
if(cvrDiscrepancy.containsKey(cvrID)){
return OptionalInt.of(cvrDiscrepancy.get(cvrID));
}
return OptionalInt.empty();
}

/**
* Return a string representation of a subset of this assertion's data. This is used for
* testing purposes.
Expand Down Expand Up @@ -577,7 +592,7 @@ private int scoreAuditedBallot(long cvrID, final CastVoteRecord auditedCVR) {

// Compute the score as per this assertion's score() function, and return the result.
final int acvrScore = score(acvrInfo.get());
LOGGER.info(String.format("%s CVR ID %d, Assertion ID %d, contest %s, audited ballot score is %d.",
LOGGER.debug(String.format("%s CVR ID %d, Assertion ID %d, contest %s, audited ballot score is %d.",
prefix, cvrID, id, contestName, acvrScore));
return acvrScore;
}
Expand Down
Loading
Loading