Hacker News new | ask | show | jobs
by remram 1911 days ago
Since I'm here, any tool recommendations for visualizing state machines, and state charts in particular? XState's [1] is ok but only works on the web and offers to export, and I found its layout algorithm a bit sub-par. Writing graphviz code by hand, or using google draw/draw.io/... gets painful very quickly.

[1]: https://xstate.js.org/viz/

2 comments

JSSM has JSSM-viz.

https://github.com/StoneCypher/jssm-viz

If you just want one to use, rather than to embed in your own software, The thing everyone's calling a live editor is actually the JSSM-viz demo. You can use that

https://stonecypher.github.io/jssm-viz-demo/graph_explorer.h...

It's kept outside of the main repo because, like xstate's, it's built on a transcompile of graphviz called viz.js, which is made with emscripten

It's several meg, and not many people want visualization, so I keep them in separate packages

You can get the graphviz code by hitting "dot" at the top, if you want to customize in ways the language doesn't know

The problem is that this uses your new custom language which is not yet documented. I had seen this, I asked for alternatives because it doesn't seem to be an option yet.

The examples in your README also seem very limited, with no guards/actions/recursion/parallelism (correct me if I'm wrong). The last two I can do without but it seems overly simplistic as of now.

> The examples in your README also seem very limited

Agreed.

.

> with no guards

It's not entirely clear what you mean by a guard. Isn't the entirety of a state machine a guard?

If you mean transitions that are disallowed due to embedded mealy values, that's meant to be handled by the return value from hooks. That runs but isn't published yet because the test cases aren't yet adequate

.

> actions

  const yeah_huh = sm`has_actions 'tell_em' -> neat;`;
or less glibly

  const matter = sm`
  
                   solid  'melt' 
    <-> 'freeze'   liquid 'boil' 
    <-> 'condense' gas    'ionize' 
    <-> 'deionize' plasma;
  
  `;
.

> recursion

State machines don't have control behavior and in general should not have direct expression of "recursion," unless I misunderstand what you mean

If you mean machines self-embedding, that is planned, and I don't know of anyone else who does that

.

> parallelism

Nothing stops you from putting a machine in each of a bunch of threads or web workers or whatever. By example, if you were making a Roller Coaster Tycoon style game, having one FSM to model each park visitor or each ride or each garbage pile or whatever would actually be fairly reasonable.

Granted, I'd probably just make an array of them and process them serially in a single web worker, because you'd want the world synchronized and fast, but, it's doable.

The core concept of a finite state machine has no direct association with process control and within a single finite state machine it's not actually clear to me what parallelism would mean within a single FSM. I've never seen this in any other state machine library. If this is what you mean, I'd like to hear more, possibly including an example API.

It's possible that I misunderstand you.

.

> it seems overly simplistic as of now.

If you can find a finite state machine with more features, please let me know where.

I'm mostly concerned about visualization, so if you have actions/guards that don't appear on the visualization, that doesn't help me. Similarly, by recursion I meant putting states inside states (from a behavior perspective you would call them compound states); Both PlantUML and XState supports that.

Parallel states [1] are compound states with multiple distinct regions, where each region transitions separately. It does not necessarily imply threading on the programming side, it might just be multiple separate actors. Both PlantUML and XState support them.

XState: https://xstate.js.org/docs/guides/statenodes.html#state-node... PlantUML: https://plantuml.com/state-diagram

[1]: https://statecharts.github.io/glossary/parallel-state.html

> I'm mostly concerned about visualization

Almost all of the finite state machines use the same underlying graphing tool, "GraphViz," to do their rendering. It sounds like you might want that.

There is an emscripten transcompile for the web called viz.js.

.

> if you have actions/guards that don't appear on the visualization

Actions do appear on the visualization. I'm still not sure what you mean by guards.

.

> imilarly, by recursion I meant putting states inside states (from a behavior perspective you would call them compound states); Both PlantUML and XState supports that. Parallel states [1] are compound states with multiple distinct regions

It looks like one of XState or PlantUML tried to rename Heirarchical Orthogonal State Regions, and the other copied the first one.

.

What you're calling "recursion" is called a Heirarchical State Machine. It appears that XState uses the regular name for these:

https://xstate.js.org/docs/guides/hierarchical.html

External reference:

https://barrgroup.com/embedded-systems/how-to/introduction-h...

.

What you're calling Parallel States is properly called an Orthogonal Region. It's problematic to call these parallel for exactly the following statement, where you suggest that this "doesn't necessarily imply threading;" this wrong name that XState and PlantUML has used has confused you.

*All state machines are by definition single threaded single context. This may not and will never be implemented with threading, nor actors. This has nothing to do with process parallelism. This cannot be implemented in a parallel way by any machine, ever.*

External reference:

https://www.boost.org/doc/libs/1_47_0/libs/msm/doc/HTML/ch02....

https://en.wikipedia.org/wiki/UML_state_machine#Orthogonal_r...

It looks like neither PlantUML nor XState allow for orthogonal regions in a way that copes with superstates, which is a very serious limitation. Their orthogonal regions seem to just subdivide whatever nested state you're currently in. This defies the core concept of an orthogonal region, which is to allow unrelated parallel pseudostates. If the context dominates which pseudostates are actually available, then this is little better than a tagged record.

Respectfully, XState and PlantUML seem to have produced the wrong tool, here. Please look to Boost, instead, which gets this very right.

I'll give two examples: one a silly one, to make what the difference actually is make sense, then a better one, to explain why it should matter.

The silly one is an extension of the keyboard example used in Wikipedia's UML state machine orthogonal region discussion. In brief, they propose a state for a keyboard which treats the main keyboard effectively separately of the numeric keypad. There are relevant separate state bits for each, eg caps lock on left and num lock on right.

To extend this, consider the APL keyboard, which is a programmer's keyboard which can switch between two layouts on the left. One is whatever your local natural language is; the other is a special layout for the programming language APL, which uses a bunch of novelty symbols. You need an actual layout switch because the control keys aren't just in different positions, but are actually different control keys (it uses meta and opt.)

In a UML state machine, the natural thing to do is:

1) Model each language's keyboard left as its own machine; 2) same thing for the APL keyboard; 3) also the keypad; 4) create an orthogonal region with the keypad on the right 5) put an HFSM in the left to swap between APL and whatever natural language(s) you're using

The problem is, if the orthogonal region is just a subdivision of your bottom level organization, step 5 isn't possible.

Worse still, this even still implies a pretty clean division of what's "on the left" and what's "on the right." They're modules that snap together and don't talk to each other.

What if these are power plants? These two over here go down, this one over here has to start up. They have to be able to synchronize (it's a wave, waves cancel.)

When one of these plants goes up and down, it might have multiple reactors. Some of those reactors might have multiple engagements. They might have differential backup. If the coal plant nearby is running, when solar comes online it doesn't need its LNG backup because there's already in-fill.

If these so-called "orthogonal states" are just being able to track several state elements and a contemporary context bit, as this appears to be, then you can't have them switching independently in any meaningful way.

I wish tools like XState and PlantUML wouldn't change the name of primary tools. If they used the correct name for this, you'd realize how wildly limited the thing you're looking at is as compared to what it's supposed to be.

.

Now that I understand where you're getting your terms, I assume that when you say "guards," you mean what XState calls "guarded transitions." That's a simple case of returning 0 from any hook.

Yes, JSSM does this. No, it doesn't render that on the visualization. I'm not sure what that ought to look like, to be frank.

.

With regards to HSMs, I do have a mechanism of this form, but, something significantly more powerful. It is as yet incomplete and as such unreleased. If you need that in your visualization, you're better off with XState (or GraphViz directly, more likely.)

From my top-level comment: "Writing graphviz code by hand, or using google draw/draw.io/... gets painful very quickly."

I am fine with a tool using graphviz under the hood for rendering or layout, but I'm not writing my statecharts in graphviz syntax.

I borrowed the term "parallel state" from https://statecharts.github.io/glossary/parallel-state.html. Both XState and MermaidUML support them.

Again, I am concerned with plotting. I am not trying to use the language/library to implement any keyboard or power plant, I just want to get a plot with minimal efforts. Having to edit the SVG or graphviz to "fix" poorly supported advanced features if I ever need them is fine, so long as I can plot most machines and it doesn't take hours. PlantUML is the only tool I've found that fit, which surprises me.

PlantUML is quite handy and text input based. I'm embedding the text state chart directly in the source code as comment to have it under version control.

https://plantuml.com/en/state-diagram