Skip to content

Commit ab7c5b5

Browse files
committed
fix: Allow precomputed flow for state networks
1 parent b1b750e commit ab7c5b5

13 files changed

+263
-42
lines changed

src/core/StateNetwork.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ class StateNetwork {
105105
double m_totalLinkWeightIgnored = 0.0;
106106
std::map<unsigned int, double> m_outWeights;
107107
bool m_haveNodeWeights = false;
108+
bool m_haveStateNodeWeights = false;
109+
bool m_haveFileInput = false;
108110
// Attributes
109111
std::map<unsigned int, std::string> m_names;
110112
std::map<unsigned int, PhysNode> m_physNodes;
@@ -177,6 +179,8 @@ class StateNetwork {
177179
std::map<unsigned int, std::string>& names() { return m_names; }
178180
const std::map<unsigned int, std::string>& names() const { return m_names; }
179181
bool haveNodeWeights() const { return m_haveNodeWeights; }
182+
bool haveStateNodeWeights() const { return m_haveStateNodeWeights; }
183+
bool haveFileInput() const { return m_haveFileInput; }
180184

181185
virtual const std::map<unsigned int, std::vector<int>>& metaData() const = 0;
182186

src/io/Config.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ Config::Config(const std::string& flags, bool isCLI) : isCLI(isCLI)
190190
} else if (flowModelArg == "precomputed") {
191191
setFlowModel(FlowModel::precomputed);
192192
} else if (!flowModelArg.empty()) {
193-
throw std::runtime_error("Unrecognized flow model");
193+
throw std::runtime_error(io::Str() << "Unrecognized flow model: '" << flowModelArg << "'");
194194
}
195195

196196
if (regularized) {

src/io/Network.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ void Network::parseNetwork(const std::string& filename)
120120

121121
void Network::parseNetwork(const std::string& filename, const InsensitiveStringSet& validHeadings, const InsensitiveStringSet& ignoreHeadings, const std::string& startHeading)
122122
{
123+
m_haveFileInput = true;
123124
SafeInFile input(filename);
124125

125126
// Parse standard links by default until possible heading is reached
@@ -450,7 +451,11 @@ void Network::parseStateNode(const std::string& line, StateNetwork::StateNode& s
450451
m_extractor.seekg(nameEnd + 1);
451452
}
452453
// Optional weight, default to 1.0
453-
(m_extractor >> stateNode.weight) || (stateNode.weight = 1.0);
454+
if ((m_extractor >> stateNode.weight)) {
455+
m_haveStateNodeWeights = true;
456+
if (stateNode.weight < 0)
457+
throw std::runtime_error(io::Str() << "Negative state node weight (" << stateNode.weight << ") from line '" << line << "'");
458+
}
454459
}
455460

456461
void Network::parseLink(const std::string& line, unsigned int& n1, unsigned int& n2, double& weight)

src/utils/FlowCalculator.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -247,9 +247,15 @@ void FlowCalculator::usePrecomputedFlow(const StateNetwork& network, const Confi
247247
Log() << "\n -> Using directed links with precomputed flow from input data.";
248248
Log() << "\n -> Total link flow: " << sumLinkWeight << ".";
249249

250-
if (config.isCLI && !network.haveNodeWeights()) {
251-
Log() << std::endl;
252-
throw std::runtime_error("Missing node flow in input data. Should be passed as a third field under a *Vertices section.");
250+
if (network.haveFileInput()) {
251+
if (network.haveMemoryInput() && !network.haveStateNodeWeights()) {
252+
Log() << std::endl;
253+
throw std::runtime_error("Missing node flow in input data. Should be passed as a third field under a *States section.");
254+
}
255+
if (!network.haveMemoryInput() && !network.haveNodeWeights()) {
256+
Log() << std::endl;
257+
throw std::runtime_error("Missing node flow in input data. Should be passed as a third field under a *Vertices section.");
258+
}
253259
}
254260

255261
// Treat the link weights as flow

test/data/multilayer.net

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# A multilayer network using explicit format
2+
# Figure 3
3+
*Vertices 5
4+
# node_id name
5+
1 "i"
6+
2 "j"
7+
3 "k"
8+
4 "l"
9+
5 "m"
10+
*Multilayer
11+
# layer_id node_id layer_id node_id weight
12+
# intra
13+
1 1 1 4 0.8
14+
1 4 1 1 1
15+
1 1 1 5 0.8
16+
1 5 1 1 1
17+
1 4 1 5 1
18+
1 5 1 4 1
19+
2 1 2 2 0.8
20+
2 2 2 1 1
21+
2 1 2 3 0.8
22+
2 3 2 1 1
23+
2 2 2 3 1
24+
2 3 2 2 1
25+
# inter
26+
1 1 2 2 0.2
27+
1 1 2 3 0.2
28+
2 1 1 4 0.2
29+
2 1 1 5 0.2

test/data/states.net

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# A network in state format
2+
# Figure 6
3+
*Vertices 5
4+
#node_id name
5+
1 "i"
6+
2 "j"
7+
3 "k"
8+
4 "l"
9+
5 "m"
10+
*States
11+
#state_id node_id name
12+
1 1 "α~_i"
13+
2 2 "β~_j"
14+
3 3 "γ~_k"
15+
4 1 "δ~_i"
16+
5 4 "ε~_l"
17+
6 5 "ζ~_m"
18+
*Links
19+
#source target weight
20+
1 2 0.8
21+
1 3 0.8
22+
1 5 0.2
23+
1 6 0.2
24+
2 1 1
25+
2 3 1
26+
3 1 1
27+
3 2 1
28+
4 5 0.8
29+
4 6 0.8
30+
4 2 0.2
31+
4 3 0.2
32+
5 4 1
33+
5 6 1
34+
6 4 1
35+
6 5 1

test/data/states_flow.net

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# A network in state format
2+
# Figure 6
3+
*Vertices 5
4+
#node_id name
5+
1 "i" 0.4
6+
2 "j" 0.15
7+
3 "k" 0.15
8+
4 "l" 0.15
9+
5 "m" 0.15
10+
*States
11+
#state_id node_id name
12+
1 1 "α~_i" 0.1
13+
2 2 "β~_j" 0.1
14+
3 3 "γ~_k" 0.3
15+
4 1 "δ~_i" 0.3
16+
5 4 "ε~_l" 0.1
17+
6 5 "ζ~_m" 0.1
18+
*Links
19+
#source target weight
20+
1 2 0.08
21+
1 3 0.08
22+
1 5 0.02
23+
1 6 0.02
24+
2 1 0.1
25+
2 3 0.1
26+
3 1 0.1
27+
3 2 0.1
28+
4 5 0.08
29+
4 6 0.08
30+
4 2 0.02
31+
4 3 0.02
32+
5 4 0.1
33+
5 6 0.1
34+
6 4 0.1
35+
6 5 0.1

test/data/states_flow_output.net

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# v2.7.0
2+
# ./Infomap --silent --flow-model precomputed
3+
# State network as physical network
4+
*Vertices
5+
#id name flow
6+
1 "1" 0.1
7+
2 "2" 0.1
8+
3 "3" 0.3
9+
4 "4" 0.3
10+
5 "5" 0.1
11+
6 "6" 0.1
12+
*Arcs
13+
#source target flow
14+
1 2 0.08
15+
1 3 0.08
16+
1 5 0.02
17+
1 6 0.02
18+
2 1 0.1
19+
2 3 0.1
20+
3 1 0.1
21+
3 2 0.1
22+
4 2 0.02
23+
4 3 0.02
24+
4 5 0.08
25+
4 6 0.08
26+
5 4 0.1
27+
5 6 0.1
28+
6 4 0.1
29+
6 5 0.1

test/data/twotriangles_flow.net

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
*Vertices
2+
1 "A" 0.1
3+
2 "B" 0.2
4+
3 "C" 0.3
5+
4 "D" 0.2
6+
5 "E" 0.1
7+
6 "F" 0.1
8+
*Edges
9+
1 2 0.1
10+
1 3 0.2
11+
2 3 0.3
12+
3 4 0.1
13+
4 5 0.1
14+
4 6 0.1
15+
5 6 0.1
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# v2.7.0
2+
# ./Infomap --silent --flow-model precomputed
3+
*Vertices
4+
#id name flow
5+
1 "A" 0.1
6+
2 "B" 0.2
7+
3 "C" 0.3
8+
4 "D" 0.2
9+
5 "E" 0.1
10+
6 "F" 0.1
11+
*Arcs
12+
#source target flow
13+
1 2 0.1
14+
1 3 0.2
15+
2 3 0.3
16+
3 4 0.1
17+
4 5 0.1
18+
4 6 0.1
19+
5 6 0.1

0 commit comments

Comments
 (0)