DEV Community

Cover image for QuantumSuperposition: a .NET library for when one value isn’t enough
hutchpd
hutchpd

Posted on

QuantumSuperposition: a .NET library for when one value isn’t enough

Most code is built on a comforting lie: that there is one correct value, right now, and everyone agrees about it.

Sometimes that’s true. Sometimes int x = 5; is exactly what the doctor ordered, and we should all go home early.

But sometimes a value is not one thing yet. It might be one of several candidates. It might depend on noisy inputs. It might live inside a search space. But sometimes a value is not one thing yet. It might be one of several candidates. It might depend on noisy inputs. It might live inside a search space. Or, for reasons that would alarm a project manager, you might actually want proper quantum-style state and gates in C#.

That’s the niche these libraries live in.

QuantumSuperposition gives you strongly typed superpositions and a proper quantum simulation layer. PositronicVariables takes some of the same machinery and points it in a much stranger direction: values can propagate backwards through execution order, so later code can influence earlier reads. One is useful for representing uncertainty and quantum-style computation. The other is useful for letting variables argue with their own future until they calm down.

The boringly useful part: keep several candidate values alive

The easiest way to understand QuantumSuperposition is not “physics,” it’s “a weighted set of possible values that you can compute over without picking one too early.”

That’s what QuBit<T> and Eigenstates<T> are doing.

You can map over possible values, filter them, combine them, do arithmetic on them, sample from them, and only collapse to a single result when you actually need one. In other words, you can stop flattening uncertainty into a lie just because your code got impatient.

using QuantumSuperposition.Core;
using QuantumSuperposition.QuantumSoup;
using QuantumSuperposition.Operators;

var candidates = new QuBit<int>(new[] { 2, 3, 4, 5, 6 });

var interesting = candidates
    .Where(x => x % 2 == 0)
    .Select(x => x * 10);

Console.WriteLine(interesting);                // still a superposition
Console.WriteLine(interesting.SampleWeighted()); // one sampled outcome
Enter fullscreen mode Exit fullscreen mode

That’s the part I suspect most people will actually use first.

Not because they’re building a quantum computer in a shoebox, but because they have a problem where “there are several plausible values here” is the honest state of the world. Search problems, candidate ranking, speculative transforms, rule systems, fuzzy pipelines, weird combinatorics, toy AI experiments, or just “I want to see all the branches before I commit.”

And because this is .NET instead of interpretive dance, you still get a nice programmer-shaped API: arithmetic, comparisons, LINQ-style Select, Where, and SelectMany, plus weighted sampling and deterministic collapse via seeded randomness or mockable collapse when your CI pipeline deserves peace for once. Haunted test suites are funny only until they’re yours.

Then there’s the actual quantum bit

The library is not just “a list with vibes.”

There’s also a proper physics-flavoured layer with QuantumSystem, tensor products, entanglement management, PhysicsQubit, QuantumRegister, built-in gates, circuit scheduling, ASCII visualisation, and algorithm helpers for things like QFT and Grover.

So if your idea of a relaxing afternoon is “let’s build a Bell pair in C# and see what happens,” you are disturbingly well catered for.

using QuantumSuperposition.Systems;

var system = new QuantumSystem();
var bell = QuantumRegister.EPRPair(system);

var measured = bell.Collapse();
Console.WriteLine(string.Join("", measured)); // 00 or 11
Enter fullscreen mode Exit fullscreen mode

You can also work at the gate level:

using QuantumSuperposition.Systems;
using QuantumSuperposition.Utilities;

var system = new QuantumSystem();

system.ApplySingleQubitGate(0, QuantumGates.Hadamard, "H");
system.ApplyTwoQubitGate(0, 1, QuantumGates.CNOT.Matrix, "CNOT");

Console.WriteLine(system.VisualiseGateSchedule(totalQubits: 2));
system.ProcessGateQueue();
Enter fullscreen mode Exit fullscreen mode

That split is part of what makes the project interesting. You can stay at the “typed superposition” layer if that’s all you need, or drop down into registers, gates, entanglement groups, canonical states, and algorithm-level tools when you want the full circuit model.

There are helpers for common states like EPR, GHZ, and W states, plus QuantumRegister for treating part of the global wavefunction as a coherent value-ish thing. You also get more than the usual gate greatest hits: controlled gates, SWAP-family gates, Toffoli, Fredkin, and QFT construction.

PositronicVariables: code that runs in the wrong direction on purpose

PositronicVariables are not mainly about “some values take a few passes to settle.” That happens, yes. But the core idea is much stranger and much more fun:

they let values propagate backwards through execution order.

Normal code runs like a stern Victorian schoolmaster. Line 1, then line 2, then line 3. Cause, then effect. Everyone in single file, no pushing.

PositronicVariables do not respect that tidy little parade.

With PVs, you can use the result of a calculation before the calculation appears in source order. If your program is lines 1, 2, 3, 4, 5, the logic can effectively flow 5, 4, 3, 2, 1. They’re the tachyon variables of the programming world: information shows up before it has any right to.

That means you can do something like print a value before the line that computes it has executed:

Console.WriteLine(answer);

answer <<= 40 + 2;
Enter fullscreen mode Exit fullscreen mode

In other words, the read on the first line can be satisfied by the assignment on the second. The program is allowed to become self-consistent across time instead of only top-to-bottom.

In ordinary programming, that is nonsense. The bad kind. The kind that gets you null, default values, exceptions, or a teammate quietly updating their CV.

With PositronicVariables, that kind of backwards causality is the point. The variable participates in a temporal dependency graph, and the system works out a self-consistent value across the whole flow rather than insisting everything must be known strictly top-to-bottom.

So the mental model is less:

“this variable needs a couple of iterations”

and more:

“this variable has received news from later in the program.”

That’s the interesting bit. The convergence machinery matters because once you allow values to leak backward in time, you need some way to make the universe stop wobbling. But that machinery is there in service of the core trick: future assignments can influence earlier reads.

That opens the door to code that feels mildly illegal in a very entertaining way:

  • declaring outputs before their derivation
  • wiring up feedback loops without immediately exploding
  • expressing circular relationships directly instead of faking them with mutable staging state
  • letting a program “discover” a consistent state across time rather than marching there in one direction

Or, put less politely: it lets your variables cheat.

That’s why the library is interesting. Not because it’s a generic fixpoint engine wearing a fake moustache, but because it experiments with a programming model where causality is negotiable. The convergence is the cleanup crew. The headline feature is that later code can reach back and affect earlier code.

Which is either a neat abstraction or an affront to God, depending on how much sleep you’ve had.

When causality breaks: Feynman diagrams for code

Once you allow information to flow backward in time, something interesting happens: you can create causal loops.

Physicists draw these using Feynman diagrams, little arrows through spacetime showing how particles interact. You can steal the same trick to understand PositronicVariables.

Take the smallest paradox we can write:

var antival = PositronicVariable<int>.GetOrCreate("antival", -1);

var val = -1 * antival;
antival.State = val;
Enter fullscreen mode Exit fullscreen mode

If you draw the causal flow, it looks like this:

Time →

[antival guess] -> val = -1 * antival -> antival = val
       ^__________________________________________|
Enter fullscreen mode Exit fullscreen mode

The value feeds back into itself.

In a normal program this is just a bad idea that ends in recursion, stack explosions, or somebody quietly deleting the code. But with PositronicVariables the engine treats it as a temporal constraint system. It replays the timeline until the loop becomes self-consistent.

Sometimes that means the system converges to a single value.

Sometimes it means the only consistent answer is multiple states at once:

antival = any(-1, 1)
val     = any(1, -1)
Enter fullscreen mode Exit fullscreen mode

The paradox doesn’t crash the program - it creates a superposition. The system couldn’t decide which timeline wins, so it keeps both.

Which is a surprisingly polite way for a runtime to handle time travel.

Why would you actually use this?

The honest answer is: not for everything.

You should still use ordinary values for ordinary values. A plain int remains one of humanity’s better ideas.

But there are a few cases where this sort of thing stops being a joke and starts being genuinely handy.

One is when you have multiple candidate states and want to compute over all of them without flattening them immediately into one guess. That’s the QuBit<T> story.

Another is when you want to prototype or teach quantum computing concepts in an ecosystem you already know. Having quantum registers, gates, entanglement, canonical states, and algorithm helpers available from C# is genuinely useful if you live in .NET and don’t fancy context-switching into a different stack every time you want to experiment.

And then there’s the weirder class of problems where you want later logic to inform earlier reads: circular definitions, feedback-heavy systems, temporal dependency graphs, or code where the most natural expression of the problem does not run neatly top-to-bottom. PositronicVariables gives that model a formal home instead of forcing you to fake it with mutable staging state and a prayer.

Also, sometimes it’s okay to build a strange library because it teaches you something. Not everything has to be another CRUD app with a motivational LinkedIn post strapped to it.

A few caveats, because humility is cheaper than bug reports

This is not a replacement for normal programming.

It is a tool for specific classes of problems: uncertainty, multi-state computation, quantum-style modelling, algorithm experimentation, and backwards-flow or convergence-heavy logic. If your use case is “I need to store a number,” congratulations, civilization has already solved that one.

It is also not magic. Multi-qubit state spaces grow explosively. Large simulations will punish your laptop for your ambition. Convergence logic is intentionally coordinated rather than “surprise, time travel is parallel now.” And if you lean into the weird parts, you are signing up for weird behaviour by design. The library is polite about it, but it is still weird.

That said, I think weird is underrated when it is honest.

Closing

I like this project because it does not pretend all uncertainty is a bug.

Sometimes “maybe” is the right value.

Sometimes several states are the truth.

Sometimes a variable should be allowed to keep its options open.

Sometimes a program is easier to express if values don’t have to arrive in strict top-to-bottom order.

QuantumSuperposition and PositronicVariables are both built around that idea, just in different directions. One lets you work with multiple possible values and quantum-style state without abandoning normal C# ergonomics. The other lets later code reach back and inform earlier reads, which is either a useful abstraction or a minor crime against causality.

Use them for search spaces, experiments, quantum toy boxes, causal weirdness, or just because you enjoy making the CLR slightly uncomfortable.

That last reason is as valid as any.

You can play with these libraries here https://github.com/hutchpd/QuantumSuperposition/ or via nuget

dotnet add package QuantumSuperposition
dotnet add package PositronicVariables
Enter fullscreen mode Exit fullscreen mode

Top comments (0)