[Circuits] Integer storage for stations controller

Don't know how to use a machine? Looking for efficient setups? Stuck in a mission?
Post Reply
Operator
Manual Inserter
Manual Inserter
Posts: 3
Joined: Sat Jan 30, 2021 11:24 am
Contact:

[Circuits] Integer storage for stations controller

Post by Operator »

Hello,

Even as an old player, I'm still struggling when it comes to advanced signals. I'm trying to make a controller to select train stations to activate depending on their filling level but I'm stuck at memorizing their values as they come.


Here is a "simple" process description I made:
1. Using a clock and a bit more: request data from 4 stations, rolling until max station > OK
2. Sending from station their content percentage on 8 bits (4 stations multiplexed) > OK
3. Demultiplex and have all stations percentage when they are emitted > OK, one issue with empty stations
4. Store this percentage as integer > TODO
5. Activate most critical station using max for loaders and min for unloaders > OK, but really ugly

(I can provide (de-)multiplexing blueprints if someone is interested)


Until now I sent all stations levels on a different signal but heading to a megabase (Angels mods btw), it is just impossible to continue like that as stations number are greatly increasing.

I thought about different solutions such as:
_ Store only the current min/max value bit-by-bit using S/R latch
_ Move the intelligence to the station itself (on a full round of "station scanning", was I the min/max?)

But I would like to stick to the original plan and I couldn't find a real solution for a problem I think I'm not alone to have. Do you have any advice on that?


Current data after process n°3 :
_ Signal requesting batch
_ Each station has an individual percentage retrieved 3 ticks after
_ I need to take care of waiting for those 3 ticks to validate data


Thanks for your help and as always,
Enjoy this beautiful game!

mmmPI
Smart Inserter
Smart Inserter
Posts: 2743
Joined: Mon Jun 20, 2016 6:10 pm
Contact:

Re: [Circuits] Integer storage for stations controller

Post by mmmPI »

I would be interested to have a look at the (de-)multiplexing blueprint :)

It's difficult for me to understand what you are doing.

It seems that what you need is some S/R latch to store values but as i understand it's tricky to set them up to behave properly.

One trick you can use to delay the signals for 3 ticks is having it pass through 3 arithmetic doing each+0=>each. It seem related to the later part of your comment.

I will struggle too, i like those :)

Nidan
Fast Inserter
Fast Inserter
Posts: 227
Joined: Sat Nov 21, 2015 1:40 am
Contact:

Re: [Circuits] Integer storage for stations controller

Post by Nidan »

Operator wrote:
Mon Jan 31, 2022 2:36 pm
Here is a "simple" process description I made:
1. Using a clock and a bit more: request data from 4 stations, rolling until max station > OK
2. Sending from station their content percentage on 8 bits (4 stations multiplexed) > OK
3. Demultiplex and have all stations percentage when they are emitted > OK, one issue with empty stations
4. Store this percentage as integer > TODO
5. Activate most critical station using max for loaders and min for unloaders > OK, but really ugly
For storing signals you need a combinator doing nothing (e.g. each + 0 -> each or reset = 0 -> each input count) feeding into itself.
But since you wrote "as integer", it sounds like you need an additional conversion besides the demultiplexing in step 3; if so, we need more details on the signals you have after step 3.
Also you're suddenly using singular, but step 3 should result in (up to) 4 values, is there some filtering/aggregating aside from step 5?
Current data after process n°3 :
_ Signal requesting batch
_ Each station has an individual percentage retrieved 3 ticks after
_ I need to take care of waiting for those 3 ticks to validate data
If all you need is a short delay, then, as mmmPI wrote, a few each + 0 -> each combinators will do.
I thought about different solutions such as:
_ Store only the current min/max value bit-by-bit using S/R latch
_ Move the intelligence to the station itself (on a full round of "station scanning", was I the min/max?)
From your description I'd probably try a distributed approach: On the global network you have a sum of percentages and the number of stations contributing to this sum. Each station calculates its percentage, then compares it to global sum divided by contributors. If less or equal or there are no contributors, enable station and add own percentage to the sum. If greater, disable station and stop contributing to the sum.

Operator
Manual Inserter
Manual Inserter
Posts: 3
Joined: Sat Jan 30, 2021 11:24 am
Contact:

Re: [Circuits] Integer storage for stations controller

Post by Operator »

mmmPI wrote:
Mon Jan 31, 2022 3:27 pm
One trick you can use to delay the signals for 3 ticks is having it pass through 3 arithmetic doing each+0=>each.
Indeed, delaying is easy to do like that.
Nidan wrote:
Mon Jan 31, 2022 5:36 pm
But since you wrote "as integer", it sounds like you need an additional conversion besides the demultiplexing in step 3; if so, we need more details on the signals you have after step 3.
Also you're suddenly using singular, but step 3 should result in (up to) 4 values, is there some filtering/aggregating aside from step 5?
At this stage, I'm having a decider combinator for each station that outputs a number between 0 and 255 which represents the percentage of filling. But only for the time it is being emitted from the matching station.
Nidan wrote:
Mon Jan 31, 2022 5:36 pm
From your description I'd probably try a distributed approach: On the global network you have a sum of percentages and the number of stations contributing to this sum. Each station calculates its percentage, then compares it to global sum divided by contributors. If less or equal or there are no contributors, enable station and add own percentage to the sum. If greater, disable station and stop contributing to the sum.
This would mean activating all stations above/below the average, right?
mmmPI wrote:
Mon Jan 31, 2022 3:27 pm
I would be interested to have a look at the (de-)multiplexing blueprint :)

It's difficult for me to understand what you are doing.
Here is the steps 1-2. I'll upload the rest after work :
20210131_factorio-forum_step1-2.png
20210131_factorio-forum_step1-2.png (3.87 MiB) Viewed 1735 times
Edit: For full size picture, right-click, Open in new tab.

mmmPI
Smart Inserter
Smart Inserter
Posts: 2743
Joined: Mon Jun 20, 2016 6:10 pm
Contact:

Re: [Circuits] Integer storage for stations controller

Post by mmmPI »

Operator wrote:
Tue Feb 01, 2022 10:48 am
Here is the steps 1-2. I'll upload the rest after work :
Thanks !

I've reproduced it



While doing so i think i spotted a thing that is improperly annotated : the last arithmetic combinator in the bottom thing is not doing A<<o=>Y but instead Y<<o=>Y ( unless i'm wrong ? ) the blueprint above uses the second formula.

Doing so i understand better your problem ( i think ).

I am playing with combinators to make the memory for those value, for now i am trying to do so without any modification to the original blueprint that sounds possible but it would seem easier to change it a little.

For example it would be easier to make a counter that only goes up to 60 and then reset instead of storing the infinite numberss.

Also it would be easier to start storing the different percentage with Z=1, then Z=2 then Z=3 rather than starting with Z=0 for the station 1-4.

but maybe that's just my personnal preference and you have other reasons to store the numbers of infinite seconds.

I will post it once it's done, but i wanted to make sure i understood properly the picture and the setting for that last combinator seem like it has a typo ?

[Edit: another thing i'm not getting is why using numbers from 0 to 255 to represent a percentage, why not just use numbers from 0 to 128 this would make it easier too :D ]

For now i have the machine that stores the numbers , but i'm having trouble making the demultiplexer function for number above 128 i'd be curious to see the other steps you made

Nidan
Fast Inserter
Fast Inserter
Posts: 227
Joined: Sat Nov 21, 2015 1:40 am
Contact:

Re: [Circuits] Integer storage for stations controller

Post by Nidan »

Operator wrote:
Tue Feb 01, 2022 10:48 am
Nidan wrote:
Mon Jan 31, 2022 5:36 pm
But since you wrote "as integer", it sounds like you need an additional conversion besides the demultiplexing in step 3; if so, we need more details on the signals you have after step 3.
Also you're suddenly using singular, but step 3 should result in (up to) 4 values, is there some filtering/aggregating aside from step 5?
At this stage, I'm having a decider combinator for each station that outputs a number between 0 and 255 which represents the percentage of filling. But only for the time it is being emitted from the matching station.
If the signals are stable for a while (as your picture suggests), you can compute the new value from the current inputs and the saved value without much consideration for timings and then save this new value. The memory can be e.g. two deciders (A < B -> A input count, A >= B -> B input count) feeding into an arithmetic (A + B -> B) feeding into both deciders. You'll have to add some reset logic though, e.g. by pulling B high or by adding a decider (don't reset -> B input count) into the cycle to break the loop when required.
If it's 4 new stations every tick, things get much more tricky. (I'm not aware of any memory that can handle a compare and update operation every tick; every 2 ticks should be doable, every 3+ ticks is easy.)
I'll play around with your complete blueprint once you post it.
Operator wrote:
Tue Feb 01, 2022 10:48 am
Nidan wrote:
Mon Jan 31, 2022 5:36 pm
From your description I'd probably try a distributed approach: On the global network you have a sum of percentages and the number of stations contributing to this sum. Each station calculates its percentage, then compares it to global sum divided by contributors. If less or equal or there are no contributors, enable station and add own percentage to the sum. If greater, disable station and stop contributing to the sum.
This would mean activating all stations above/below the average, right?
Almost. It does calculate an average, but by stopping the stations that are above average from contributing to it, it should quickly become the minimum and keep tracking the minimum when the percentages of the individual stations change. However, this system will fall apart if you want the n lowest stations enabled.

mmmPI
Smart Inserter
Smart Inserter
Posts: 2743
Joined: Mon Jun 20, 2016 6:10 pm
Contact:

Re: [Circuits] Integer storage for stations controller

Post by mmmPI »

Hey i have made this but it's not very optimised and have some limits that i'll explain at the end :
somewhatfunctionnal.jpg
somewhatfunctionnal.jpg (394.62 KiB) Viewed 1681 times

how to plug to previous blueprint

1) limit => It doesn't work for the first group of station associated with Z=0.
2) It requires that Z+1 is called for the station group Z to update its value. so if you have 12 station, they fit in 3 groups, supposedly Z0 Z1 Z2, but you need to call Z3 to otherwise Z2 won't update.

This means that if you have 12 station, you'd need to start numeroting them 4 5 6 7 for the group associated with Z1 then 8 9 10 11 for the group associated with Z2 then 12 13 14 15 for the group associated with Z3, you would also need to use N >= 20, for the machine to call group Z5 even if there is no station associated with Z5.


Apart from that the value are stored as integer representing percentage in the right most combinator, each group of 4 line is a Zgroup (batch), each line is an individual station in the group.

The 3 main difficulty i had was 1) => doing the right bit shift "unsigned" for the de-multiplexer i had to cheat and re-use something i had seen on the forum already. ( that's the constant combinator holding a green and grey signal with value 2^30 and Y= -2^32). This is an advancded trick ! That's because factorio uses https://en.wikipedia.org/wiki/Arithmetic_shift. It's required to make sure there is not "sticky bit" when doing the right shift.

The other 2) Why don't you use 1=1 instead of making all things starts with the first thing being called 0, then the 2nd thing is called 1 and the 3rd thing is called 2, and so on. This is confusing me a lot because it's so much easier in my opinion in factorio to use the other way around :D I guess it comes from habits outside of factorio that i don't have.

3) In order to make the memory function i thought i had to transform your continous signals into pulse. This is made significantly harder due to previous numeroration system in my opinion. I made it by detecting when the signal will change at the end of the second of broadcast. This is done using 2 arithmetic combinators, one checking when Z+1 is true ( to update group Z2 , check Z=3), and forwarding using 2 parralel wire one going to another arithmetic negating the signal and another wire bypassing this arithmetic.[the 3 combinator on the left on the following picture] Then the idea is that when the signal Z is going to no longer be 2 and instead be 3 for a whole second, delay this signal transition by 2 ticks( with 2 dummy arithmetic each+0=>0). This allow to have 1 tick where there is no signal at all to reset the memory ( adding an extra decider to detect when the new value is arriving) , and 1 tick where you register the new value that will loop in the combinator until the next update.

maybe it is better to see the combinator organised this way to understand :
unaligned.jpg
unaligned.jpg (148.91 KiB) Viewed 1681 times
This represent the line storing the value of 1 station after the de-multiplexing. I though this approach would allow me to make group 0 function but no :( i would need to try again more time.

I'm pretty sure both the demultiplexer and the memory could be optimised in number of combinator because i see many of them doing the same thing and there's probably a way to do a more efficient wiring.

Both would be unecessary though if the clock signal was slightly altered so that instead of having the value Z1 during 1 second then Z2 during 1 second, and so on you would work with a clock signal that count up to N and to each N value you assign 1 32 bit number aka 4 stations. Then you have the N value being sent to the network for something like 5 ticks alongside a value Z. So it would look like

Tick 1 N=1 Z=1
Tick 2 N=1 Z=2
Tick 3 N=1 Z=3
Tick 4 N=1 Z=4
Tick 5 N=1 Z=5
Tick 6 N=2 Z=1
Tick 7 N=2 Z=2
Tick 8 N=2 Z=3
Tick 9 N=2 Z=4
Tick 10N=2 Z=5

This would be a way to "name" each tick and go as fast as possible , because 1 second is super long ! It requires you to keep track of the timing for signal propagation everywhere, but it makes all operation easier to synchronize. It would be easier to utilize that second to cycle different value very fast than to pack 4 value in 1 number, and unpacking them later. At least that's an approach i think would require less combinators but if you are using mods like Angels, ( and i saw the piece of slag on the ground) then maybe the amount of combinators and the space it takes is not as much as a concern and indexing each tick is a waste of time.

Maybe this is what you have in mind already since you can always reduce the period of 1 second per group Z to less amount of time to make the update cycle faster. You'd lose flexibility on the interval you want to choose if you go for the approach of indexing each frame. But it would be easier to remove all the delay combinator and instead rely on the Z value to synchronize the operation and it helps (me) mentally representing what's happening.

And during tick 0, nothing happens, everything is 0 it's fine ,it's not even needed to have a tick 0, things can go 1 2 3 4 1 2 3 4 with no 0 1 2 3 0 1 2 3 :D This is the simplest change

I have not considered a distributed approach, my attempt was to make something you could just plug onto the existing picture. That's some food thought for later :)

Nidan
Fast Inserter
Fast Inserter
Posts: 227
Joined: Sat Nov 21, 2015 1:40 am
Contact:

Re: [Circuits] Integer storage for stations controller

Post by Nidan »

mmmPI wrote:
Wed Feb 02, 2022 1:21 am
The other 2) Why don't you use 1=1 instead of making all things starts with the first thing being called 0, then the 2nd thing is called 1 and the 3rd thing is called 2, and so on. This is confusing me a lot because it's so much easier in my opinion in factorio to use the other way around :D I guess it comes from habits outside of factorio that i don't have.
Well, the first thing is obviously at 0 ;) . In programming, when you have an array (a sequence of objects/things of the same type in a continuous chunk of memory), the variable containing the array actually only has the memory address of the start of the array. So, to get to the first element, you don't have to do anything and can just use the address for the whole array. To get to the second element, you have to skip over the first, i.e. take the address of the array and add the size of a single element. To get to the third element, you take the address of the array and add two times the size of a single element. And so on.
In C-like languages this gets written as "array[index]" which the compiler will translate to "array + index * sizeof(element)" behind the scenes. With this background starting at 0 becomes natural. Interestingly, Lua (the language factorio mods are written in) starts at 1, and it trips me up at least once every time I work with Lua.
I have not considered a distributed approach, my attempt was to make something you could just plug onto the existing picture. That's some food thought for later :)
After reading about OPs other approaches:
I thought about different solutions such as:
_ Move the intelligence to the station itself (on a full round of "station scanning", was I the min/max?)
I felt like doing this, but continuous, could work and just started sketching out the idea.

mmmPI
Smart Inserter
Smart Inserter
Posts: 2743
Joined: Mon Jun 20, 2016 6:10 pm
Contact:

Re: [Circuits] Integer storage for stations controller

Post by mmmPI »

Operator wrote:
Tue Feb 01, 2022 10:48 am
Here is the steps 1-2. I'll upload the rest after work :
I hope you are still ok, i haven't said that i like the machine you have made because i was too focus on playing with the combinators, as so i would be interested to see the other parts of it if you are ok with it. Instead i complained about the annotations on the image which i guess must take time to do at least it would for me :), they look nice and clear, i would try to do the same for the memory thing if you don't mind giving me a hint on the (fast?) method you used or maybe this WE i can try my slow and terrible microsoft paint method :D.

I'm still trying to figure out how the "unsigned right shift" is happening, because i saw the contraption to make it on the forum and recognize i needed it but i'm not quite sure why it works so it would be hard to label properly for me :D.
Nidan wrote:
Wed Feb 02, 2022 7:39 am
Well, the first thing is obviously at 0 ;)
Haaa thanks for the explanations i had some intuitions but it's clearer now :). In my mind naming each ticks is somewhat similar to the way the different lines of code have a number to order them.

For example when looking at the machine i "know" / "represent in my head" that a cycle of update that last 15 ticks would be used with 1 2 3 for demultiplexing, then 4 and 5 to convert the result into percentage, now if i want to do some operation on this percentage, i know that i can use a decider combinator that let signals pass only when Z=6 or 5, considering that only during 1 tick, the 6th tick which is also conviently refered to as Z=6 , the value is relevant, but i can let the signal pass the tick before or 2 in case it's required.

This would be like 2 programs executing on parralel and waiting for each other to synchronize at tick 6. If one program as 1 operation and the other program has 5 operation, you don't need to delay the signal by 4 ticks, instead you always use 1 single decider combinator which let the signal pass only when it's relevant due to reading the name of the tick.

For the previous build it's a bit different, i used 3 dummy arithmetic to synchronize the emission of Z and Y so that the percentage of filling per station (Y) is received exactly at the same time as when the name of the group of 4 (Z) is called in the multiplexer . Then another 3 to synchronize again the Y value and the Z value after the Y value is demultiplexed (? sorry for english) ? The Y value requires 2 operation to isolate the 8 correct bit, then 2 operation to make it a percentage. The Z value require 1 operation/decider i think before Y and Z need to be synchronized. This is when the continous signal is made into a pulse.

At this point the sync between Y and Z need to be correct so that when the transition of the Z value to the next group of station occurs, the Y value can be registered. This is why one signal need to be delayed by 2 ticks ( i think). This means a combinator reading the delayed and non-delayed signal at the same time can do 1 operation and send the result into the non-delayed signal before the delayed signal arrives. ( delay Y by 2 ticks, so that when Z changes it triggers a pulse that register the Y value just before it changes).

I'm not 100% sure it's working as described including the limits, it seemed like it did but i may have missed things like other limitations or used unecessary things, it was a lot of trial and errors that i've tried to clean up the remnants of at the end :).

Nidan wrote:
Wed Feb 02, 2022 7:39 am
After reading about OPs other approaches:
I thought about different solutions such as:
_ Move the intelligence to the station itself (on a full round of "station scanning", was I the min/max?)
I felt like doing this, but continuous, could work and just started sketching out the idea.
Sounds interesting/intriguing, i think the 32 bits per item-signal could be used to store 2 range of percentage. (from w to x and from y to z) Those could be continous and update dynamically without particular frequency. Then station could check if they belong to the range either for being a receiver of material or a supplier of material this also continously and update dynamically without particular frequency, reacting to both their quantity and the network request.

But you could use only 2 number for 2 range considering 1 end at 100% and the other start at 0%. And then i'm not quite sure what to do with those other 2 numbers maybe the previous value to make a chart ? :D

Or maybe considering it's 16 bits, you could store 2 percentage as 2 different 7 bit number, and use the 2 remaining bit to tell if each of the previous value was updated recently 1 or not 0. If you choose an interval for what is called "recently" you could then ring an alert when a trend begins where you keep lowering or increasing a threshold for say 10 times in a row the interval of "recently". That seems pretty unecessary at this point, but also something i could try for hours of fun :).

Post Reply

Return to “Gameplay Help”