79 lines
3.2 KiB
MiniZinc
79 lines
3.2 KiB
MiniZinc
% --- Data quantities ---
|
|
enum Patient; % Patients for which samples have been taken
|
|
set of int: Horizon = -5..2; % (Relative) sampling times
|
|
|
|
% --- Data input ---
|
|
float: DLMO_threshold = 13.043;
|
|
array[Patient] of opt float: dlmo;
|
|
array[Patient, Horizon] of opt float: sample;
|
|
|
|
% consistency in terms of STDEV
|
|
array[Patient] of opt float: consistency;
|
|
|
|
test has_dlmo(Patient: pt) = occurs(dlmo[pt]);
|
|
|
|
% --- Derived data ---
|
|
|
|
% For each patient: after which sample could we stop and have found dlmo? (round must then include `critical_test[PT]` and its successor to catch it).
|
|
array[Patient] of var Horizon: critical_sample = [
|
|
if has_dlmo(pt) then
|
|
min([i | i in -5..1 where sample[pt, i] <= DLMO_threshold /\ sample[pt, i+1] >= DLMO_threshold])
|
|
else
|
|
min(Horizon)
|
|
endif
|
|
| pt in Patient];
|
|
|
|
% --- Decisions ---
|
|
% First round:
|
|
var Horizon: first_sample; % When to start sampling on the first round
|
|
var 2..length(Horizon): num_samples; % How many samples to take on the first round
|
|
|
|
% (Assumption: If the levels were to high in all samples during the first round, then we sample `num_samples` ending with the `first_sample`.
|
|
% If the levels were to low in all samples during the first round, then we sample `num_samples` from `first_sample + num_samples`.)
|
|
|
|
% --- Decision Consequences ---
|
|
|
|
% For each patient: will their DLMO be detected on the first round?
|
|
array[Patient] of var bool: first_detected = [
|
|
has_dlmo(pt) /\ (critical_sample[pt] >= first_sample /\ critical_sample[pt] + 1 <= first_sample + (num_samples - 1))
|
|
| pt in Patient
|
|
];
|
|
|
|
|
|
% --- Constraint ---
|
|
|
|
% The DLMO should be detected on the second round (if not detected on the first round)
|
|
constraint forall (pt in Patient where has_dlmo(pt)) (
|
|
first_detected[pt]
|
|
% Before first round
|
|
\/ (critical_sample[pt] >= first_sample - (num_samples - 1) /\ critical_sample[pt] + 1 <= first_sample)
|
|
% After first round
|
|
\/ (critical_sample[pt] >= first_sample + (num_samples - 1) /\ critical_sample[pt] + 1 <= first_sample + (num_samples - 1) + (num_samples - 1))
|
|
);
|
|
|
|
% --- Objective ---
|
|
% solve minimize total_tests;
|
|
% Pareto Front objectives
|
|
var int: total_tests ::output =
|
|
% Number of tests on first round
|
|
(length([pt | pt in Patient where has_dlmo(pt)]) * num_samples)
|
|
% Number of test on second round
|
|
+ (count(pt in Patient) (not first_detected[pt]) * num_samples);
|
|
|
|
var int: total_not_detected ::output = length([pt | pt in Patient where has_dlmo(pt)]) - count(first_detected);
|
|
|
|
% --- Output ---
|
|
|
|
output ["First Round:\n"]
|
|
++ [format(2, i) ++ " " | i in Horizon] ++ ["\n |"]
|
|
++ [if i in fix(first_sample)..fix(first_sample + (num_samples-1) - 1) then "====|" else "----|" endif | i in -5..1]
|
|
++ ["\n\nFirst try (%): \(count(first_detected) / length([pt | pt in Patient where has_dlmo(pt)]) * 100)\n"]
|
|
++ ["\n\nSecond Round:\n"]
|
|
++ [format(2, i) ++ " " | i in Horizon] ++ ["\n |"]
|
|
++ [if i in fix(first_sample-(num_samples-1))..fix(first_sample-1) \/ i in fix(first_sample + (num_samples - 1))..fix(first_sample + (num_samples - 1) + (num_samples - 1) - 1) then "====|" else "----|" endif | i in -5..1]
|
|
++ ["\n\nTotal number of tests = \(total_tests);"]
|
|
|
|
|
|
++ ["\n\n\nfirst_sample = \(first_sample);\n"]
|
|
++ ["num_samples = \(num_samples);\n"]
|