How to achieve complex (cyclic) Markov chains?

We have a table full of data points that gets populated as the user interacts with the application. We call it “behaviors.” I did an analysis of the series of behaviors to see what the typical flows are. By treating each behavior as a node, I can tell the probability of going to each of the possible next nodes. I broke it down into series of three nodes, or “When the user went from A to B, odds are they will go to C.” It is not quite a Markov chain, but it is valid.

But looking at the randomSwitch documentation, it specifically says that “cyclic graphs are not supported.” While I could go from three nodes down to two, to make it more like a classical Markov chain, I definitely need cycles. How would you model that?

One obvious but painful option is to build a chain for every distinct flow, and put an appropriate percentage attached to each one. But I’m not keen on that, as it will not give me unexpected or unique flows, and will introduce a level of complexity that probably is not warranted.

So, how have you accomplished something like this in the past?

You can’t use simple randomSwitch for this as the decisions are both random and depending on the path.

You can do something like this:

// compute the next node to go to, depending on the path
val goto: Expression[Session] = ???

// store in the Session a stack of nodes so you now where vu have been
def logPath(node: String): Expression[Session] = ???

asLongAs(continue) {
doSwitch("${goto}") (
“A” => exec(nodeA).exec(logPath(“A”)).exec(goto),
“B” => exec(nodeB).exec(logPath(“B”)).exec(goto),
“C” => exec(nodeC).exec(logPath(“C”)).exec(goto)
)
}

I figured I would do something along those lines.

Out of curiosity, if I were to store a reference to a chain in a session variable, would it be possible to execute it? I’m thinking not, based on how I understand the DSL to work, but it would seem so much more efficient than using a doSwitch.

No.