<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://vinurad.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://vinurad.github.io/" rel="alternate" type="text/html" /><updated>2026-10-20T01:12:47+00:00</updated><id>https://vinurad.github.io/feed.xml</id><title type="html">Vinura Dhananjaya Galwaduge</title><subtitle>Notes and writeups on causal machine learning, large language models, and assorted technical work.</subtitle><author><name>Vinura Dhananjaya Galwaduge</name></author><entry><title type="html">AI and Us-1</title><link href="https://vinurad.github.io/blog/misc-other/ai-wars-1/" rel="alternate" type="text/html" title="AI and Us-1" /><published>2026-10-18T00:00:00+00:00</published><updated>2026-10-18T00:00:00+00:00</updated><id>https://vinurad.github.io/blog/misc-other/ai-wars-1</id><content type="html" xml:base="https://vinurad.github.io/blog/misc-other/ai-wars-1/"><![CDATA[<p>I recently had the chance to watch an episode from <em>X_Files</em>, which shows an AI gone rogue (S1, E7, “Ghost in the machine”). The story shows an intelligent operating system becoming sentient, and taking actions for its survival. I do not remember how I felt when I watched this when I was younger (at least 10-15 years ago). The show itself was a favourite of mine, and somehwat inspiring too. But, this time, as I watched this with my wife, it was only a bit amusing to me. Nevertheless, we agreed that it must have felt very differently to the people back then. Did we find it only amusing because AI itself has become more familiar to us? Or is it that we downplay such scenarios involving AI? or is it because we already know that it is a possibility?
Only weeks ago, HuggingFace hack happened (https://metr.org/hugging-face-incident-report-aug-2026.pdf). Frequently, researchers state the risk of AI becoming rogue, and perhaps threatening humanity. Some argue that such threats are not credible and current AI is merely mechanistic and dumb. Especially, some argue that most of these (including other claims about present AI capabilities) are only marketing tactics, inflating the facts and perhaps nothing other than result the irresponsible practices of some AI companies (https://www.youtube.com/watch?v=54Lu6_ZRF0c). As I think, If we look beyond (or maybe not beyond, just nearby) this possible threatening nature if AI, we may see that AI poses a different kind of dilemma, which is our ‘dependency’ to it, which could be a very costly one.
I believe all these ideas have already been discussed or argued about, but here are my two cents. Throughout the history, many dilemmas that the humankind faced have been of our own making. Wars and their implications are obvious examples. Certain Non-commucable diseases (except for unfortunate causes such as genetics) are another example. The unprecedented implications of AI could be just another similar example in the future. One way it could happen is due to our dependencies on it. Currently, such dependency has been created, and being reinforced as the time goes by. As intellectuals argue this may or may not create other associated problems, such as a genration of people who do not think well (cognitive dependency), the resource consumption etc. Yet, it is really difficult to get away from the dependency as well. I think the primary reason is that the efficiency boost that AI is capable bringing into economic activities does not give an incentive to turn away from it. Only a bigger incentive such as preventing a risk to human safety/health would do otherwise. Another reason for dependency is that the values individuals attribute to certain AI systems (e.g., chatbots that are seemingly intelligent), as if they have intelligent capabilities. This masks possible blind spots that they obviously possess, and perhaps strengthen with the time, and more interactions. Perhaps, just as social media/short content cater to our boredom, and anxiety in a way (and thus woresening it with time), AI might be doing that in an unseen way.
Yet, as humans try to adopt AI in safety critical tasks (such as autonomous tasks that is already using AI) more and more, there may be better chances to realize and solve those problems. On the other hand, people do not learn lessons from their past mistakes (not true to every case, but surprisingly at some disastrous cases. e.g.- wars), especially when it involves attracitve incentives. The disruptiveness (or distructiveness) of some modern age decisions are only coming into light now (unfiltered digital media and short content). Should there be a major fault of AI that pose a visible threat to humans collectively, so that more eager guardrails would be applied, and make humans rethink about the dependency to AI? or would such a case still give power to a limited set of individuals? In a next post, I’d like to think about what long term implications, interventions should there be regarding AI adoption.</p>

<p>Update (19 Oct 2026): I did not that there was a paper presenting a mathematical model of LLMs as a cognitive virus (https://arxiv.org/pdf/2609.03344). I think this is a reference to what was mentioned earlier, where AI behaves in a similar way to Social media ( in terms of cognitive impediments).</p>

<p><img src="/assets/images/xfiles-cos.png" alt="The Central Operating System (COS) panel from The X-Files, S1E7, &quot;Ghost in the Machine&quot;" /></p>

<hr />

<p><em>This post is licensed under <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">CC BY-NC-SA 4.0</a>. The X-Files still is excluded and remains the property of its copyright holder.</em></p>]]></content><author><name>Vinura Dhananjaya Galwaduge</name></author><category term="misc-other" /><summary type="html"><![CDATA[On rogue AI, and the costlier dilemma of our growing dependency on it.]]></summary></entry><entry><title type="html">CID Tutorial 1</title><link href="https://vinurad.github.io/blog/causality/cid-tutorial-1/" rel="alternate" type="text/html" title="CID Tutorial 1" /><published>2026-10-03T00:00:00+00:00</published><updated>2026-10-03T00:00:00+00:00</updated><id>https://vinurad.github.io/blog/causality/cid-tutorial-1</id><content type="html" xml:base="https://vinurad.github.io/blog/causality/cid-tutorial-1/"><![CDATA[<h1 id="introduction">Introduction</h1>

<p>Let us look at an example problem involving a causal influence diagram. The problem is about an oil widlcatter. I think that this is a popular use-case/scenario in decision sciences. The decision to drill is a high risk and a highly rewarding if successful. The problem has been studied previously in publications such as Shachter et al., 2013 (https://arxiv.org/pdf/1304.3108) and Raiffa 1968 (Decision Analysis: Introductory Lectures on Choices under Uncertainty).
Wildcatters are known as the popele who drills wildcat wells, which is a hugely risky venture but gives an advantage over others, if succeed.</p>

<figure>
<img src="/assets/images/wildcat-well.png" alt="A drilling crew working on the rig floor of an oil well" />
<figcaption>Figure 1. A drilling crew at work on the rig floor, 1944. Image source: <a href="https://www.sciencedirect.com/topics/engineering/wildcat-wells">“Wildcat Wells”, ScienceDirect Topics, Elsevier</a> (accessed 18 Oct 2026).</figcaption>
</figure>

<h1 id="problem-setup">Problem Setup</h1>

<p>The wildcatter must make a decision to drill (or not) a particular location for oil. There is a test result that provides some information about the presence of oil. However, the test result can be 10% wrong. There is also the chance that oil will not be there at all (60%). The cost of the test is 10 (xe6, USD. For ease, 10 units). If they drill, the reward of finding oil is 100 units, and the loss is -40 units if they do not find it. There is no reward for not drilling (except for the cost of the test that they decide to do the it and do nothing afterward).
The test can also be decided to taken or not (considering its cost). The decision to drill is based on the knowledge that the test was done or not (‘sufficient recall’).</p>

<figure class="cid">
<svg viewBox="0 0 560 260" width="560" role="img" aria-labelledby="cid-t cid-d" xmlns="http://www.w3.org/2000/svg">
<title id="cid-t">Causal influence diagram of the oil wildcatter problem</title>
<desc id="cid-d">Decision nodes T (test) and D (drill) are rectangles, chance nodes R (test result) and O (oil) are circles, and the utility nodes C (test cost) and U (payoff) are diamonds. Arrows run from T to R, T to C, O to R, T to D, R to D, D to U and O to U. The arrows into D are dashed information links.</desc>
<style>
.cid { color: var(--ink); }
.cid svg { max-width: 100%; height: auto; overflow: visible; }
.cid .node { fill: var(--paper); stroke: currentColor; stroke-width: 2; }
.cid .dec  { fill: var(--hover); }
.cid .util { fill: var(--hover); stroke: var(--accent); }
.cid .edge { fill: none; stroke: currentColor; stroke-width: 1.6; }
.cid .info { stroke-dasharray: 5 4; }
.cid .head { fill: currentColor; }
.cid .lab  { fill: currentColor; font-family: var(--serif); font-style: italic; font-size: 24px; }
.cid .name { fill: var(--muted); font-family: var(--mono); font-size: 12px; }
</style>
<defs>
<marker id="cid-arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="8" markerHeight="8" orient="auto">
<path class="head" d="M 0 0 L 10 5 L 0 10 Z" />
</marker>
</defs>

<!-- edges -->
<path class="edge" d="M 126 70 H 252" marker-end="url(#cid-arrow)" />
<path class="edge" d="M 442 70 H 308" marker-end="url(#cid-arrow)" />
<path class="edge info" d="M 125 94 L 245 176" marker-end="url(#cid-arrow)" />
<path class="edge info" d="M 280 98 V 176" marker-end="url(#cid-arrow)" />
<path class="edge" d="M 316 200 H 436" marker-end="url(#cid-arrow)" />
<path class="edge" d="M 470 98 V 166" marker-end="url(#cid-arrow)" />
<path class="edge" d="M 90 94 V 166" marker-end="url(#cid-arrow)" />

<!-- decision nodes -->
<rect class="node dec" x="54" y="46" width="72" height="48" rx="2" />
<text class="lab" x="90" y="78" text-anchor="middle">T</text>
<text class="name" x="90" y="34" text-anchor="middle">test</text>

<rect class="node dec" x="244" y="176" width="72" height="48" rx="2" />
<text class="lab" x="280" y="208" text-anchor="middle">D</text>
<text class="name" x="280" y="246" text-anchor="middle">drill</text>

<!-- chance nodes -->
<circle class="node" cx="280" cy="70" r="28" />
<text class="lab" x="280" y="78" text-anchor="middle">R</text>
<text class="name" x="280" y="30" text-anchor="middle">result</text>

<circle class="node" cx="470" cy="70" r="28" />
<text class="lab" x="470" y="78" text-anchor="middle">O</text>
<text class="name" x="470" y="30" text-anchor="middle">oil</text>

<!-- utility nodes -->
<path class="node util" d="M 90 166 L 124 200 L 90 234 L 56 200 Z" />
<text class="lab" x="90" y="208" text-anchor="middle">C</text>
<text class="name" x="90" y="254" text-anchor="middle">cost</text>

<path class="node util" d="M 470 166 L 504 200 L 470 234 L 436 200 Z" />
<text class="lab" x="470" y="208" text-anchor="middle">U</text>
<text class="name" x="470" y="254" text-anchor="middle">payoff</text>
</svg>
<figcaption>Figure 2. Causal influence diagram of the oil wildcatter problem. Rectangles are decisions, circles are chance nodes, diamonds are utilities. Dashed arrows are information links.</figcaption>
</figure>

<h1 id="the-optimal-decisions">The optimal decisions</h1>

<p>Let us first calculate the expected utilities of drill/not drill for the scenario where they decide to do the test and it comes back as positive (oil present) (T=1, R=1).
In order to compar the expected utilitites, it is sufficient to compare only the joint probabilities of events. Because, 
\(P(w \mid Pa(D))=P(w,Pa(D))/P(Pa(D))\). We would try to find the conditional probabilities of \(w\) (the unobserved world) given the available information for the decisions (\(Pa(D)\). Here, it would be the situation where we calculate the possibility of oil being actually present, based on the test results. When we compute these for each decision at our decision node (here, drill or not drill) the normalizing \(P(Pa(D))\) will be similar, which can be ignored for <em>comparison</em>. However, to calculate the actual utilites the normalizing step must be done.</p>

\[\begin{aligned}
E(U\_drill) &amp;= 100*0.9*0.4+(-40)*0.1*0.6=33.6 \\
E(U\_not\_drill) &amp;= 0
\end{aligned}\]

<p>Now, if T=1, R=0 (test returns negative),</p>

\[\begin{aligned}
E(U\_drill) &amp;= (-40)*0.9*0.6+100*0.1*0.4=-17.6 \\
E(U\_not\_drill) &amp;= 0
\end{aligned}\]

<p>Here, regardless of the decision, there is always the cost of the test (-10). We can also ignore it as it is common for every decision.
Comparing these unnormalized utilities, it seems that it is the best to <em>trust the test result always</em>.</p>]]></content><author><name>Vinura Dhananjaya Galwaduge</name></author><category term="causality" /><summary type="html"><![CDATA[A causal influence diagram for the oil wildcatter problem, and its optimal decisions.]]></summary></entry><entry><title type="html">Notes on causality in games</title><link href="https://vinurad.github.io/blog/causality/Notes-on-causality-in-games/" rel="alternate" type="text/html" title="Notes on causality in games" /><published>2026-09-30T00:00:00+00:00</published><updated>2026-09-30T00:00:00+00:00</updated><id>https://vinurad.github.io/blog/causality/Notes-on-causality-in-games</id><content type="html" xml:base="https://vinurad.github.io/blog/causality/Notes-on-causality-in-games/"><![CDATA[<h1 id="introduction">Introduction</h1>
<p>This is an evolving note, primarily based on the work <a href="https://www.sciencedirect.com/science/article/pii/S0004370223000656?via%3Dihub">“Reasoning about causality in games (Hammond et al.)”</a>.</p>

<h1 id="key-points">Key points</h1>

<p>The parts up until section 2.2 describes the problem and an introduction to Structural Causal Models (SCM) and Pearl’s hierarchy of causality.</p>

<h2 id="maids">MAIDs</h2>

<p>An ID (Influence Diagram) generalizes a BN by introducing decision and utility variables. A MAID (Multi Agent ID) extends it to a scenario with multiple agents. At the core, this captures an EFG in a more compact way (the branches in EFG captured in the nodes and their associated CPDs). There are chance nodes, decision nodes and utility nodes.  The decision nodes describe decisions (or actions) made by agents, either as deterministic rules or stochastic rules. A decision rule is denoted as a CPD (below),</p>

\[\pi_D(D|Pa_D)\]

<p>A Nash Equilibrium describes the best response decision rule of an agent to those of other agents, and the parameters of the game (chance variables).</p>

<h1 id="s-relevance-and-s-reacheabiliy">s-relevance and s-reacheabiliy</h1>
<p>s=strategically. s-relevance tells if a particular decision rule impact another decision rule, i.e- changing one gives incentive to change the other or strategically relevant. s-reacheability tests if a 
This has a similar notion to d-connectedness in causal graphs.</p>

<h1 id="mechanized-maids">Mechanized MAIDs</h1>

<ol>
  <li>Call $V$ the variables (nodes) in MAIDs. Mechanized MAIDS (MMAIDs) add a new variable set $M$, and $m_v in M$ are parents of each $v \in V$ (where necessary).</li>
  <li>Each $m_v$ is either a decision rule variable $\Pi_D$ or a parameter variable $\Theta_V$.</li>
  <li>A mechanized graph $\mathcal mG$ is simply the MAID plus $m_v$ and extra edges from $M_V \to V$ and edges within $m_v$ ($E’$, not self loops, but may have cycles).</li>
  <li>The decision rule variables are policies that determine the actions (decisions) at the decision nodes (or the probability distribution of them). For example, a policy tells to always take a particular decision if some condition is met.</li>
</ol>

\[P(d|pa_D,\Pi_D=\pi_D)=\pi_D(d|pa_D)\]

<p>With this addition, we can intervene over the CPDs of the decision variables, unlike the given CPDs in MAIDs.</p>
<ol>
  <li>The mechanisms that sets utilities and the chance are parameters; $dom(U) \in \mathbb R$.</li>
</ol>

<p>The addition of new variables now allow to model the changes of an agent’s policy (how they pick decisions) and the impact of those changes to other agent’s policies. For example, $\Pi_D=\hat\pi_D$ can be a certain rule, where the agent ‘always go regardless of their laziness’ (the example EFG describes the chance variable parameterizing lazy/hardworking).</p>

<h1 id="independent-mmaids">Independent MMAIDs</h1>

<ol>
  <li>Denoted by $\mathcal m \perp G$, removes all $E’$ edges. Mechanisms are independent (i.e. similar to non-requisite variables in BN).</li>
  <li>Strategic play in games break this independence. Because in reality agents respond to the changes in mechanisms.</li>
</ol>

<h1 id="rationality-relation">Rationality relation</h1>

<p>Described as a function $r_D(pa_{\Pi_D})$, describes the set of acceptable decision rules $\pi_D$</p>

<h1 id="r-rational-response-and-outcome">R-rational response and outcome</h1>

<p>R-rational response is any $\pi_D \in r_D(pa_{\Pi_D})$. R-rational outcome describes a profile <strong>$\pi$</strong>, in which every $\pi_D$ is the rational response.</p>

<h1 id="pycid-examples">PyCID Examples</h1>

<p>The repository https://github.com/causalincentives/pycid has implemented the MMAIDs and contains a few examples.</p>]]></content><author><name>Vinura Dhananjaya Galwaduge</name></author><category term="causality" /><summary type="html"><![CDATA[Introduction This is an evolving note, primarily based on the work “Reasoning about causality in games (Hammond et al.)”. Key points The parts up until section 2.2 describes the problem and an introduction to Structural Causal Models (SCM) and Pearl’s hierarchy of causality. MAIDs An ID (Influence Diagram) generalizes a BN by introducing decision and utility variables. A MAID (Multi Agent ID) extends it to a scenario with multiple agents. At the core, this captures an EFG in a more compact way (the branches in EFG captured in the nodes and their associated CPDs). There are chance nodes, decision nodes and utility nodes. The decision nodes describe decisions (or actions) made by agents, either as deterministic rules or stochastic rules. A decision rule is denoted as a CPD (below), \[\pi_D(D|Pa_D)\] A Nash Equilibrium describes the best response decision rule of an agent to those of other agents, and the parameters of the game (chance variables). s-relevance and s-reacheabiliy s=strategically. s-relevance tells if a particular decision rule impact another decision rule, i.e- changing one gives incentive to change the other or strategically relevant. s-reacheability tests if a This has a similar notion to d-connectedness in causal graphs. Mechanized MAIDs Call $V$ the variables (nodes) in MAIDs. Mechanized MAIDS (MMAIDs) add a new variable set $M$, and $m_v in M$ are parents of each $v \in V$ (where necessary). Each $m_v$ is either a decision rule variable $\Pi_D$ or a parameter variable $\Theta_V$. A mechanized graph $\mathcal mG$ is simply the MAID plus $m_v$ and extra edges from $M_V \to V$ and edges within $m_v$ ($E’$, not self loops, but may have cycles). The decision rule variables are policies that determine the actions (decisions) at the decision nodes (or the probability distribution of them). For example, a policy tells to always take a particular decision if some condition is met. \[P(d|pa_D,\Pi_D=\pi_D)=\pi_D(d|pa_D)\] With this addition, we can intervene over the CPDs of the decision variables, unlike the given CPDs in MAIDs. The mechanisms that sets utilities and the chance are parameters; $dom(U) \in \mathbb R$. The addition of new variables now allow to model the changes of an agent’s policy (how they pick decisions) and the impact of those changes to other agent’s policies. For example, $\Pi_D=\hat\pi_D$ can be a certain rule, where the agent ‘always go regardless of their laziness’ (the example EFG describes the chance variable parameterizing lazy/hardworking). Independent MMAIDs Denoted by $\mathcal m \perp G$, removes all $E’$ edges. Mechanisms are independent (i.e. similar to non-requisite variables in BN). Strategic play in games break this independence. Because in reality agents respond to the changes in mechanisms. Rationality relation Described as a function $r_D(pa_{\Pi_D})$, describes the set of acceptable decision rules $\pi_D$ R-rational response and outcome R-rational response is any $\pi_D \in r_D(pa_{\Pi_D})$. R-rational outcome describes a profile $\pi$, in which every $\pi_D$ is the rational response. PyCID Examples The repository https://github.com/causalincentives/pycid has implemented the MMAIDs and contains a few examples.]]></summary></entry><entry><title type="html">Connections Of Ope To Causal Theory</title><link href="https://vinurad.github.io/blog/Connections-of-OPE-to-Causal-Theory/" rel="alternate" type="text/html" title="Connections Of Ope To Causal Theory" /><published>2026-09-13T00:00:00+00:00</published><updated>2026-09-13T00:00:00+00:00</updated><id>https://vinurad.github.io/blog/Connections-of-OPE-to-Causal-Theory</id><content type="html" xml:base="https://vinurad.github.io/blog/Connections-of-OPE-to-Causal-Theory/"><![CDATA[]]></content><author><name>Vinura Dhananjaya Galwaduge</name></author><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">Identifiability of Causes</title><link href="https://vinurad.github.io/blog/causality/Identifiability-of-Causes/" rel="alternate" type="text/html" title="Identifiability of Causes" /><published>2026-09-12T00:00:00+00:00</published><updated>2026-09-12T00:00:00+00:00</updated><id>https://vinurad.github.io/blog/causality/Identifiability-of-Causes</id><content type="html" xml:base="https://vinurad.github.io/blog/causality/Identifiability-of-Causes/"><![CDATA[<h1 id="introduction">Introduction</h1>

<p>This was written based on one of the exercises (problem 3.8) from the book “Elements of Causal Inference: Foundations and Learning Algorithms” by Jonas Peters, Dominik Janzing and Bernhard Scholkopf, which is a great read on the foundations of causal theory. The problem descirbes two random variables that can belong to one of two possible Structural Causal Models (SCM).</p>

\[\begin{aligned}
X &amp;:= Y + N_X \\
Y &amp;:= N_Y
\end{aligned}
\qquad \text{(SCM 1)}\]

<p>or,</p>

\[\begin{aligned}
X &amp;:= M_X \\
Y &amp;:= X + M_Y
\end{aligned}
\qquad \text{(SCM 2)}\]

<p>In each SCM, the parent and the child are different (the cause and the effect are reversed). Also, both SCMs have the exogeneous noise variables ($N_X, N_Y, M_X, M_Y$) following different Gaussian distributions (i.e.- different means and variances that are non zero). The problem is if we can identify which is the cause and effect, only using interventions. We do not know the nature of the noise distributions at all (i.e.- the parameter values are unknown).
To quickly state what an intervention is; we intervene on a desired random variable by changing its value. Theoretically, there are two main ways how this can be done (hard, soft). Here, hard interventions (directly setting a random variable to a specific, known value) matter.</p>

<h1 id="solution">Solution</h1>

<p>Below is one possible real world example.</p>

<figure class="gxy">
<svg viewBox="0 0 560 250" width="560" role="img" aria-labelledby="gxy-t gxy-d" xmlns="http://www.w3.org/2000/svg">
<title id="gxy-t">Two light globes, X and Y, connected by a wire</title>
<desc id="gxy-d">Two light globes joined by a wire, each glowing at a randomly varying intensity. The left globe is labelled X and the right globe is labelled Y.</desc>
<style>
.gxy { color: var(--ink); --gxy-glow: #F2B544; }
.gxy svg { max-width: 100%; height: auto; overflow: visible; }
.gxy .line { fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.gxy .base { fill: var(--paper); stroke: currentColor; stroke-width: 2; }
.gxy .lab  { fill: currentColor; font-family: var(--serif); font-style: italic; font-size: 30px; }
.gxy .lit  { fill: var(--gxy-glow); }
.gxy .fil  { fill: none; stroke: var(--gxy-glow); stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
.gxy .a { animation: gxy-a 4.3s ease-in-out infinite; }
.gxy .b { animation: gxy-b 6.1s ease-in-out infinite -2.2s; }
@keyframes gxy-a {
  0% {opacity:.15} 9% {opacity:.85} 17% {opacity:.35} 31% {opacity:.95} 44% {opacity:.2}
  52% {opacity:.6} 68% {opacity:.1} 79% {opacity:.9} 91% {opacity:.4} 100% {opacity:.15}
}
@keyframes gxy-b {
  0% {opacity:.7} 13% {opacity:.2} 22% {opacity:.9} 36% {opacity:.45} 47% {opacity:.05}
  58% {opacity:.8} 71% {opacity:.3} 84% {opacity:1} 93% {opacity:.25} 100% {opacity:.7}
}
@media (prefers-reduced-motion: reduce) {
  .gxy .a, .gxy .b { animation: none; opacity: .6; }
}
</style>
<defs>
<radialGradient id="gxy-halo">
<stop offset="0" stop-color="#F2B544" stop-opacity=".55" />
<stop offset="1" stop-color="#F2B544" stop-opacity="0" />
</radialGradient>
</defs>
<path class="line" d="M 150 184 C 150 236 410 236 410 184" />
<g transform="translate(150 110)">
<circle class="a" cx="0" cy="-14" r="92" fill="url(#gxy-halo)" />
<path class="lit a" fill-opacity=".6" d="M -30 34 C -30 20 -46 8 -46 -14 A 46 46 0 1 1 46 -14 C 46 8 30 20 30 34 Z" />
<path class="line" d="M -10 34 V 4 M 10 34 V 4 M -10 4 l 5 -9 l 5 9 l 5 -9 l 5 9" />
<path class="fil a" d="M -10 4 l 5 -9 l 5 9 l 5 -9 l 5 9" />
<path class="line" d="M -30 34 C -30 20 -46 8 -46 -14 A 46 46 0 1 1 46 -14 C 46 8 30 20 30 34 Z" />
<rect class="base" x="-30" y="34" width="60" height="10" rx="2" />
<rect class="base" x="-26" y="44" width="52" height="8" />
<rect class="base" x="-26" y="52" width="52" height="8" />
<rect class="base" x="-26" y="60" width="52" height="8" />
<path class="base" d="M -14 68 H 14 L 6 74 H -6 Z" />
<text class="lab" x="-82" y="-6" text-anchor="middle">X</text>
</g>
<g transform="translate(410 110)">
<circle class="b" cx="0" cy="-14" r="92" fill="url(#gxy-halo)" />
<path class="lit b" fill-opacity=".6" d="M -30 34 C -30 20 -46 8 -46 -14 A 46 46 0 1 1 46 -14 C 46 8 30 20 30 34 Z" />
<path class="line" d="M -10 34 V 4 M 10 34 V 4 M -10 4 l 5 -9 l 5 9 l 5 -9 l 5 9" />
<path class="fil b" d="M -10 4 l 5 -9 l 5 9 l 5 -9 l 5 9" />
<path class="line" d="M -30 34 C -30 20 -46 8 -46 -14 A 46 46 0 1 1 46 -14 C 46 8 30 20 30 34 Z" />
<rect class="base" x="-30" y="34" width="60" height="10" rx="2" />
<rect class="base" x="-26" y="44" width="52" height="8" />
<rect class="base" x="-26" y="52" width="52" height="8" />
<rect class="base" x="-26" y="60" width="52" height="8" />
<path class="base" d="M -14 68 H 14 L 6 74 H -6 Z" />
<text class="lab" x="82" y="-6" text-anchor="middle">Y</text>
</g>
</svg>
</figure>

<p>Suppose there are two electric light globes, which is connected to each other through some unknown circuitry. Their light intensity appears to be random, and we can measure it. Unknown to us, one globe’s light intensity controls the other (we do not know which controls which). We only know that the control mechansim could be either one of the above SCMs. Also, we can manually set the intensity of a globe to a fixed value (an intervention). We cannot know (even my measuring) their original distributions, and only measure after an intervention. The goal is to find which one is the unknown mechansim. Note that, this example forces the mean values of the distributions to be positive as the light intensity must be some positive (or zero) value, but I believe the example works fine.
First, we shall set the intensity of Y to 2 (i.e.- \(\mathrm{do}(Y=2)\), and the units are measured with some standard intensity unit). We would then measure the light intensity of X by taking many samples. If the mechanism follows SCM 1, X would show a different distribution than its original (unintervened on Y) distribution. If it follows SCM 2, then X will not change its original distribution. Unfortunately, we cannot still distinguish between the two scenarios as we do not have any knowledge what those different distributions should look like, as we do not know their original distributions.</p>

\[\begin{aligned}
Y &amp;:= 2 \\
X &amp;:= 2 + N_X
\end{aligned}
\qquad \text{(SCM 1)}\]

\[\begin{aligned}
X &amp;:= M_X \\
Y &amp;:= 2
\end{aligned}
\qquad \text{(SCM 2)}\]

<p>In each of the above equations, the non-intervened variable $X$ still follows a normal distribution (mean shifted), which cannot be distinguished from each other as we do not know the original distribution parameters.
Now, let’s do another intervention (\(\mathrm{do}(Y=3)\)). This time however, we can observe and measure a difference. In SCM 2, $X$ will still follow its original distribution, while SCM 1 will show a mean shift from the previous intervened distribution.</p>

\[\begin{aligned}
P_{\text{SCM}_1}\big(X \mid \mathrm{do}(Y=3)\big) &amp;\neq P_{\text{SCM}_1}\big(X \mid \mathrm{do}(Y=2)\big) \\
P_{\text{SCM}_2}\big(X \mid \mathrm{do}(Y=3)\big) &amp;= P_{\text{SCM}_2}\big(X \mid \mathrm{do}(Y=2)\big)
\end{aligned}\]

<p>This is similar to an increase in the average light intensity in our example. Practically, this second intervention could be done as a drastic change of the value, so that the change is visible to the eye.</p>]]></content><author><name>Vinura Dhananjaya Galwaduge</name></author><category term="causality" /><summary type="html"><![CDATA[How to identify causal effects from distributions]]></summary></entry><entry><title type="html">Vllm On Hpc</title><link href="https://vinurad.github.io/blog/vLLM-on-HPC/" rel="alternate" type="text/html" title="Vllm On Hpc" /><published>2026-09-07T00:00:00+00:00</published><updated>2026-09-07T00:00:00+00:00</updated><id>https://vinurad.github.io/blog/vLLM-on-HPC</id><content type="html" xml:base="https://vinurad.github.io/blog/vLLM-on-HPC/"><![CDATA[]]></content><author><name>Vinura Dhananjaya Galwaduge</name></author><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">pwnable.kr - random</title><link href="https://vinurad.github.io/blog/misc-tech/pwnable-random/" rel="alternate" type="text/html" title="pwnable.kr - random" /><published>2026-02-15T00:00:00+00:00</published><updated>2026-02-15T00:00:00+00:00</updated><id>https://vinurad.github.io/blog/misc-tech/pwnable-random</id><content type="html" xml:base="https://vinurad.github.io/blog/misc-tech/pwnable-random/"><![CDATA[<p>This is the 4th challenge in ‘Tolddler’s Bottle’ in pwnable.kr. The ‘rand()’ function is supposed to generate pseudo-random numbers when a seed is given. The thing with psuedo-random number generators (PRNG, such as rand()) is that they provide deterministic outputs for a given seed. Usually, ‘stdlib.h’ is required to properly declare rand(). The given code does not contain it - hence a compiler warning is raised.</p>

<p><img src="/assets/images/pwn-1-1.png" alt="Compiler warning for implicit declaration" /></p>

<p>Then how does rand() work? If the linker can correctly match it during the runtime, rand() runs. In fact since the implicit assumption of a function call matches rand() implementation (the output is int and the function call is rand(void)), it runs. However, in the process, the seed does not change. The results is the random value is the same each time (not random!). This value can be obtained as below.</p>

<p><img src="/assets/images/pwn-1-2.png" alt="The deterministic value of the varaible 'random'" /></p>

<p>The goal is to uncover the flag by using the correct key. In this case,
\(\mathrm{key} \oplus \mathrm{random} = \mathtt{0xcafebabe}\)
\(\mathrm{key} = \mathtt{0xcafebabe} \oplus \mathrm{random}\)</p>

<p>This is because, XOR operation’s identity property (XOR’ing the same variable is just unit). The returned value is 0xa175ffd9. We are supposed to provide a decimal as the input to the program. However, a caveat is that although the key is initially declared as an ‘unsigned int’, the ‘scanf’ reads the input as a ‘signed int’ (‘%d’). The decimal of the previous 0xa175ffd9 is 2708864985. This is larger than the max. positive for 32-bit signed integers. If we use an online tool like ‘rapidtables’(https://www.rapidtables.com/convert/number/hex-to-decimal.html), it shows the 2’s complement of an input value as well. In this case, the 2’s complement of 2708864985 is -1586102311. The ‘scanf’ function would store the value corresponding to the 2’s complement of -1586102311, if we give it as the input to the program. Also, this value is in range of the 32 bit signed ints. 
This reminds me of something one of my instructors said; “The bits do not have any inherent meaning, but the meaning we give them”. Giving this negative value as the input to the program will reveal the flag.</p>

<p><img src="/assets/images/pwn-1-3.png" alt="Flag" /></p>]]></content><author><name>Vinura Dhananjaya Galwaduge</name></author><category term="misc-tech" /><summary type="html"><![CDATA[Solving the random challenge from Toddler's Bottle.]]></summary></entry><entry><title type="html">Fail2Ban</title><link href="https://vinurad.github.io/blog/misc-tech/fail2ban/" rel="alternate" type="text/html" title="Fail2Ban" /><published>2026-01-31T00:00:00+00:00</published><updated>2026-01-31T00:00:00+00:00</updated><id>https://vinurad.github.io/blog/misc-tech/fail2ban</id><content type="html" xml:base="https://vinurad.github.io/blog/misc-tech/fail2ban/"><![CDATA[<h1 id="fail2ban">Fail2Ban</h1>

<p>A while ago I noticed that the humble linux server in my lab had received many unauthorized connection attempts. Hence, I</p>]]></content><author><name>Vinura Dhananjaya Galwaduge</name></author><category term="misc-tech" /><summary type="html"><![CDATA[Blocking repeated unauthorised connection attempts on a server.]]></summary></entry><entry><title type="html">GCP Backups</title><link href="https://vinurad.github.io/blog/misc-tech/gcp-backups/" rel="alternate" type="text/html" title="GCP Backups" /><published>2026-01-21T00:00:00+00:00</published><updated>2026-01-21T00:00:00+00:00</updated><id>https://vinurad.github.io/blog/misc-tech/gcp-backups</id><content type="html" xml:base="https://vinurad.github.io/blog/misc-tech/gcp-backups/"><![CDATA[<h1 id="gcp-backups">GCP Backups</h1>

<p>I wanted to get a backup of a server image that was already running.</p>

<p>GCP usually retains the backups. The default setting for disk encryption is using GCP owned keys.</p>

<p>We can provide custom encryption keys and perform disk encryption with it.</p>

<p>Create the image and send it to a GCP bucket.</p>

<p>The image file can be downloaded from the GCP bucket.</p>]]></content><author><name>Vinura Dhananjaya Galwaduge</name></author><category term="misc-tech" /><summary type="html"><![CDATA[Imaging a running server and handling disk encryption keys on GCP.]]></summary></entry><entry><title type="html">Hodge Laplacian Operator</title><link href="https://vinurad.github.io/blog/misc-tech/hodge-laplacian/" rel="alternate" type="text/html" title="Hodge Laplacian Operator" /><published>2025-12-25T00:00:00+00:00</published><updated>2025-12-25T00:00:00+00:00</updated><id>https://vinurad.github.io/blog/misc-tech/hodge-laplacian</id><content type="html" xml:base="https://vinurad.github.io/blog/misc-tech/hodge-laplacian/"><![CDATA[<h1 id="introduction">Introduction</h1>
<p>The Hodge-Laplacian (HL) operator is a generalization of the node (graph) Laplacian operator. Below are some key ideas related to the HL operator.</p>

<h2 id="simplices">Simplices</h2>
<p>Simplices are the structural building blocks of a graph. A 0-dimensional simplex is a node, and a 1-dimensional simplex is an edge connecting two nodes.</p>

<h2 id="boundary-operators-on-a-graph">Boundary operators on a graph</h2>
<p>Boundary operators take two simplices as the inputs, and represent a relationship between those two simplices (e.g., a node and an edge). Let us denote boundary operators by $B_k$. Here, $k=1$ would mean that it would take a max dimension of 1 for one of the input simplices (an edge). The other would be 0 dimensional (a node). The $B_1$ operator on vertex $i$ and an edge $e$ would look like below,</p>

\[(B_1)_{i,e} =
\begin{cases}
1 &amp; \text{if } i \text{ is the tail of edge } e \\
-1 &amp; \text{if } i \text{ is the head of edge } e \\
0 &amp; \text{otherwise}
\end{cases}\]

<p>Applying a boundary operator on a node signal (feature) would return</p>

<h2 id="graph-laplacians">Graph Laplacians</h2>
<p>Graph Laplacian or node Laplacian (unnormalized) ($L$) is known as $L=D-A$. $L$ is taken as the difference of the degree matrix $D$ and the adjacency matrix $A$. It can also be observed that $L=B_1B_1^T$. The graph Laplacian operator can be understood as an operator that filters (specifically, a low-pass filter) that operates on the node level, and smooth the node level signals (representations) throughout the graph.</p>

<h1 id="hodge-laplacian">Hodge Laplacian</h1>
<p>Hodge Laplacian is a ‘higher-order generalization’ of graph laplcian [1]. While the node Laplacian operates at the node level, the Hodge Laplacian operates at edge level and beyond.</p>

<h2 id="hl-operator">HL operator</h2>
<p>HL operator is also a type of Laplacian operator. It is formally defined as $\mathcal{L}<em>k=B</em>{k+1}B_{k+1}^T+B_k^TB_k$. When $k=0$, $\mathcal{L_0}$ becomes the node Laplacian operator that operates on node signals. When $k=1$, HL becomes an operator at edge level and the triangle (2-dimensional simplices) level. While the node Laplacian operates on node signals (or nodes), the HL operator works at higher levels structures such as edges, or triangles and their signals. In other words, HL operators can act on more complex graph structural relationships (in general) such as node-edge, edge-edge or edge-triangle relationships while the node Laplacian is limited to node-node level.</p>

<h2 id="references">References</h2>
<p>[1] - Hodge Laplacians on Graphs, Lek-Heng Lim, https://www.stat.uchicago.edu/~lekheng/work/psapm.pdf</p>]]></content><author><name>Vinura Dhananjaya Galwaduge</name></author><category term="misc-tech" /><summary type="html"><![CDATA[Simplices, boundary operators, and generalising the graph Laplacian.]]></summary></entry></feed>