zet4080
zet4080

Reputation: 55

How to handle multiple states with a state machine?

I started to implement a system with a state machine. But I came to a point where I doubt that a state machine is the correct approach.

For example: I have four states:

(idle, powerup, powerdown, work)

and two other states:

(production, test)

powerup and powerdown do behave different in production and test state ...

If I do have more states the combination of states explodes ...

How is this solved with a state machine?

Upvotes: 3

Views: 6779

Answers (5)

Martin C
Martin C

Reputation: 161

That's a bit difficult to answer since the actual use case is very vague, but here are some possible techniques:

  1. Create separate states for Production+Powerup, Test+Powerup, Production+Powerdown, Test+Powerdown. Depending on the complexity and number of combinations of states this can explode pretty quickly.

Pros: straightforward.

Cons: cluttered, does not scale well, if some of the state logic is shared across instances there will be some copy pasta involved (hence, not very maintainable)

  1. Use hierarchical state machines (HFSM), that is, if you can define some sort of hierarchical relationship between the various state groups, the implementation of a specific state would be a state machine on it's own.

So in your example, you would have a Production/Test state machine, and each one will implement it's own Idle/Powerup/Powerdown/Work state machine internally.

If you think this over, this is actually a neater implementation of option 1.

Pros: more readable than option 1

Cons: assuming substates should share some common logic, there will still be copy pasting involved

  1. Have 2 parallel state machines, one handling Production/Test states and one handling the Idle/Powerup/Powerdown/Work states with some sort of blackboard or shared memory to communicate between machines.

In your example, your agent or system will a container of the above mentioned state machines and process them in turn. The Production/Test machine would write some status to a shared memory that the other machine will read from and branch it's state logic accordingly.

Pros: Can share code between different states

Cons: Can share code between different states... Ok, serioulsy, it's super important to empashize that sharing code is NOT always a good idea (but that's a whole other phylosophical discussion. Just make sure you properly evaluate the amount of shared code vs. the amount of unique code or paths so you don't end up with a huge class that essentially contains 2 completely separate code paths

  1. I know it's a granted, but consider if FSM is the proper method of representing state and execution in your application. Again, not enough context to dive deep into this, and this point on it's own is a phylosophical debate - but keep your mind open to other solutions as well.

Upvotes: 3

Miro Samek
Miro Samek

Reputation: 1975

The feeling that your state machine "explodes" is very typical in traditional "flat" FSMs (in fact it is generally known as the "state-transition explosion" phenomenon). The remedy is to use a hierarchical state machine (HSM) instead, which specifically counteracts the "explosion" of a traditional FSM. Basically, the HSM allows you to group states with similar behavior together (inside a higher-level super-state) and thus reuse the common behavior among the related states. This is a very powerful concept that leads to much more elegant and consistent designs. To learn more about hierarchical state machines, you can read the article "Introduction to Hierarchical State Machines".

Upvotes: 2

Mesmo
Mesmo

Reputation: 2000

Could it be that you need two instances of the same state machine model? One for production and one for test?

An alternative is that production and test could be orthogonal regions of a single machine.

Upvotes: 0

ttemple
ttemple

Reputation: 882

I would classify 'production' and 'test' as modes, not states. It will still be somewhat messy, but the distinction is important, in my opinion.

switch(state)
{
case powerup:
    switch(mode)
    {
    case test:
        test_powerup_stuff();
        break;
    case production:
        production_powerup_stuff();
        break;
    default:
        break;
    }
    break;
case powerdown:
    switch(mode)
    {
    case test:
        test_powerdown_stuff();
        break;
    case production:
        production_powerdown_stuff();
        break;
    default:
        break;
    }
    break;
case idle:
    do_idle_stuff();
    break;
case work:
    do_work_stuff();
    break;
default:
    state = powerdown;
    break;
}

Upvotes: 0

Nathanael
Nathanael

Reputation: 77

A state machine can share signal with another one. So the state machine that indicate prod or dev can send a signal to the other one.

In fact, if you have only 2 state on the state machine, you can use a variable for that purpose. So you will have one state machine that will do different job depending on the value of the variable.

Upvotes: 0

Related Questions