Skip to content

Commit ef9d006

Browse files
author
Haley Clark
committed
Add scoped fairness constraint mechanism.
1 parent ffc1c0f commit ef9d006

7 files changed

Lines changed: 211 additions & 30 deletions

File tree

artifacts/test_files/20260821_DCMA_schedule_template.tsv

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@
1212
"Constraint","max_weekly_remote","5.0","XI = 2",,,,,,,,,,,
1313
"Constraint","max_weekly_remote","5.0","XJ = 2",,,,,,,,,,,
1414
"Constraint","max_weekly_remote","5.0","XK = 2",,,,,,,,,,,
15-
"Constraint","fairness_remote","20.0",,,,,,,,,,,,
16-
"Constraint","fairness_overrides","50.0",,,,,,,,,,,,
15+
"Constraint","fairness_remote","20.0","all of XA and XB and XC and XD and XE",,,,,,,,,,,
16+
"Constraint","fairness_overrides","50.0","all of XA and XB and XC and XD and XE",,,,,,,,,,,
17+
"Constraint","align_with_preferences","50.0","each of XF and XG and XH",,,,,,,,,,,
1718
,,,,,,,,,,,,,,
1819
"Date","XA","XB","XC","XD","XE","XF","XG","XH","XI","XJ","XK",,,
1920
"Mon, Aug 31, 2026","Pref","x","Prim","x","Sec","Pref","Vac","x","Pref","x","Pref",,,

broad_plan.md

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ exclusivity (<non-empty name>)
162162
max_weekly_remote
163163
fairness_remote
164164
fairness_overrides
165+
align_with_preferences
165166
```
166167

167168
Supported expressions are:
@@ -172,19 +173,22 @@ any <positive integer> of <staff> (or <staff>)+
172173
any 1 of <staff> (xor <staff>)+
173174
<non-negative integer>
174175
<staff> = <non-negative integer> (, <staff> = <non-negative integer>)*
176+
all of <staff> (and <staff>)*
177+
each of <staff> (and <staff>)*
175178
```
176179

177180
The standalone integer applies only to `max_consecutive_remote`. The assignment list applies only to
178181
`max_weekly_remote`; the any-of and xor forms apply only to their corresponding coverage/exclusivity
179-
types. The any-of integer may be zero only for `maximum_onsite`; it must be positive for minimum and group
182+
types. The all-of form selects staff for fairness rows, and each-of selects staff for
183+
`align_with_preferences`. For compatibility, an empty fairness expression selects all staff. The any-of
184+
integer may be zero only for `maximum_onsite`; it must be positive for minimum and group
180185
coverage. Integers use ASCII digits only with full-token consumption and overflow checking. Weights use
181186
a locale-independent decimal grammar with optional exponent and full-token consumption.
182187

183188
Whitespace around tokens is flexible. Staff identifiers are looked up case-insensitively but must be
184189
unambiguous. Referencing an unknown staff identifier, repeating one in a list, requesting more staff
185-
than the candidate set contains, supplying an expression to a no-expression constraint, or omitting a
186-
required expression is an error. The exclusivity grammar deliberately requires `any 1`; accepting any
187-
other number would disguise a malformed policy.
190+
than the candidate set contains, or omitting a required expression is an error. The exclusivity grammar
191+
deliberately requires `any 1`; accepting any other number would disguise a malformed policy.
188192

189193
For the initial implementation, staff identifiers must match `[A-Za-z0-9_.-]+`. Validate header labels
190194
against this grammar. This avoids ambiguity with the reserved expression delimiters `or`, `xor`, comma,
@@ -202,6 +206,7 @@ Default status sets are:
202206
| `max_weekly_remote` | `Remote` |
203207
| `fairness_remote` | `Remote` |
204208
| `fairness_overrides` | Not configurable; it specifically detects `Pref` to `Onsite*`. |
209+
| `align_with_preferences` | Not configurable; it detects `x` to `Remote*` and `Pref` to `Onsite*`. |
205210

206211
Thus the sample's minimum and group constraints exclude `Prim` and `Sec`, while exclusivity includes
207212
them. A user can override this per row, for example:
@@ -351,7 +356,8 @@ attribution is deterministic and does not imply that the last day is uniquely re
351356

352357
### 6.6 Remote fairness
353358

354-
Fairness is based only on opportunities controlled by this optimizer. For staff `i`:
359+
Fairness is based only on opportunities controlled by this optimizer and only on staff selected by the
360+
row's all-of expression. For selected staff `i`:
355361

356362
```text
357363
eligible_i = active cells initially equal to x or Pref
@@ -378,7 +384,7 @@ the end user can choose statuses counted by an individual constraint.
378384

379385
### 6.7 Preference override fairness and cost
380386

381-
For staff `i` with at least one input `Pref` on an active day:
387+
For selected staff `i` with at least one input `Pref` on an active day:
382388

383389
```text
384390
pref_i = number of active Pref cells
@@ -407,7 +413,16 @@ with positive weight. Omitting it or assigning zero weight explicitly opts out o
407413
cost, though overrides remain visibly rendered and reported. `OperationDoc` must make this consequence
408414
prominent; there is no hidden, unweighted objective.
409415

410-
### 6.8 No constraints and impossible constraints
416+
### 6.8 Preference alignment
417+
418+
For each staff member selected by the each-of expression, a mutable `x` aligned with preferences is
419+
assigned Onsite and a mutable `Pref` is assigned Remote. The per-staff mismatch ratio is therefore the
420+
fraction of that staff member's active mutable cells assigned in the opposite direction. Staff with no
421+
eligible cells are excluded, and the component is the mean of the included per-staff mismatch ratios.
422+
This gives every selected staff member equal influence regardless of their number of mutable days. The
423+
row is optional and weighted like every other constraint; it accepts no `statuses` policy.
424+
425+
### 6.9 No constraints and impossible constraints
411426

412427
With no positive-weight rows, all assignments have objective zero. The initializer should honor `Pref`
413428
as `Remote` and choose `Remote` for `x`; additional requested outputs may vary any mutable cells,

integration_tests/tests/OptimizeSchedule.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,6 @@ outputs="schedule-outputs.csv"
3131

3232
cmp "${source_before}" "${source_after}"
3333
test "$(grep -c '"Schedule Optimizer Report","Summary","result"' "${outputs}")" -eq 3
34+
test "$(grep -c '"Schedule Optimizer Report","Component"' "${outputs}")" -eq 48
35+
test "$(grep -c '"Schedule Optimizer Report","Component",[^,]*,"align_with_preferences"' "${outputs}")" -eq 3
3436
! grep -E '^"(Mon|Tues|Wed|Thurs|Fri)[^"]*".*,"(x|Pref)"(,|$)' "${outputs}"

prompt.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ You are a senior software engineer with focus in C++, simulation, and medical ph
22

33
DICOMautomaton contains a variety of functionality to support clinical medical physics. One recently added component is an automated scheduling system to ensure there is sufficient onsite operational coverage. The end-user provides a template containing a schedule outline and a list of operational constraints, and the operation optimizes the schedule. Design documents and broad goals are provided in `broad_plan.md` and specific implementation steps were tracked in `tracker.md`. However, there are a few problems that need to be addressed:
44

5-
1. To assist the end-user in evaluating schedules, add a status `Remote*` that is treated the same as `Remote` when evaluating constraints, but is emitted when a `Remote` is assigned to staff only when replacing a `x` cell (i.e., not when it replaces a `Pref` cell).
5+
1. The fairness constraints should accept a list of staff to which the fairness constraint should apply. Accept an input specifier like `all of XA and XB and XC` which applies only to staff `XA`, `XB`, and `XC`.
66

7-
2. Add a `maximum_onsite` constraint that penalizes when the number of `Onsite`/`Onsite*` staff exceed the provided number. An example of this constraint has been added to the template.
7+
2. If any staff are unconstrained on a given day, then currently their preferences are sometimes overridden for no apparent reason. In such situations, it makes sense that mutable days should then be assigned solely according to their preferences (i.e., when input is `Pref` output `Remote` and when input is `x` output `Onsite`); this can be accomplished by adding another constraint `align_with_preferences` which accepts input specifiers like `each of XA and XB and XC` which applies individually to each of staff `XA`, `XB`, and `XC`. The end-user can decide what weight to use.
88

99
Address all issues. Ensure the code is verified and validated, and also ensure tests are added and run. Finally, ensure all added C++ strictly adheres to the C++17 standard. Adhere to local styles and conventions.
1010

0 commit comments

Comments
 (0)