BayesNet/html/bayesnet/network/Network.cc.gcov.html
2024-05-06 17:56:00 +02:00

514 lines
63 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>LCOV - BayesNet Coverage Report - bayesnet/network/Network.cc</title>
<link rel="stylesheet" type="text/css" href="../../gcov.css">
</head>
<body>
<table width="100%" border=0 cellspacing=0 cellpadding=0>
<tr><td class="title">LCOV - code coverage report</td></tr>
<tr><td class="ruler"><img src="../../glass.png" width=3 height=3 alt=""></td></tr>
<tr>
<td width="100%">
<table cellpadding=1 border=0 width="100%">
<tr>
<td width="10%" class="headerItem">Current view:</td>
<td width="10%" class="headerValue"><a href="../../index.html" target="_parent">top level</a> - <a href="index.html" target="_parent">bayesnet/network</a> - Network.cc<span style="font-size: 80%;"> (source / <a href="Network.cc.func-c.html">functions</a>)</span></td>
<td width="5%"></td>
<td width="5%"></td>
<td width="5%" class="headerCovTableHead">Coverage</td>
<td width="5%" class="headerCovTableHead" title="Covered + Uncovered code">Total</td>
<td width="5%" class="headerCovTableHead" title="Exercised code only">Hit</td>
</tr>
<tr>
<td class="headerItem">Test:</td>
<td class="headerValue">BayesNet Coverage Report</td>
<td></td>
<td class="headerItem">Lines:</td>
<td class="headerCovTableEntryHi">100.0&nbsp;%</td>
<td class="headerCovTableEntry">295</td>
<td class="headerCovTableEntry">295</td>
</tr>
<tr>
<td class="headerItem">Test Date:</td>
<td class="headerValue">2024-05-06 17:54:04</td>
<td></td>
<td class="headerItem">Functions:</td>
<td class="headerCovTableEntryHi">100.0&nbsp;%</td>
<td class="headerCovTableEntry">40</td>
<td class="headerCovTableEntry">40</td>
</tr>
<tr>
<td class="headerItem">Legend:</td>
<td class="headerValueLeg"> Lines:
<span class="coverLegendCov">hit</span>
<span class="coverLegendNoCov">not hit</span>
</td>
<td></td>
</tr>
<tr><td><img src="../../glass.png" width=3 height=3 alt=""></td></tr>
</table>
</td>
</tr>
<tr><td class="ruler"><img src="../../glass.png" width=3 height=3 alt=""></td></tr>
</table>
<table cellpadding=0 cellspacing=0 border=0>
<tr>
<td><br></td>
</tr>
<tr>
<td>
<pre class="sourceHeading"> Line data Source code</pre>
<pre class="source">
<span id="L1"><span class="lineNum"> 1</span> : // ***************************************************************</span>
<span id="L2"><span class="lineNum"> 2</span> : // SPDX-FileCopyrightText: Copyright 2024 Ricardo Montañana Gómez</span>
<span id="L3"><span class="lineNum"> 3</span> : // SPDX-FileType: SOURCE</span>
<span id="L4"><span class="lineNum"> 4</span> : // SPDX-License-Identifier: MIT</span>
<span id="L5"><span class="lineNum"> 5</span> : // ***************************************************************</span>
<span id="L6"><span class="lineNum"> 6</span> : </span>
<span id="L7"><span class="lineNum"> 7</span> : #include &lt;thread&gt;</span>
<span id="L8"><span class="lineNum"> 8</span> : #include &lt;mutex&gt;</span>
<span id="L9"><span class="lineNum"> 9</span> : #include &lt;sstream&gt;</span>
<span id="L10"><span class="lineNum"> 10</span> : #include &quot;Network.h&quot;</span>
<span id="L11"><span class="lineNum"> 11</span> : #include &quot;bayesnet/utils/bayesnetUtils.h&quot;</span>
<span id="L12"><span class="lineNum"> 12</span> : namespace bayesnet {</span>
<span id="L13"><span class="lineNum"> 13</span> <span class="tlaGNC tlaBgGNC"> 2332 : Network::Network() : fitted{ false }, maxThreads{ 0.95 }, classNumStates{ 0 }, laplaceSmoothing{ 0 }</span></span>
<span id="L14"><span class="lineNum"> 14</span> : {</span>
<span id="L15"><span class="lineNum"> 15</span> <span class="tlaGNC"> 2332 : }</span></span>
<span id="L16"><span class="lineNum"> 16</span> <span class="tlaGNC"> 8 : Network::Network(float maxT) : fitted{ false }, maxThreads{ maxT }, classNumStates{ 0 }, laplaceSmoothing{ 0 }</span></span>
<span id="L17"><span class="lineNum"> 17</span> : {</span>
<span id="L18"><span class="lineNum"> 18</span> : </span>
<span id="L19"><span class="lineNum"> 19</span> <span class="tlaGNC"> 8 : }</span></span>
<span id="L20"><span class="lineNum"> 20</span> <span class="tlaGNC"> 2244 : Network::Network(const Network&amp; other) : laplaceSmoothing(other.laplaceSmoothing), features(other.features), className(other.className), classNumStates(other.getClassNumStates()),</span></span>
<span id="L21"><span class="lineNum"> 21</span> <span class="tlaGNC"> 4488 : maxThreads(other.getMaxThreads()), fitted(other.fitted), samples(other.samples)</span></span>
<span id="L22"><span class="lineNum"> 22</span> : {</span>
<span id="L23"><span class="lineNum"> 23</span> <span class="tlaGNC"> 2244 : if (samples.defined())</span></span>
<span id="L24"><span class="lineNum"> 24</span> <span class="tlaGNC"> 4 : samples = samples.clone();</span></span>
<span id="L25"><span class="lineNum"> 25</span> <span class="tlaGNC"> 2264 : for (const auto&amp; node : other.nodes) {</span></span>
<span id="L26"><span class="lineNum"> 26</span> <span class="tlaGNC"> 20 : nodes[node.first] = std::make_unique&lt;Node&gt;(*node.second);</span></span>
<span id="L27"><span class="lineNum"> 27</span> : }</span>
<span id="L28"><span class="lineNum"> 28</span> <span class="tlaGNC"> 2244 : }</span></span>
<span id="L29"><span class="lineNum"> 29</span> <span class="tlaGNC"> 1740 : void Network::initialize()</span></span>
<span id="L30"><span class="lineNum"> 30</span> : {</span>
<span id="L31"><span class="lineNum"> 31</span> <span class="tlaGNC"> 1740 : features.clear();</span></span>
<span id="L32"><span class="lineNum"> 32</span> <span class="tlaGNC"> 1740 : className = &quot;&quot;;</span></span>
<span id="L33"><span class="lineNum"> 33</span> <span class="tlaGNC"> 1740 : classNumStates = 0;</span></span>
<span id="L34"><span class="lineNum"> 34</span> <span class="tlaGNC"> 1740 : fitted = false;</span></span>
<span id="L35"><span class="lineNum"> 35</span> <span class="tlaGNC"> 1740 : nodes.clear();</span></span>
<span id="L36"><span class="lineNum"> 36</span> <span class="tlaGNC"> 1740 : samples = torch::Tensor();</span></span>
<span id="L37"><span class="lineNum"> 37</span> <span class="tlaGNC"> 1740 : }</span></span>
<span id="L38"><span class="lineNum"> 38</span> <span class="tlaGNC"> 2256 : float Network::getMaxThreads() const</span></span>
<span id="L39"><span class="lineNum"> 39</span> : {</span>
<span id="L40"><span class="lineNum"> 40</span> <span class="tlaGNC"> 2256 : return maxThreads;</span></span>
<span id="L41"><span class="lineNum"> 41</span> : }</span>
<span id="L42"><span class="lineNum"> 42</span> <span class="tlaGNC"> 48 : torch::Tensor&amp; Network::getSamples()</span></span>
<span id="L43"><span class="lineNum"> 43</span> : {</span>
<span id="L44"><span class="lineNum"> 44</span> <span class="tlaGNC"> 48 : return samples;</span></span>
<span id="L45"><span class="lineNum"> 45</span> : }</span>
<span id="L46"><span class="lineNum"> 46</span> <span class="tlaGNC"> 31216 : void Network::addNode(const std::string&amp; name)</span></span>
<span id="L47"><span class="lineNum"> 47</span> : {</span>
<span id="L48"><span class="lineNum"> 48</span> <span class="tlaGNC"> 31216 : if (name == &quot;&quot;) {</span></span>
<span id="L49"><span class="lineNum"> 49</span> <span class="tlaGNC"> 8 : throw std::invalid_argument(&quot;Node name cannot be empty&quot;);</span></span>
<span id="L50"><span class="lineNum"> 50</span> : }</span>
<span id="L51"><span class="lineNum"> 51</span> <span class="tlaGNC"> 31208 : if (nodes.find(name) != nodes.end()) {</span></span>
<span id="L52"><span class="lineNum"> 52</span> <span class="tlaGNC"> 4 : return;</span></span>
<span id="L53"><span class="lineNum"> 53</span> : }</span>
<span id="L54"><span class="lineNum"> 54</span> <span class="tlaGNC"> 31204 : if (find(features.begin(), features.end(), name) == features.end()) {</span></span>
<span id="L55"><span class="lineNum"> 55</span> <span class="tlaGNC"> 31204 : features.push_back(name);</span></span>
<span id="L56"><span class="lineNum"> 56</span> : }</span>
<span id="L57"><span class="lineNum"> 57</span> <span class="tlaGNC"> 31204 : nodes[name] = std::make_unique&lt;Node&gt;(name);</span></span>
<span id="L58"><span class="lineNum"> 58</span> : }</span>
<span id="L59"><span class="lineNum"> 59</span> <span class="tlaGNC"> 380 : std::vector&lt;std::string&gt; Network::getFeatures() const</span></span>
<span id="L60"><span class="lineNum"> 60</span> : {</span>
<span id="L61"><span class="lineNum"> 61</span> <span class="tlaGNC"> 380 : return features;</span></span>
<span id="L62"><span class="lineNum"> 62</span> : }</span>
<span id="L63"><span class="lineNum"> 63</span> <span class="tlaGNC"> 2616 : int Network::getClassNumStates() const</span></span>
<span id="L64"><span class="lineNum"> 64</span> : {</span>
<span id="L65"><span class="lineNum"> 65</span> <span class="tlaGNC"> 2616 : return classNumStates;</span></span>
<span id="L66"><span class="lineNum"> 66</span> : }</span>
<span id="L67"><span class="lineNum"> 67</span> <span class="tlaGNC"> 48 : int Network::getStates() const</span></span>
<span id="L68"><span class="lineNum"> 68</span> : {</span>
<span id="L69"><span class="lineNum"> 69</span> <span class="tlaGNC"> 48 : int result = 0;</span></span>
<span id="L70"><span class="lineNum"> 70</span> <span class="tlaGNC"> 288 : for (auto&amp; node : nodes) {</span></span>
<span id="L71"><span class="lineNum"> 71</span> <span class="tlaGNC"> 240 : result += node.second-&gt;getNumStates();</span></span>
<span id="L72"><span class="lineNum"> 72</span> : }</span>
<span id="L73"><span class="lineNum"> 73</span> <span class="tlaGNC"> 48 : return result;</span></span>
<span id="L74"><span class="lineNum"> 74</span> : }</span>
<span id="L75"><span class="lineNum"> 75</span> <span class="tlaGNC"> 3735008 : std::string Network::getClassName() const</span></span>
<span id="L76"><span class="lineNum"> 76</span> : {</span>
<span id="L77"><span class="lineNum"> 77</span> <span class="tlaGNC"> 3735008 : return className;</span></span>
<span id="L78"><span class="lineNum"> 78</span> : }</span>
<span id="L79"><span class="lineNum"> 79</span> <span class="tlaGNC"> 70324 : bool Network::isCyclic(const std::string&amp; nodeId, std::unordered_set&lt;std::string&gt;&amp; visited, std::unordered_set&lt;std::string&gt;&amp; recStack)</span></span>
<span id="L80"><span class="lineNum"> 80</span> : {</span>
<span id="L81"><span class="lineNum"> 81</span> <span class="tlaGNC"> 70324 : if (visited.find(nodeId) == visited.end()) // if node hasn't been visited yet</span></span>
<span id="L82"><span class="lineNum"> 82</span> : {</span>
<span id="L83"><span class="lineNum"> 83</span> <span class="tlaGNC"> 70324 : visited.insert(nodeId);</span></span>
<span id="L84"><span class="lineNum"> 84</span> <span class="tlaGNC"> 70324 : recStack.insert(nodeId);</span></span>
<span id="L85"><span class="lineNum"> 85</span> <span class="tlaGNC"> 81496 : for (Node* child : nodes[nodeId]-&gt;getChildren()) {</span></span>
<span id="L86"><span class="lineNum"> 86</span> <span class="tlaGNC"> 11196 : if (visited.find(child-&gt;getName()) == visited.end() &amp;&amp; isCyclic(child-&gt;getName(), visited, recStack))</span></span>
<span id="L87"><span class="lineNum"> 87</span> <span class="tlaGNC"> 24 : return true;</span></span>
<span id="L88"><span class="lineNum"> 88</span> <span class="tlaGNC"> 11180 : if (recStack.find(child-&gt;getName()) != recStack.end())</span></span>
<span id="L89"><span class="lineNum"> 89</span> <span class="tlaGNC"> 8 : return true;</span></span>
<span id="L90"><span class="lineNum"> 90</span> : }</span>
<span id="L91"><span class="lineNum"> 91</span> : }</span>
<span id="L92"><span class="lineNum"> 92</span> <span class="tlaGNC"> 70300 : recStack.erase(nodeId); // remove node from recursion stack before function ends</span></span>
<span id="L93"><span class="lineNum"> 93</span> <span class="tlaGNC"> 70300 : return false;</span></span>
<span id="L94"><span class="lineNum"> 94</span> : }</span>
<span id="L95"><span class="lineNum"> 95</span> <span class="tlaGNC"> 59152 : void Network::addEdge(const std::string&amp; parent, const std::string&amp; child)</span></span>
<span id="L96"><span class="lineNum"> 96</span> : {</span>
<span id="L97"><span class="lineNum"> 97</span> <span class="tlaGNC"> 59152 : if (nodes.find(parent) == nodes.end()) {</span></span>
<span id="L98"><span class="lineNum"> 98</span> <span class="tlaGNC"> 8 : throw std::invalid_argument(&quot;Parent node &quot; + parent + &quot; does not exist&quot;);</span></span>
<span id="L99"><span class="lineNum"> 99</span> : }</span>
<span id="L100"><span class="lineNum"> 100</span> <span class="tlaGNC"> 59144 : if (nodes.find(child) == nodes.end()) {</span></span>
<span id="L101"><span class="lineNum"> 101</span> <span class="tlaGNC"> 8 : throw std::invalid_argument(&quot;Child node &quot; + child + &quot; does not exist&quot;);</span></span>
<span id="L102"><span class="lineNum"> 102</span> : }</span>
<span id="L103"><span class="lineNum"> 103</span> : // Temporarily add edge to check for cycles</span>
<span id="L104"><span class="lineNum"> 104</span> <span class="tlaGNC"> 59136 : nodes[parent]-&gt;addChild(nodes[child].get());</span></span>
<span id="L105"><span class="lineNum"> 105</span> <span class="tlaGNC"> 59136 : nodes[child]-&gt;addParent(nodes[parent].get());</span></span>
<span id="L106"><span class="lineNum"> 106</span> <span class="tlaGNC"> 59136 : std::unordered_set&lt;std::string&gt; visited;</span></span>
<span id="L107"><span class="lineNum"> 107</span> <span class="tlaGNC"> 59136 : std::unordered_set&lt;std::string&gt; recStack;</span></span>
<span id="L108"><span class="lineNum"> 108</span> <span class="tlaGNC"> 59136 : if (isCyclic(nodes[child]-&gt;getName(), visited, recStack)) // if adding this edge forms a cycle</span></span>
<span id="L109"><span class="lineNum"> 109</span> : {</span>
<span id="L110"><span class="lineNum"> 110</span> : // remove problematic edge</span>
<span id="L111"><span class="lineNum"> 111</span> <span class="tlaGNC"> 8 : nodes[parent]-&gt;removeChild(nodes[child].get());</span></span>
<span id="L112"><span class="lineNum"> 112</span> <span class="tlaGNC"> 8 : nodes[child]-&gt;removeParent(nodes[parent].get());</span></span>
<span id="L113"><span class="lineNum"> 113</span> <span class="tlaGNC"> 8 : throw std::invalid_argument(&quot;Adding this edge forms a cycle in the graph.&quot;);</span></span>
<span id="L114"><span class="lineNum"> 114</span> : }</span>
<span id="L115"><span class="lineNum"> 115</span> <span class="tlaGNC"> 59144 : }</span></span>
<span id="L116"><span class="lineNum"> 116</span> <span class="tlaGNC"> 3735276 : std::map&lt;std::string, std::unique_ptr&lt;Node&gt;&gt;&amp; Network::getNodes()</span></span>
<span id="L117"><span class="lineNum"> 117</span> : {</span>
<span id="L118"><span class="lineNum"> 118</span> <span class="tlaGNC"> 3735276 : return nodes;</span></span>
<span id="L119"><span class="lineNum"> 119</span> : }</span>
<span id="L120"><span class="lineNum"> 120</span> <span class="tlaGNC"> 1888 : void Network::checkFitData(int n_samples, int n_features, int n_samples_y, const std::vector&lt;std::string&gt;&amp; featureNames, const std::string&amp; className, const std::map&lt;std::string, std::vector&lt;int&gt;&gt;&amp; states, const torch::Tensor&amp; weights)</span></span>
<span id="L121"><span class="lineNum"> 121</span> : {</span>
<span id="L122"><span class="lineNum"> 122</span> <span class="tlaGNC"> 1888 : if (weights.size(0) != n_samples) {</span></span>
<span id="L123"><span class="lineNum"> 123</span> <span class="tlaGNC"> 8 : throw std::invalid_argument(&quot;Weights (&quot; + std::to_string(weights.size(0)) + &quot;) must have the same number of elements as samples (&quot; + std::to_string(n_samples) + &quot;) in Network::fit&quot;);</span></span>
<span id="L124"><span class="lineNum"> 124</span> : }</span>
<span id="L125"><span class="lineNum"> 125</span> <span class="tlaGNC"> 1880 : if (n_samples != n_samples_y) {</span></span>
<span id="L126"><span class="lineNum"> 126</span> <span class="tlaGNC"> 8 : throw std::invalid_argument(&quot;X and y must have the same number of samples in Network::fit (&quot; + std::to_string(n_samples) + &quot; != &quot; + std::to_string(n_samples_y) + &quot;)&quot;);</span></span>
<span id="L127"><span class="lineNum"> 127</span> : }</span>
<span id="L128"><span class="lineNum"> 128</span> <span class="tlaGNC"> 1872 : if (n_features != featureNames.size()) {</span></span>
<span id="L129"><span class="lineNum"> 129</span> <span class="tlaGNC"> 8 : throw std::invalid_argument(&quot;X and features must have the same number of features in Network::fit (&quot; + std::to_string(n_features) + &quot; != &quot; + std::to_string(featureNames.size()) + &quot;)&quot;);</span></span>
<span id="L130"><span class="lineNum"> 130</span> : }</span>
<span id="L131"><span class="lineNum"> 131</span> <span class="tlaGNC"> 1864 : if (features.size() == 0) {</span></span>
<span id="L132"><span class="lineNum"> 132</span> <span class="tlaGNC"> 8 : throw std::invalid_argument(&quot;The network has not been initialized. You must call addNode() before calling fit()&quot;);</span></span>
<span id="L133"><span class="lineNum"> 133</span> : }</span>
<span id="L134"><span class="lineNum"> 134</span> <span class="tlaGNC"> 1856 : if (n_features != features.size() - 1) {</span></span>
<span id="L135"><span class="lineNum"> 135</span> <span class="tlaGNC"> 8 : throw std::invalid_argument(&quot;X and local features must have the same number of features in Network::fit (&quot; + std::to_string(n_features) + &quot; != &quot; + std::to_string(features.size() - 1) + &quot;)&quot;);</span></span>
<span id="L136"><span class="lineNum"> 136</span> : }</span>
<span id="L137"><span class="lineNum"> 137</span> <span class="tlaGNC"> 1848 : if (find(features.begin(), features.end(), className) == features.end()) {</span></span>
<span id="L138"><span class="lineNum"> 138</span> <span class="tlaGNC"> 8 : throw std::invalid_argument(&quot;Class Name not found in Network::features&quot;);</span></span>
<span id="L139"><span class="lineNum"> 139</span> : }</span>
<span id="L140"><span class="lineNum"> 140</span> <span class="tlaGNC"> 32868 : for (auto&amp; feature : featureNames) {</span></span>
<span id="L141"><span class="lineNum"> 141</span> <span class="tlaGNC"> 31044 : if (find(features.begin(), features.end(), feature) == features.end()) {</span></span>
<span id="L142"><span class="lineNum"> 142</span> <span class="tlaGNC"> 8 : throw std::invalid_argument(&quot;Feature &quot; + feature + &quot; not found in Network::features&quot;);</span></span>
<span id="L143"><span class="lineNum"> 143</span> : }</span>
<span id="L144"><span class="lineNum"> 144</span> <span class="tlaGNC"> 31036 : if (states.find(feature) == states.end()) {</span></span>
<span id="L145"><span class="lineNum"> 145</span> <span class="tlaGNC"> 8 : throw std::invalid_argument(&quot;Feature &quot; + feature + &quot; not found in states&quot;);</span></span>
<span id="L146"><span class="lineNum"> 146</span> : }</span>
<span id="L147"><span class="lineNum"> 147</span> : }</span>
<span id="L148"><span class="lineNum"> 148</span> <span class="tlaGNC"> 1824 : }</span></span>
<span id="L149"><span class="lineNum"> 149</span> <span class="tlaGNC"> 1824 : void Network::setStates(const std::map&lt;std::string, std::vector&lt;int&gt;&gt;&amp; states)</span></span>
<span id="L150"><span class="lineNum"> 150</span> : {</span>
<span id="L151"><span class="lineNum"> 151</span> : // Set states to every Node in the network</span>
<span id="L152"><span class="lineNum"> 152</span> <span class="tlaGNC"> 1824 : for_each(features.begin(), features.end(), [this, &amp;states](const std::string&amp; feature) {</span></span>
<span id="L153"><span class="lineNum"> 153</span> <span class="tlaGNC"> 32828 : nodes.at(feature)-&gt;setNumStates(states.at(feature).size());</span></span>
<span id="L154"><span class="lineNum"> 154</span> <span class="tlaGNC"> 32828 : });</span></span>
<span id="L155"><span class="lineNum"> 155</span> <span class="tlaGNC"> 1824 : classNumStates = nodes.at(className)-&gt;getNumStates();</span></span>
<span id="L156"><span class="lineNum"> 156</span> <span class="tlaGNC"> 1824 : }</span></span>
<span id="L157"><span class="lineNum"> 157</span> : // X comes in nxm, where n is the number of features and m the number of samples</span>
<span id="L158"><span class="lineNum"> 158</span> <span class="tlaGNC"> 4 : void Network::fit(const torch::Tensor&amp; X, const torch::Tensor&amp; y, const torch::Tensor&amp; weights, const std::vector&lt;std::string&gt;&amp; featureNames, const std::string&amp; className, const std::map&lt;std::string, std::vector&lt;int&gt;&gt;&amp; states)</span></span>
<span id="L159"><span class="lineNum"> 159</span> : {</span>
<span id="L160"><span class="lineNum"> 160</span> <span class="tlaGNC"> 4 : checkFitData(X.size(1), X.size(0), y.size(0), featureNames, className, states, weights);</span></span>
<span id="L161"><span class="lineNum"> 161</span> <span class="tlaGNC"> 4 : this-&gt;className = className;</span></span>
<span id="L162"><span class="lineNum"> 162</span> <span class="tlaGNC"> 4 : torch::Tensor ytmp = torch::transpose(y.view({ y.size(0), 1 }), 0, 1);</span></span>
<span id="L163"><span class="lineNum"> 163</span> <span class="tlaGNC"> 12 : samples = torch::cat({ X , ytmp }, 0);</span></span>
<span id="L164"><span class="lineNum"> 164</span> <span class="tlaGNC"> 20 : for (int i = 0; i &lt; featureNames.size(); ++i) {</span></span>
<span id="L165"><span class="lineNum"> 165</span> <span class="tlaGNC"> 48 : auto row_feature = X.index({ i, &quot;...&quot; });</span></span>
<span id="L166"><span class="lineNum"> 166</span> <span class="tlaGNC"> 16 : }</span></span>
<span id="L167"><span class="lineNum"> 167</span> <span class="tlaGNC"> 4 : completeFit(states, weights);</span></span>
<span id="L168"><span class="lineNum"> 168</span> <span class="tlaGNC"> 24 : }</span></span>
<span id="L169"><span class="lineNum"> 169</span> <span class="tlaGNC"> 1792 : void Network::fit(const torch::Tensor&amp; samples, const torch::Tensor&amp; weights, const std::vector&lt;std::string&gt;&amp; featureNames, const std::string&amp; className, const std::map&lt;std::string, std::vector&lt;int&gt;&gt;&amp; states)</span></span>
<span id="L170"><span class="lineNum"> 170</span> : {</span>
<span id="L171"><span class="lineNum"> 171</span> <span class="tlaGNC"> 1792 : checkFitData(samples.size(1), samples.size(0) - 1, samples.size(1), featureNames, className, states, weights);</span></span>
<span id="L172"><span class="lineNum"> 172</span> <span class="tlaGNC"> 1792 : this-&gt;className = className;</span></span>
<span id="L173"><span class="lineNum"> 173</span> <span class="tlaGNC"> 1792 : this-&gt;samples = samples;</span></span>
<span id="L174"><span class="lineNum"> 174</span> <span class="tlaGNC"> 1792 : completeFit(states, weights);</span></span>
<span id="L175"><span class="lineNum"> 175</span> <span class="tlaGNC"> 1792 : }</span></span>
<span id="L176"><span class="lineNum"> 176</span> : // input_data comes in nxm, where n is the number of features and m the number of samples</span>
<span id="L177"><span class="lineNum"> 177</span> <span class="tlaGNC"> 92 : void Network::fit(const std::vector&lt;std::vector&lt;int&gt;&gt;&amp; input_data, const std::vector&lt;int&gt;&amp; labels, const std::vector&lt;double&gt;&amp; weights_, const std::vector&lt;std::string&gt;&amp; featureNames, const std::string&amp; className, const std::map&lt;std::string, std::vector&lt;int&gt;&gt;&amp; states)</span></span>
<span id="L178"><span class="lineNum"> 178</span> : {</span>
<span id="L179"><span class="lineNum"> 179</span> <span class="tlaGNC"> 92 : const torch::Tensor weights = torch::tensor(weights_, torch::kFloat64);</span></span>
<span id="L180"><span class="lineNum"> 180</span> <span class="tlaGNC"> 92 : checkFitData(input_data[0].size(), input_data.size(), labels.size(), featureNames, className, states, weights);</span></span>
<span id="L181"><span class="lineNum"> 181</span> <span class="tlaGNC"> 28 : this-&gt;className = className;</span></span>
<span id="L182"><span class="lineNum"> 182</span> : // Build tensor of samples (nxm) (n+1 because of the class)</span>
<span id="L183"><span class="lineNum"> 183</span> <span class="tlaGNC"> 28 : samples = torch::zeros({ static_cast&lt;int&gt;(input_data.size() + 1), static_cast&lt;int&gt;(input_data[0].size()) }, torch::kInt32);</span></span>
<span id="L184"><span class="lineNum"> 184</span> <span class="tlaGNC"> 140 : for (int i = 0; i &lt; featureNames.size(); ++i) {</span></span>
<span id="L185"><span class="lineNum"> 185</span> <span class="tlaGNC"> 448 : samples.index_put_({ i, &quot;...&quot; }, torch::tensor(input_data[i], torch::kInt32));</span></span>
<span id="L186"><span class="lineNum"> 186</span> : }</span>
<span id="L187"><span class="lineNum"> 187</span> <span class="tlaGNC"> 112 : samples.index_put_({ -1, &quot;...&quot; }, torch::tensor(labels, torch::kInt32));</span></span>
<span id="L188"><span class="lineNum"> 188</span> <span class="tlaGNC"> 28 : completeFit(states, weights);</span></span>
<span id="L189"><span class="lineNum"> 189</span> <span class="tlaGNC"> 232 : }</span></span>
<span id="L190"><span class="lineNum"> 190</span> <span class="tlaGNC"> 1824 : void Network::completeFit(const std::map&lt;std::string, std::vector&lt;int&gt;&gt;&amp; states, const torch::Tensor&amp; weights)</span></span>
<span id="L191"><span class="lineNum"> 191</span> : {</span>
<span id="L192"><span class="lineNum"> 192</span> <span class="tlaGNC"> 1824 : setStates(states);</span></span>
<span id="L193"><span class="lineNum"> 193</span> <span class="tlaGNC"> 1824 : laplaceSmoothing = 1.0 / samples.size(1); // To use in CPT computation</span></span>
<span id="L194"><span class="lineNum"> 194</span> <span class="tlaGNC"> 1824 : std::vector&lt;std::thread&gt; threads;</span></span>
<span id="L195"><span class="lineNum"> 195</span> <span class="tlaGNC"> 34652 : for (auto&amp; node : nodes) {</span></span>
<span id="L196"><span class="lineNum"> 196</span> <span class="tlaGNC"> 32828 : threads.emplace_back([this, &amp;node, &amp;weights]() {</span></span>
<span id="L197"><span class="lineNum"> 197</span> <span class="tlaGNC"> 32828 : node.second-&gt;computeCPT(samples, features, laplaceSmoothing, weights);</span></span>
<span id="L198"><span class="lineNum"> 198</span> <span class="tlaGNC"> 32828 : });</span></span>
<span id="L199"><span class="lineNum"> 199</span> : }</span>
<span id="L200"><span class="lineNum"> 200</span> <span class="tlaGNC"> 34652 : for (auto&amp; thread : threads) {</span></span>
<span id="L201"><span class="lineNum"> 201</span> <span class="tlaGNC"> 32828 : thread.join();</span></span>
<span id="L202"><span class="lineNum"> 202</span> : }</span>
<span id="L203"><span class="lineNum"> 203</span> <span class="tlaGNC"> 1824 : fitted = true;</span></span>
<span id="L204"><span class="lineNum"> 204</span> <span class="tlaGNC"> 1824 : }</span></span>
<span id="L205"><span class="lineNum"> 205</span> <span class="tlaGNC"> 3320 : torch::Tensor Network::predict_tensor(const torch::Tensor&amp; samples, const bool proba)</span></span>
<span id="L206"><span class="lineNum"> 206</span> : {</span>
<span id="L207"><span class="lineNum"> 207</span> <span class="tlaGNC"> 3320 : if (!fitted) {</span></span>
<span id="L208"><span class="lineNum"> 208</span> <span class="tlaGNC"> 8 : throw std::logic_error(&quot;You must call fit() before calling predict()&quot;);</span></span>
<span id="L209"><span class="lineNum"> 209</span> : }</span>
<span id="L210"><span class="lineNum"> 210</span> <span class="tlaGNC"> 3312 : torch::Tensor result;</span></span>
<span id="L211"><span class="lineNum"> 211</span> <span class="tlaGNC"> 3312 : result = torch::zeros({ samples.size(1), classNumStates }, torch::kFloat64);</span></span>
<span id="L212"><span class="lineNum"> 212</span> <span class="tlaGNC"> 785016 : for (int i = 0; i &lt; samples.size(1); ++i) {</span></span>
<span id="L213"><span class="lineNum"> 213</span> <span class="tlaGNC"> 2345136 : const torch::Tensor sample = samples.index({ &quot;...&quot;, i });</span></span>
<span id="L214"><span class="lineNum"> 214</span> <span class="tlaGNC"> 781712 : auto psample = predict_sample(sample);</span></span>
<span id="L215"><span class="lineNum"> 215</span> <span class="tlaGNC"> 781704 : auto temp = torch::tensor(psample, torch::kFloat64);</span></span>
<span id="L216"><span class="lineNum"> 216</span> : // result.index_put_({ i, &quot;...&quot; }, torch::tensor(predict_sample(sample), torch::kFloat64));</span>
<span id="L217"><span class="lineNum"> 217</span> <span class="tlaGNC"> 2345112 : result.index_put_({ i, &quot;...&quot; }, temp);</span></span>
<span id="L218"><span class="lineNum"> 218</span> <span class="tlaGNC"> 781712 : }</span></span>
<span id="L219"><span class="lineNum"> 219</span> <span class="tlaGNC"> 3304 : if (proba)</span></span>
<span id="L220"><span class="lineNum"> 220</span> <span class="tlaGNC"> 1476 : return result;</span></span>
<span id="L221"><span class="lineNum"> 221</span> <span class="tlaGNC"> 3656 : return result.argmax(1);</span></span>
<span id="L222"><span class="lineNum"> 222</span> <span class="tlaGNC"> 1566728 : }</span></span>
<span id="L223"><span class="lineNum"> 223</span> : // Return mxn tensor of probabilities</span>
<span id="L224"><span class="lineNum"> 224</span> <span class="tlaGNC"> 1476 : torch::Tensor Network::predict_proba(const torch::Tensor&amp; samples)</span></span>
<span id="L225"><span class="lineNum"> 225</span> : {</span>
<span id="L226"><span class="lineNum"> 226</span> <span class="tlaGNC"> 1476 : return predict_tensor(samples, true);</span></span>
<span id="L227"><span class="lineNum"> 227</span> : }</span>
<span id="L228"><span class="lineNum"> 228</span> : </span>
<span id="L229"><span class="lineNum"> 229</span> : // Return mxn tensor of probabilities</span>
<span id="L230"><span class="lineNum"> 230</span> <span class="tlaGNC"> 1844 : torch::Tensor Network::predict(const torch::Tensor&amp; samples)</span></span>
<span id="L231"><span class="lineNum"> 231</span> : {</span>
<span id="L232"><span class="lineNum"> 232</span> <span class="tlaGNC"> 1844 : return predict_tensor(samples, false);</span></span>
<span id="L233"><span class="lineNum"> 233</span> : }</span>
<span id="L234"><span class="lineNum"> 234</span> : </span>
<span id="L235"><span class="lineNum"> 235</span> : // Return mx1 std::vector of predictions</span>
<span id="L236"><span class="lineNum"> 236</span> : // tsamples is nxm std::vector of samples</span>
<span id="L237"><span class="lineNum"> 237</span> <span class="tlaGNC"> 48 : std::vector&lt;int&gt; Network::predict(const std::vector&lt;std::vector&lt;int&gt;&gt;&amp; tsamples)</span></span>
<span id="L238"><span class="lineNum"> 238</span> : {</span>
<span id="L239"><span class="lineNum"> 239</span> <span class="tlaGNC"> 48 : if (!fitted) {</span></span>
<span id="L240"><span class="lineNum"> 240</span> <span class="tlaGNC"> 16 : throw std::logic_error(&quot;You must call fit() before calling predict()&quot;);</span></span>
<span id="L241"><span class="lineNum"> 241</span> : }</span>
<span id="L242"><span class="lineNum"> 242</span> <span class="tlaGNC"> 32 : std::vector&lt;int&gt; predictions;</span></span>
<span id="L243"><span class="lineNum"> 243</span> <span class="tlaGNC"> 32 : std::vector&lt;int&gt; sample;</span></span>
<span id="L244"><span class="lineNum"> 244</span> <span class="tlaGNC"> 3564 : for (int row = 0; row &lt; tsamples[0].size(); ++row) {</span></span>
<span id="L245"><span class="lineNum"> 245</span> <span class="tlaGNC"> 3540 : sample.clear();</span></span>
<span id="L246"><span class="lineNum"> 246</span> <span class="tlaGNC"> 26252 : for (int col = 0; col &lt; tsamples.size(); ++col) {</span></span>
<span id="L247"><span class="lineNum"> 247</span> <span class="tlaGNC"> 22712 : sample.push_back(tsamples[col][row]);</span></span>
<span id="L248"><span class="lineNum"> 248</span> : }</span>
<span id="L249"><span class="lineNum"> 249</span> <span class="tlaGNC"> 3540 : std::vector&lt;double&gt; classProbabilities = predict_sample(sample);</span></span>
<span id="L250"><span class="lineNum"> 250</span> : // Find the class with the maximum posterior probability</span>
<span id="L251"><span class="lineNum"> 251</span> <span class="tlaGNC"> 3532 : auto maxElem = max_element(classProbabilities.begin(), classProbabilities.end());</span></span>
<span id="L252"><span class="lineNum"> 252</span> <span class="tlaGNC"> 3532 : int predictedClass = distance(classProbabilities.begin(), maxElem);</span></span>
<span id="L253"><span class="lineNum"> 253</span> <span class="tlaGNC"> 3532 : predictions.push_back(predictedClass);</span></span>
<span id="L254"><span class="lineNum"> 254</span> <span class="tlaGNC"> 3532 : }</span></span>
<span id="L255"><span class="lineNum"> 255</span> <span class="tlaGNC"> 48 : return predictions;</span></span>
<span id="L256"><span class="lineNum"> 256</span> <span class="tlaGNC"> 40 : }</span></span>
<span id="L257"><span class="lineNum"> 257</span> : // Return mxn std::vector of probabilities</span>
<span id="L258"><span class="lineNum"> 258</span> : // tsamples is nxm std::vector of samples</span>
<span id="L259"><span class="lineNum"> 259</span> <span class="tlaGNC"> 552 : std::vector&lt;std::vector&lt;double&gt;&gt; Network::predict_proba(const std::vector&lt;std::vector&lt;int&gt;&gt;&amp; tsamples)</span></span>
<span id="L260"><span class="lineNum"> 260</span> : {</span>
<span id="L261"><span class="lineNum"> 261</span> <span class="tlaGNC"> 552 : if (!fitted) {</span></span>
<span id="L262"><span class="lineNum"> 262</span> <span class="tlaGNC"> 8 : throw std::logic_error(&quot;You must call fit() before calling predict_proba()&quot;);</span></span>
<span id="L263"><span class="lineNum"> 263</span> : }</span>
<span id="L264"><span class="lineNum"> 264</span> <span class="tlaGNC"> 544 : std::vector&lt;std::vector&lt;double&gt;&gt; predictions;</span></span>
<span id="L265"><span class="lineNum"> 265</span> <span class="tlaGNC"> 544 : std::vector&lt;int&gt; sample;</span></span>
<span id="L266"><span class="lineNum"> 266</span> <span class="tlaGNC"> 111516 : for (int row = 0; row &lt; tsamples[0].size(); ++row) {</span></span>
<span id="L267"><span class="lineNum"> 267</span> <span class="tlaGNC"> 110972 : sample.clear();</span></span>
<span id="L268"><span class="lineNum"> 268</span> <span class="tlaGNC"> 1055620 : for (int col = 0; col &lt; tsamples.size(); ++col) {</span></span>
<span id="L269"><span class="lineNum"> 269</span> <span class="tlaGNC"> 944648 : sample.push_back(tsamples[col][row]);</span></span>
<span id="L270"><span class="lineNum"> 270</span> : }</span>
<span id="L271"><span class="lineNum"> 271</span> <span class="tlaGNC"> 110972 : predictions.push_back(predict_sample(sample));</span></span>
<span id="L272"><span class="lineNum"> 272</span> : }</span>
<span id="L273"><span class="lineNum"> 273</span> <span class="tlaGNC"> 1088 : return predictions;</span></span>
<span id="L274"><span class="lineNum"> 274</span> <span class="tlaGNC"> 544 : }</span></span>
<span id="L275"><span class="lineNum"> 275</span> <span class="tlaGNC"> 20 : double Network::score(const std::vector&lt;std::vector&lt;int&gt;&gt;&amp; tsamples, const std::vector&lt;int&gt;&amp; labels)</span></span>
<span id="L276"><span class="lineNum"> 276</span> : {</span>
<span id="L277"><span class="lineNum"> 277</span> <span class="tlaGNC"> 20 : std::vector&lt;int&gt; y_pred = predict(tsamples);</span></span>
<span id="L278"><span class="lineNum"> 278</span> <span class="tlaGNC"> 12 : int correct = 0;</span></span>
<span id="L279"><span class="lineNum"> 279</span> <span class="tlaGNC"> 2324 : for (int i = 0; i &lt; y_pred.size(); ++i) {</span></span>
<span id="L280"><span class="lineNum"> 280</span> <span class="tlaGNC"> 2312 : if (y_pred[i] == labels[i]) {</span></span>
<span id="L281"><span class="lineNum"> 281</span> <span class="tlaGNC"> 1944 : correct++;</span></span>
<span id="L282"><span class="lineNum"> 282</span> : }</span>
<span id="L283"><span class="lineNum"> 283</span> : }</span>
<span id="L284"><span class="lineNum"> 284</span> <span class="tlaGNC"> 24 : return (double)correct / y_pred.size();</span></span>
<span id="L285"><span class="lineNum"> 285</span> <span class="tlaGNC"> 12 : }</span></span>
<span id="L286"><span class="lineNum"> 286</span> : // Return 1xn std::vector of probabilities</span>
<span id="L287"><span class="lineNum"> 287</span> <span class="tlaGNC"> 114512 : std::vector&lt;double&gt; Network::predict_sample(const std::vector&lt;int&gt;&amp; sample)</span></span>
<span id="L288"><span class="lineNum"> 288</span> : {</span>
<span id="L289"><span class="lineNum"> 289</span> : // Ensure the sample size is equal to the number of features</span>
<span id="L290"><span class="lineNum"> 290</span> <span class="tlaGNC"> 114512 : if (sample.size() != features.size() - 1) {</span></span>
<span id="L291"><span class="lineNum"> 291</span> <span class="tlaGNC"> 16 : throw std::invalid_argument(&quot;Sample size (&quot; + std::to_string(sample.size()) +</span></span>
<span id="L292"><span class="lineNum"> 292</span> <span class="tlaGNC"> 24 : &quot;) does not match the number of features (&quot; + std::to_string(features.size() - 1) + &quot;)&quot;);</span></span>
<span id="L293"><span class="lineNum"> 293</span> : }</span>
<span id="L294"><span class="lineNum"> 294</span> <span class="tlaGNC"> 114504 : std::map&lt;std::string, int&gt; evidence;</span></span>
<span id="L295"><span class="lineNum"> 295</span> <span class="tlaGNC"> 1081840 : for (int i = 0; i &lt; sample.size(); ++i) {</span></span>
<span id="L296"><span class="lineNum"> 296</span> <span class="tlaGNC"> 967336 : evidence[features[i]] = sample[i];</span></span>
<span id="L297"><span class="lineNum"> 297</span> : }</span>
<span id="L298"><span class="lineNum"> 298</span> <span class="tlaGNC"> 229008 : return exactInference(evidence);</span></span>
<span id="L299"><span class="lineNum"> 299</span> <span class="tlaGNC"> 114504 : }</span></span>
<span id="L300"><span class="lineNum"> 300</span> : // Return 1xn std::vector of probabilities</span>
<span id="L301"><span class="lineNum"> 301</span> <span class="tlaGNC"> 781712 : std::vector&lt;double&gt; Network::predict_sample(const torch::Tensor&amp; sample)</span></span>
<span id="L302"><span class="lineNum"> 302</span> : {</span>
<span id="L303"><span class="lineNum"> 303</span> : // Ensure the sample size is equal to the number of features</span>
<span id="L304"><span class="lineNum"> 304</span> <span class="tlaGNC"> 781712 : if (sample.size(0) != features.size() - 1) {</span></span>
<span id="L305"><span class="lineNum"> 305</span> <span class="tlaGNC"> 16 : throw std::invalid_argument(&quot;Sample size (&quot; + std::to_string(sample.size(0)) +</span></span>
<span id="L306"><span class="lineNum"> 306</span> <span class="tlaGNC"> 24 : &quot;) does not match the number of features (&quot; + std::to_string(features.size() - 1) + &quot;)&quot;);</span></span>
<span id="L307"><span class="lineNum"> 307</span> : }</span>
<span id="L308"><span class="lineNum"> 308</span> <span class="tlaGNC"> 781704 : std::map&lt;std::string, int&gt; evidence;</span></span>
<span id="L309"><span class="lineNum"> 309</span> <span class="tlaGNC"> 18085136 : for (int i = 0; i &lt; sample.size(0); ++i) {</span></span>
<span id="L310"><span class="lineNum"> 310</span> <span class="tlaGNC"> 17303432 : evidence[features[i]] = sample[i].item&lt;int&gt;();</span></span>
<span id="L311"><span class="lineNum"> 311</span> : }</span>
<span id="L312"><span class="lineNum"> 312</span> <span class="tlaGNC"> 1563408 : return exactInference(evidence);</span></span>
<span id="L313"><span class="lineNum"> 313</span> <span class="tlaGNC"> 781704 : }</span></span>
<span id="L314"><span class="lineNum"> 314</span> <span class="tlaGNC"> 3734984 : double Network::computeFactor(std::map&lt;std::string, int&gt;&amp; completeEvidence)</span></span>
<span id="L315"><span class="lineNum"> 315</span> : {</span>
<span id="L316"><span class="lineNum"> 316</span> <span class="tlaGNC"> 3734984 : double result = 1.0;</span></span>
<span id="L317"><span class="lineNum"> 317</span> <span class="tlaGNC"> 72886736 : for (auto&amp; node : getNodes()) {</span></span>
<span id="L318"><span class="lineNum"> 318</span> <span class="tlaGNC"> 69151752 : result *= node.second-&gt;getFactorValue(completeEvidence);</span></span>
<span id="L319"><span class="lineNum"> 319</span> : }</span>
<span id="L320"><span class="lineNum"> 320</span> <span class="tlaGNC"> 3734984 : return result;</span></span>
<span id="L321"><span class="lineNum"> 321</span> : }</span>
<span id="L322"><span class="lineNum"> 322</span> <span class="tlaGNC"> 896208 : std::vector&lt;double&gt; Network::exactInference(std::map&lt;std::string, int&gt;&amp; evidence)</span></span>
<span id="L323"><span class="lineNum"> 323</span> : {</span>
<span id="L324"><span class="lineNum"> 324</span> <span class="tlaGNC"> 896208 : std::vector&lt;double&gt; result(classNumStates, 0.0);</span></span>
<span id="L325"><span class="lineNum"> 325</span> <span class="tlaGNC"> 896208 : std::vector&lt;std::thread&gt; threads;</span></span>
<span id="L326"><span class="lineNum"> 326</span> <span class="tlaGNC"> 896208 : std::mutex mtx;</span></span>
<span id="L327"><span class="lineNum"> 327</span> <span class="tlaGNC"> 4631192 : for (int i = 0; i &lt; classNumStates; ++i) {</span></span>
<span id="L328"><span class="lineNum"> 328</span> <span class="tlaGNC"> 3734984 : threads.emplace_back([this, &amp;result, &amp;evidence, i, &amp;mtx]() {</span></span>
<span id="L329"><span class="lineNum"> 329</span> <span class="tlaGNC"> 3734984 : auto completeEvidence = std::map&lt;std::string, int&gt;(evidence);</span></span>
<span id="L330"><span class="lineNum"> 330</span> <span class="tlaGNC"> 3734984 : completeEvidence[getClassName()] = i;</span></span>
<span id="L331"><span class="lineNum"> 331</span> <span class="tlaGNC"> 3734984 : double factor = computeFactor(completeEvidence);</span></span>
<span id="L332"><span class="lineNum"> 332</span> <span class="tlaGNC"> 3734984 : std::lock_guard&lt;std::mutex&gt; lock(mtx);</span></span>
<span id="L333"><span class="lineNum"> 333</span> <span class="tlaGNC"> 3734984 : result[i] = factor;</span></span>
<span id="L334"><span class="lineNum"> 334</span> <span class="tlaGNC"> 3734984 : });</span></span>
<span id="L335"><span class="lineNum"> 335</span> : }</span>
<span id="L336"><span class="lineNum"> 336</span> <span class="tlaGNC"> 4631192 : for (auto&amp; thread : threads) {</span></span>
<span id="L337"><span class="lineNum"> 337</span> <span class="tlaGNC"> 3734984 : thread.join();</span></span>
<span id="L338"><span class="lineNum"> 338</span> : }</span>
<span id="L339"><span class="lineNum"> 339</span> : // Normalize result</span>
<span id="L340"><span class="lineNum"> 340</span> <span class="tlaGNC"> 896208 : double sum = accumulate(result.begin(), result.end(), 0.0);</span></span>
<span id="L341"><span class="lineNum"> 341</span> <span class="tlaGNC"> 4631192 : transform(result.begin(), result.end(), result.begin(), [sum](const double&amp; value) { return value / sum; });</span></span>
<span id="L342"><span class="lineNum"> 342</span> <span class="tlaGNC"> 1792416 : return result;</span></span>
<span id="L343"><span class="lineNum"> 343</span> <span class="tlaGNC"> 896208 : }</span></span>
<span id="L344"><span class="lineNum"> 344</span> <span class="tlaGNC"> 28 : std::vector&lt;std::string&gt; Network::show() const</span></span>
<span id="L345"><span class="lineNum"> 345</span> : {</span>
<span id="L346"><span class="lineNum"> 346</span> <span class="tlaGNC"> 28 : std::vector&lt;std::string&gt; result;</span></span>
<span id="L347"><span class="lineNum"> 347</span> : // Draw the network</span>
<span id="L348"><span class="lineNum"> 348</span> <span class="tlaGNC"> 160 : for (auto&amp; node : nodes) {</span></span>
<span id="L349"><span class="lineNum"> 349</span> <span class="tlaGNC"> 132 : std::string line = node.first + &quot; -&gt; &quot;;</span></span>
<span id="L350"><span class="lineNum"> 350</span> <span class="tlaGNC"> 308 : for (auto child : node.second-&gt;getChildren()) {</span></span>
<span id="L351"><span class="lineNum"> 351</span> <span class="tlaGNC"> 176 : line += child-&gt;getName() + &quot;, &quot;;</span></span>
<span id="L352"><span class="lineNum"> 352</span> : }</span>
<span id="L353"><span class="lineNum"> 353</span> <span class="tlaGNC"> 132 : result.push_back(line);</span></span>
<span id="L354"><span class="lineNum"> 354</span> <span class="tlaGNC"> 132 : }</span></span>
<span id="L355"><span class="lineNum"> 355</span> <span class="tlaGNC"> 56 : return result;</span></span>
<span id="L356"><span class="lineNum"> 356</span> <span class="tlaGNC"> 28 : }</span></span>
<span id="L357"><span class="lineNum"> 357</span> <span class="tlaGNC"> 112 : std::vector&lt;std::string&gt; Network::graph(const std::string&amp; title) const</span></span>
<span id="L358"><span class="lineNum"> 358</span> : {</span>
<span id="L359"><span class="lineNum"> 359</span> <span class="tlaGNC"> 112 : auto output = std::vector&lt;std::string&gt;();</span></span>
<span id="L360"><span class="lineNum"> 360</span> <span class="tlaGNC"> 112 : auto prefix = &quot;digraph BayesNet {\nlabel=&lt;BayesNet &quot;;</span></span>
<span id="L361"><span class="lineNum"> 361</span> <span class="tlaGNC"> 112 : auto suffix = &quot;&gt;\nfontsize=30\nfontcolor=blue\nlabelloc=t\nlayout=circo\n&quot;;</span></span>
<span id="L362"><span class="lineNum"> 362</span> <span class="tlaGNC"> 112 : std::string header = prefix + title + suffix;</span></span>
<span id="L363"><span class="lineNum"> 363</span> <span class="tlaGNC"> 112 : output.push_back(header);</span></span>
<span id="L364"><span class="lineNum"> 364</span> <span class="tlaGNC"> 844 : for (auto&amp; node : nodes) {</span></span>
<span id="L365"><span class="lineNum"> 365</span> <span class="tlaGNC"> 732 : auto result = node.second-&gt;graph(className);</span></span>
<span id="L366"><span class="lineNum"> 366</span> <span class="tlaGNC"> 732 : output.insert(output.end(), result.begin(), result.end());</span></span>
<span id="L367"><span class="lineNum"> 367</span> <span class="tlaGNC"> 732 : }</span></span>
<span id="L368"><span class="lineNum"> 368</span> <span class="tlaGNC"> 112 : output.push_back(&quot;}\n&quot;);</span></span>
<span id="L369"><span class="lineNum"> 369</span> <span class="tlaGNC"> 224 : return output;</span></span>
<span id="L370"><span class="lineNum"> 370</span> <span class="tlaGNC"> 112 : }</span></span>
<span id="L371"><span class="lineNum"> 371</span> <span class="tlaGNC"> 408 : std::vector&lt;std::pair&lt;std::string, std::string&gt;&gt; Network::getEdges() const</span></span>
<span id="L372"><span class="lineNum"> 372</span> : {</span>
<span id="L373"><span class="lineNum"> 373</span> <span class="tlaGNC"> 408 : auto edges = std::vector&lt;std::pair&lt;std::string, std::string&gt;&gt;();</span></span>
<span id="L374"><span class="lineNum"> 374</span> <span class="tlaGNC"> 7396 : for (const auto&amp; node : nodes) {</span></span>
<span id="L375"><span class="lineNum"> 375</span> <span class="tlaGNC"> 6988 : auto head = node.first;</span></span>
<span id="L376"><span class="lineNum"> 376</span> <span class="tlaGNC"> 20312 : for (const auto&amp; child : node.second-&gt;getChildren()) {</span></span>
<span id="L377"><span class="lineNum"> 377</span> <span class="tlaGNC"> 13324 : auto tail = child-&gt;getName();</span></span>
<span id="L378"><span class="lineNum"> 378</span> <span class="tlaGNC"> 13324 : edges.push_back({ head, tail });</span></span>
<span id="L379"><span class="lineNum"> 379</span> <span class="tlaGNC"> 13324 : }</span></span>
<span id="L380"><span class="lineNum"> 380</span> <span class="tlaGNC"> 6988 : }</span></span>
<span id="L381"><span class="lineNum"> 381</span> <span class="tlaGNC"> 816 : return edges;</span></span>
<span id="L382"><span class="lineNum"> 382</span> <span class="tlaGNC"> 408 : }</span></span>
<span id="L383"><span class="lineNum"> 383</span> <span class="tlaGNC"> 364 : int Network::getNumEdges() const</span></span>
<span id="L384"><span class="lineNum"> 384</span> : {</span>
<span id="L385"><span class="lineNum"> 385</span> <span class="tlaGNC"> 364 : return getEdges().size();</span></span>
<span id="L386"><span class="lineNum"> 386</span> : }</span>
<span id="L387"><span class="lineNum"> 387</span> <span class="tlaGNC"> 220 : std::vector&lt;std::string&gt; Network::topological_sort()</span></span>
<span id="L388"><span class="lineNum"> 388</span> : {</span>
<span id="L389"><span class="lineNum"> 389</span> : /* Check if al the fathers of every node are before the node */</span>
<span id="L390"><span class="lineNum"> 390</span> <span class="tlaGNC"> 220 : auto result = features;</span></span>
<span id="L391"><span class="lineNum"> 391</span> <span class="tlaGNC"> 220 : result.erase(remove(result.begin(), result.end(), className), result.end());</span></span>
<span id="L392"><span class="lineNum"> 392</span> <span class="tlaGNC"> 220 : bool ending{ false };</span></span>
<span id="L393"><span class="lineNum"> 393</span> <span class="tlaGNC"> 628 : while (!ending) {</span></span>
<span id="L394"><span class="lineNum"> 394</span> <span class="tlaGNC"> 408 : ending = true;</span></span>
<span id="L395"><span class="lineNum"> 395</span> <span class="tlaGNC"> 3804 : for (auto feature : features) {</span></span>
<span id="L396"><span class="lineNum"> 396</span> <span class="tlaGNC"> 3396 : auto fathers = nodes[feature]-&gt;getParents();</span></span>
<span id="L397"><span class="lineNum"> 397</span> <span class="tlaGNC"> 9000 : for (const auto&amp; father : fathers) {</span></span>
<span id="L398"><span class="lineNum"> 398</span> <span class="tlaGNC"> 5604 : auto fatherName = father-&gt;getName();</span></span>
<span id="L399"><span class="lineNum"> 399</span> <span class="tlaGNC"> 5604 : if (fatherName == className) {</span></span>
<span id="L400"><span class="lineNum"> 400</span> <span class="tlaGNC"> 2980 : continue;</span></span>
<span id="L401"><span class="lineNum"> 401</span> : }</span>
<span id="L402"><span class="lineNum"> 402</span> : // Check if father is placed before the actual feature</span>
<span id="L403"><span class="lineNum"> 403</span> <span class="tlaGNC"> 2624 : auto it = find(result.begin(), result.end(), fatherName);</span></span>
<span id="L404"><span class="lineNum"> 404</span> <span class="tlaGNC"> 2624 : if (it != result.end()) {</span></span>
<span id="L405"><span class="lineNum"> 405</span> <span class="tlaGNC"> 2624 : auto it2 = find(result.begin(), result.end(), feature);</span></span>
<span id="L406"><span class="lineNum"> 406</span> <span class="tlaGNC"> 2624 : if (it2 != result.end()) {</span></span>
<span id="L407"><span class="lineNum"> 407</span> <span class="tlaGNC"> 5248 : if (distance(it, it2) &lt; 0) {</span></span>
<span id="L408"><span class="lineNum"> 408</span> : // if it is not, insert it before the feature</span>
<span id="L409"><span class="lineNum"> 409</span> <span class="tlaGNC"> 244 : result.erase(remove(result.begin(), result.end(), fatherName), result.end());</span></span>
<span id="L410"><span class="lineNum"> 410</span> <span class="tlaGNC"> 244 : result.insert(it2, fatherName);</span></span>
<span id="L411"><span class="lineNum"> 411</span> <span class="tlaGNC"> 244 : ending = false;</span></span>
<span id="L412"><span class="lineNum"> 412</span> : }</span>
<span id="L413"><span class="lineNum"> 413</span> : }</span>
<span id="L414"><span class="lineNum"> 414</span> : }</span>
<span id="L415"><span class="lineNum"> 415</span> <span class="tlaGNC"> 5604 : }</span></span>
<span id="L416"><span class="lineNum"> 416</span> <span class="tlaGNC"> 3396 : }</span></span>
<span id="L417"><span class="lineNum"> 417</span> : }</span>
<span id="L418"><span class="lineNum"> 418</span> <span class="tlaGNC"> 440 : return result;</span></span>
<span id="L419"><span class="lineNum"> 419</span> <span class="tlaGNC"> 220 : }</span></span>
<span id="L420"><span class="lineNum"> 420</span> <span class="tlaGNC"> 8 : std::string Network::dump_cpt() const</span></span>
<span id="L421"><span class="lineNum"> 421</span> : {</span>
<span id="L422"><span class="lineNum"> 422</span> <span class="tlaGNC"> 8 : std::stringstream oss;</span></span>
<span id="L423"><span class="lineNum"> 423</span> <span class="tlaGNC"> 48 : for (auto&amp; node : nodes) {</span></span>
<span id="L424"><span class="lineNum"> 424</span> <span class="tlaGNC"> 40 : oss &lt;&lt; &quot;* &quot; &lt;&lt; node.first &lt;&lt; &quot;: (&quot; &lt;&lt; node.second-&gt;getNumStates() &lt;&lt; &quot;) : &quot; &lt;&lt; node.second-&gt;getCPT().sizes() &lt;&lt; std::endl;</span></span>
<span id="L425"><span class="lineNum"> 425</span> <span class="tlaGNC"> 40 : oss &lt;&lt; node.second-&gt;getCPT() &lt;&lt; std::endl;</span></span>
<span id="L426"><span class="lineNum"> 426</span> : }</span>
<span id="L427"><span class="lineNum"> 427</span> <span class="tlaGNC"> 16 : return oss.str();</span></span>
<span id="L428"><span class="lineNum"> 428</span> <span class="tlaGNC"> 8 : }</span></span>
<span id="L429"><span class="lineNum"> 429</span> : }</span>
</pre>
</td>
</tr>
</table>
<br>
<table width="100%" border=0 cellspacing=0 cellpadding=0>
<tr><td class="ruler"><img src="../../glass.png" width=3 height=3 alt=""></td></tr>
<tr><td class="versionInfo">Generated by: <a href="https://github.com//linux-test-project/lcov" target="_parent">LCOV version 2.0-1</a></td></tr>
</table>
<br>
</body>
</html>