I'm dealing with a state machine that is currently traversed via Dijkstra's algorithm. However, now I need to enhance that state machine to be "smarter" in how it figures out routes to account for some side-effects. Basically some paths are not traversable if certain requirements aren't met, even if you're in the correct starting state for that path. These requirements can be satisfied by traversing other paths first. A simplified example of what I'm trying to address is traveling between cities:
- You can travel domestically without your passport (just a basic ID) (i.e. Philly -> NYC)
- As soon as you need to travel internationally, you need your passport (NYC -> Paris)
- If you already have your passport, you can travel internationally (NYC -> Paris)
- If you don't, you need to travel home first to take it (NYC -> Philly -> NYC -> Paris)
An alternative example (that I'm actually dealing with) is website states and the concept of being logged in and logged out).
There are 2 approaches I'm thinking of:
- Composing states (i.e. having passport is itself a secondary state that can be combined with "location" states), this sounds like it would add a whole other dimension to my state machine and I'm not sure whether it would make the algorithm a mess.
- Conditional paths that are only available if certain property is set while being in a state (a somewhat Bayesian approach), this would effectively make my states "impure", where transition taken would depend on internal state properties, so I prefer the composing states approach instead.
Is there a clean way to represent this via graph theory? Is there a general case algorithm that can deal with this preliminary requirement for being able to traverse a path? This problem is basically a 2-stage Dijkstra's search where you must visit a certain node first, but that node doesn't need to be visited if you already satisfy the "has passport" condition.
Given these facts
where a
connectionhas argumentsfrom,to,passport neededand these test cases
Here is the solution using prolog. This code was written as a proof of concept to see how to answer the question. It was not written to the specs of the question so if you know Prolog you will find the obvious places where it can be improved or doesn't implement an algorithm as expected.
When the test case are run
All the test pass.
The reason the passport is in Harrisburg instead of Philly is that in testing the code, the code worked when the passport was in Philly. Then by adding Harrisburg and testing again a problem was uncovered in the code and fixed. If one changes
passport(harrisburg).topassport(philly).the code will work but requires additional test cases.Further questions posted in comments and moved here.
From grodzi
Nice to see someone is paying attention. That is no bug and that was one of the test that exposed the bug when the passport was in Harrisburg. The way I interpret the problem as stated by the OP, the travel case is just an easier to understand version of his real problem related to an dynamic FSA with login and logout. So knowing that you need the passport is not known until you try to do the travel from
nyctoparis. At this point you need the passport if it is not in hand and so need travel back toharrisbugto get it.So yes that does look odd from a normal trip solver problem and we as humans can easily see the optimization, either because of experience, or superior reason ability, or peeking ahead and knowing that we need a passport to get to
paris, but the system does not know it needs a passport until it is needed. I can add more rules and more conditions to this, but at present there is only the passport. If however the OP adds more conditions then I will ask for a new question because this question should have been more specific.From OP
It doesn't at the moment because there were no rules needing to do that. It was posed as a question for others who have or plan to answer this as it will be a choice they would have to make when writing the code.
From OP
No, I only looked at your basic ideas in the question posted.
This question is referring to the OPs code posted at GitHub
References of value
Attribute Grammars (Wikipedia)
Automated planning and scheduling (Wikipedia) (Prolog example)
RosettaCode Dijkstra's algorithm
SLD Resolution
Tabled execution (SLG resolution)
Declarative Programming - 3: logic programming and Prolog