LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Toggle main menu visibility
Loading...
Searching...
No Matches
pfqn_comb_common.h
Go to the documentation of this file.
1
/*
2
* Copyright (c) 2012-2026, QORE Lab, Imperial College London
3
* All rights reserved.
4
*/
5
#ifndef LINE_API_PFQN_COMB_COMMON_H
6
#define LINE_API_PFQN_COMB_COMMON_H
7
8
/**
9
* @file
10
* @ingroup api_pfqn
11
* Integer-composition enumeration shared by the CoMoM and MVAC ports.
12
*
13
* Templated-free helpers mirroring matlab/src/util/multichoose.m and
14
* matlab/src/util/matchrow.m. Both are pure index arithmetic on integers, so
15
* they carry no number type at all and are usable from any instantiation.
16
*
17
* ORDERING MATTERS. MATLAB's multichoose(n,k) recurses as
18
*
19
* for i = 0:k, rows = [ i , multichoose(n-1, k-i) ]
20
*
21
* so the first component ascends slowest. Several callers (pfqn_comom's basis
22
* layout, pfqn_mvac's multiplicity list) index into the result by position
23
* rather than by content, and a different but equally valid enumeration order
24
* would silently permute their bases. The recursion is reproduced verbatim
25
* rather than replaced by a "nicer" odometer.
26
*
27
* `line::multichoose` in util/population.h returns the COUNT C(n+k-1,k);
28
* `multichoose_rows` here returns the compositions themselves. The names are
29
* kept distinct so that a call site cannot pick up the wrong one.
30
*/
31
32
#include <cstddef>
33
#include <vector>
34
35
#include "
line/util/error.h
"
36
37
namespace
line
{
38
namespace
pfqn
{
39
40
/**
41
* All n-vectors of nonnegative integers summing to k, in MATLAB
42
* multichoose(n,k) order.
43
*/
44
inline
std::vector<std::vector<int>>
multichoose_rows
(
int
n,
int
k) {
45
if
(n < 1)
throw
InputError
(
"multichoose_rows: at least one component is required"
);
46
if
(k < 0)
throw
InputError
(
"multichoose_rows: negative total"
);
47
std::vector<std::vector<int>> out;
48
if
(n == 1) {
49
out.push_back(std::vector<int>(1, k));
50
return
out;
51
}
52
if
(k == 0) {
53
out.push_back(std::vector<int>(
static_cast<
std::size_t
>
(n), 0));
54
return
out;
55
}
56
for
(
int
i = 0; i <= k; ++i) {
57
const
std::vector<std::vector<int>> w =
multichoose_rows
(n - 1, k - i);
58
for
(std::size_t j = 0; j < w.size(); ++j) {
59
std::vector<int> row;
60
row.reserve(
static_cast<
std::size_t
>
(n));
61
row.push_back(i);
62
row.insert(row.end(), w[j].begin(), w[j].end());
63
out.push_back(row);
64
}
65
}
66
return
out;
67
}
68
69
/**
70
* Position of `row` in `rows`, or -1 when absent. MATLAB's matchrow checks the
71
* LAST row first and otherwise returns the first match; with the distinct row
72
* sets used here the two rules coincide, and the first-match rule is used.
73
*/
74
inline
int
matchrow
(
const
std::vector<std::vector<int>>& rows,
const
std::vector<int>& row) {
75
for
(std::size_t i = 0; i < rows.size(); ++i) {
76
if
(rows[i].size() != row.size())
return
-2;
77
bool
eq =
true
;
78
for
(std::size_t j = 0; j < row.size(); ++j)
79
if
(rows[i][j] != row[j]) {
80
eq =
false
;
81
break
;
82
}
83
if
(eq)
return
static_cast<
int
>
(i);
84
}
85
return
-1;
86
}
87
88
/**
89
* MATLAB's sortbynnzpos: a stable bubble sort putting the rows with FEWER
90
* nonzeros first and, among rows with equally many, the row whose leftmost
91
* differing entry is nonzero first. Reproduced exactly, including the O(n^2)
92
* shape, because the resulting order is the basis layout that pfqn_comom and
93
* pfqn_procomom index into.
94
*/
95
inline
void
sort_by_nnz_pos
(std::vector<std::vector<int>>& I) {
96
const
auto
nnz = [](
const
std::vector<int>& v) {
97
int
c = 0;
98
for
(
int
x : v)
99
if
(x != 0) ++c;
100
return
c;
101
};
102
// returns true when i1 must come AFTER i2 (MATLAB nnzcmp(i1,i2) == 1)
103
const
auto
after = [&](
const
std::vector<int>& i1,
const
std::vector<int>& i2) {
104
const
int
n1 = nnz(i1), n2 = nnz(i2);
105
if
(n1 > n2)
return
true
;
106
if
(n1 < n2)
return
false
;
107
for
(std::size_t j = 0; j < i1.size(); ++j) {
108
if
(i1[j] == 0 && i2[j] > 0)
return
true
;
109
if
(i1[j] > 0 && i2[j] == 0)
return
false
;
110
}
111
return
false
;
112
};
113
for
(std::size_t i = 0; i + 1 < I.size(); ++i)
114
for
(std::size_t j = i + 1; j < I.size(); ++j)
115
if
(after(I[i], I[j])) std::swap(I[i], I[j]);
116
}
117
118
}
// namespace pfqn
119
}
// namespace line
120
121
#endif
// LINE_API_PFQN_COMB_COMMON_H
line::InputError::InputError
InputError(const std::string &what)
Definition
error.h:39
error.h
The exception types the port throws.
line::pfqn
Definition
cd_peak_scaling.h:43
line::pfqn::matchrow
int matchrow(const std::vector< std::vector< int > > &rows, const std::vector< int > &row)
Position of row in rows, or -1 when absent.
Definition
pfqn_comb_common.h:74
line::pfqn::multichoose_rows
std::vector< std::vector< int > > multichoose_rows(int n, int k)
All n-vectors of nonnegative integers summing to k, in MATLAB multichoose(n,k) order.
Definition
pfqn_comb_common.h:44
line::pfqn::sort_by_nnz_pos
void sort_by_nnz_pos(std::vector< std::vector< int > > &I)
MATLAB's sortbynnzpos: a stable bubble sort putting the rows with FEWER nonzeros first and,...
Definition
pfqn_comb_common.h:95
line
Definition
aoi_dist2ph.h:52
include
line
api
pfqn
pfqn_comb_common.h
Generated by
1.18.0