LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
fromMarginalBounds.m
1function space = fromMarginalBounds(sn, ind, lb, ub, cap, options)
2% SPACE = FROMMARGINALBOUNDS(QN, IND, LB, UB, CAP, OPTIONS)
3
4% Copyright (c) 2012-2026, Imperial College London
5% All rights reserved.
6
7if nargin<6 %~exist('options','var')
8 options = Solver.defaultOptions;
9end
10
11% ind: node index
12ist = sn.nodeToStation(ind);
13%isf = sn.nodeToStateful(ind);
14
15% returns all states lb<= x<= ub, where ub/lb are either a scalar (total
16% number of jobs) or a vector (per-class number of jobs)
17space = [];
18if isempty(lb), lb=0*ub; end
19R = sn.nclasses;
20if length(lb) == 1, isVectorLB =0; else, isVectorLB = 1; end
21if length(ub) == 1, isVectorUB =0; else, isVectorUB = 1; end
22if isVectorLB~=isVectorUB, line_error(mfilename,'Bounds must either be both vectors or both scalars'); end
23
24if isVectorUB && isVectorLB
25 nmax = State.fromMarginal(sn, ind, ub, options);
26 if isempty(nmax)
27 nmax = State.fromMarginal(sn, ind, ub, options);
28 end
29 n = pprodcon(lb,ub);
30 while n ~= -1
31 % Cooperative wall-clock budget checkpoint (options.timeout)
32 if lineTimeoutExceeded(options)
33 line_error(mfilename,'State space generation exceeded the wall-clock time budget (options.timeout=%gs).', options.timeout);
34 end
35 state = State.fromMarginal(sn, ind, n, options);
36 space(end+1:end+size(state,1),(size(nmax,2)-size(state,2)+1):size(nmax,2)) = state;
37 n = pprodcon(n,lb,ub);
38 end
39else % both scalar
40 if ub >= lb
41 for bi=ub:-1:lb % reverse order so that largest vector determines size(space,2)
42 nset = multichoose(R,bi);
43 for j=1:size(nset,1)
44 % Cooperative wall-clock budget checkpoint (options.timeout)
45 if nargin>=6 && lineTimeoutExceeded(options)
46 line_error(mfilename,'State space generation exceeded the wall-clock time budget (options.timeout=%gs).', options.timeout);
47 end
48 state = State.fromMarginal(sn, ind, nset(j,:));
49 if bi==ub && j==1
50 space(end+1:end+size(state,1),:) = state;
51 else
52 space(end+1:end+size(state,1),(end-size(state,2)+1):end) = state;
53 end
54 end
55 end
56 end
57end
58space = unique(space,'rows');
59% now we remove states that are not reachable
60if sn.isstateful(ind)
61 keep = [];
62 nvarsSum = sum(sn.nvars(ind,:));
63 for s=1:size(space,1)
64 % toMarginal expects state_i to include trailing nvars columns and
65 % strips them off; fromMarginalBounds builds buffer-only rows, so
66 % pad with zeros to match the expected layout.
67 if ~sn.isstation(ind) && nvarsSum > 0
68 state_full = [space(s,:), zeros(1, nvarsSum)];
69 else
70 state_full = space(s,:);
71 end
72 [ni,nir] = State.toMarginal(sn,ind,state_full);
73 if sn.isstation(ind)
74 if all(nir <= sn.classcap(ist,:)) && ni <= cap
75 keep = [keep; s];
76 end
77 else
78 if ni <= cap
79 keep = [keep; s];
80 end
81 end
82 end
83 space = space(keep,:);
84end
85space = space(end:-1:1,:); % so that states with jobs in phase 1 comes earlier
86end
Definition Station.m:245