I already have working (ugly) code for this, but I will ask anyway:
I have the time intervals [09:15, 10:00), [21:10, 21:45) during weekdays. Given time t and a number of seconds s, if t is within the intervals, I have to calculate the date and time where t - s would fall into.
Example: t = 20130913 21:15, s = 600, t - s falls into 20130913 09:55.
Example: t = 20130923 09:16, s = 120, t - s falls into 20130920 21:44.
Is there a way of doing this in C++ cleanly (boost::icl? boost::date_time?)
I have tried boost::icl, it can certainly hold the time ranges in an interval_set<Time> and find which interval a certain Time is in, but if t - s time point does not fall into an interval range, I don't see how I can find the nearest interval before that time point, and how to detect if I have to go back a day or through the whole weekend.
I think the problem is too complicated to allow for a clean solution, at least according to my definition of "clean".
You'll need a container for your (non-overlapping) daily intervals, supporting efficiently the following operations:
find in which specific interval a given time belongs,
move an interval backwards, in the container, and
move to the last interval (in chronological order).
It seems to me that boost::icl::interval_set<Time> is an adequate solution. Your time does not need to keep track of the date, you can have that separately.
Your algorithm will be something like:
let d and t be the date and time portions of your t
let i be the interval where t belongs
loop
if t-s belongs in i then
return t-s on day d
else
let j be the previous interval from i
if j does not exist (because i was the first) then
let j be the last interval
move d one weekday backwards
s := s - (t-start(i))
t := end(j)
i := j
This is more or less what you say that your code does. I don't think it can be much cleaner.
Related
I need to find the most efficient approach to the following. If someone can point me in the right direction, I can write the code myself.
Environment
I am using an ESP32 and working in Arduino C++.
What I want to achieve
I want to track the amount of time an actuator has been on over the past x minutes. This is to prevent the actuator from over-heating.
My idea
Storing current times in an array every time the actuator goes on (it is on for a fixed amount of time). When the oldest measurement is older than x minutes, it is removed from the array. If the array exceeds a certain size (e.g. certain amount of minutes the actuator has been on), a cool down period is started.
However, I feel there must be a more efficient / easy way to achieve this. How would you go about this?
Thanks in advance.
If possible, has temperature sensor is the easiest way.
With array, there will be problem with the size, especially, if you want to count in minutes. For counting, there is also way for easier as following:
T is the total time ON in last xx minutes as you expected. During initialization, it will be 0.
If actuator is ON, so every check cycle (may be every s or smaller depend on your required), T will be increase value = cycle time
If actuator is OFF: if T>0 then decrease value = cycle time, if T= 0, nothin to subtract more.
I am trying to overcome a machine allocation problem with time horizon of 5 day. Production plan is hard to catch up, so my objective is to minimize total machines working time spent. Machines uses molds to produce and there are molds for each type of product. If a product is produced at the end of the day and if there will be production later day, total setup needed for that machine should be decreased by one. For this reason,
sets
i: mold type
j:jobs
k: days
parameters
x(i,k) ith mold production needed at day k
y(i,j) 1 if ith mold is compatible with jth machine
Decision variable
m(i,j,k) : 1 if ith mold processed in jth machine in day k 0 o/w
b(j,k) setup number of jth machine in day k
While computing the setup number for day 1, b(j,’1’), is simply equal to the sum of m(i,j,k).
For computing other days setup number I tried these but these made problem nonlinear and it takes months to solve.
b(j,'2')=e=sum(i,m(i,j,'2')) - sum(i,m(i,j,'2')*m(i,j,'1'))
By this way, if mold i is produced in both days, there will not be any setup made at second day. In order to restrain multiple setup reduction I put: sum(i,m(i,j,'2')*m(i,j,'1')) =l= 1
So, how can I decrease the setup number for a machine if it has used a mold a day before without making the problem nonlinear.
It is possible to linearize m(i,j,'2')*m(i,j,'1'):
Both(i,j) <= m(i,j,'2')
Both(i,j) <= m(i,j,'1')
Both(i,j) >= m(i,j,'2')+m(i,j,'1')-1
Both(i,j) is a binary variable
This transformation is done automatically by some solvers.
Note that there are alternative ways to model the start of a run, and often there are things to exploit (depending on the details).
This might be a slightly unusual question and I have a feeling this is a simple task and yet I struggle to find a solution.
I have an arduino project for controlling an valve based on rotational speed of a wheel. The valve needs to be opened in specific time intervals. I have a predefined maximum interval variable as well as minimum interval (both in seconds). I also have a minimum speed (in km/h), below which the valve will stay closed.
So let's assume:
min_v = 20;
max_interval = 60;
min_interval = 1;
All of the above values might possibly be change based on requirements.
How do I calculate the current opening interval based on current speed? Important thing to note is that the interval has to decrease as the speed increases.
Not sure if I also need to assume a max speed for this to be possible?
Ok so here's my formula that seems to be working:
currentInterval = maxOpeningInterval - ((maxOpeningInterval - minOpeningInterval) / (maxSpeed - minSpeed) * currentSpeed);
I create a standard RRDTool database with a default step of 5mn (300s).
I have different types of values in it, some gauges which are easily processed, but I have other values I would have in COUNTER but here is my problem :
I read the data in a program, and get the difference between values over two steps is good but the counter increment less than time (It can increment by less than 300 during a step), so my out value is wrong.
Is it possible to change the COUNTER for not be a number by second but by step or something like that, if it's not I suppose I have to calculate the difference in my program ?
Thank you for helping.
RRDTool is capable of handling fractional values, so there is no problem if the counter increments by less than the seconds interval since the last update.
RRDTool stores everything as a Rate. If your DS is of type GAUGE, then RRDTool assumes that the incoming value is alreayd a rate, and only applies Data Normalisation (more on this later). If the type is COUNTER or DERIVE, then the value/timepoint you are updating with is compared to the previous value/timepoint to obtain a rate thus: r=(x2 - x1)/(t2 - t1). The rate obtained is then Normalised. The other DS type is ABSOLUTE, which assumes the counter was reset on the last read, giving r=x2/(t2 - t1).
The Normalisation step adjusts the data point based on assuming a linear progression from the last data point so that it lies exactly on an interval boundary. For example, if your step is 5min, and you update at 12:06, the data point is adjusted back to what it would have been at 12:05, and stored against 12:05. However the last unadjusted DP is still preserved for use at the next update, so that overall rates are correct.
So, if you have a 300s (5min) interval, and the value increased by 150, the rate stored will be 0.5.
If the value you are graphing is something small, e.g. 'number of pages printed', this might seem counterintuitive, but it works well for large rates such as network traffic counters (which is what RRDTool was designed for).
If you really do not want to display fractional values in the generated graphs or output, then you can use a format string such as %.0f to enforce no decimal places and the displayed number will be rounded to the nearest integer.
I’m not specialist in signal processing. I’m doing simple processing on 1D signal using c++. I want really to know how I can determine the part that have the highest zero cross rate (highest frequency!). Is there a simple way or method to tell the beginning and the end of this part.
This image illustrate the form of my signal, and this image is what I need to do (two indexes of beginning and end)
Edited:
Actually I have no prior idea about the width of the beginning and the end, it's so variable.
I could calculate the number of zero crossing, but I have no idea how to define it's range
double calculateZC(vector<double> signals){
int ZC_counter=0;
int size=signals.size();
for (int i=0; i<size-1; i++){
if((signals[i]>=0 && signals[i+1]<0) || (signals[i]<0 && signals[i+1]>=0)){
ZC_counter++;
}
}
return ZC_counter;
}
Here is a fairly simple strategy which might give you some point to start. The outline of the algorithm is as follows
Input: Vector of your data points {y0,y1,...}
Parameters:
Window size sigma.
A threshold 0<p<1 defining when to start looking for a region.
Output: The start- and endpoint {t0,t1} of the region with the most zero-crossings
I won't give any C++ code, but the method should be easy to implement. As example let us use the following function
What we desire is the region between about 480 and 600 where the zero density higher than in the front. First step in the algorithm is to calculate the positions of zeros. You can do this by what you already have but instead of counting, you store the values for i where you met a zero.
This will give you a list of zero positions
From this list (you can do this directly in the above for-loop!) you create a list having the same size as your input data which looks like {0,0,0,...,1,0,..,1,0,..}. Every zero-crossing position in your input data is marked with a 1.
The next step is to smooth this list with a smoothing filter of size sigma. Here, you can use what you like; in the simplest case a moving average or a Gaussian filter. The higher you choose sigma the bigger becomes your look around window which measures how many zero-crossings are around a certain point. Let me give the output of this filter together with the original zero positions. Note that I used a Gaussian filter of size 10 here
In a next step, you go through the filtered data find the maximum value. In this case it is about 0.15. Now you choose your second parameter which is some percentage of this maximum. Lets say p=0.6.
The final step is to go through the filtered data and when the value is greater than p you start to remember a new region. As soon as the value drops below p, you end this region and remember start and endpoint. Once you are finished walking through the data, you are left with a list of regions, each defined by a start and an endpoint. Now you choose the region with the biggest extend and you are done.
(Optionally, you could add the filter size to each end of the final region)
For the above example, I get 11 regions as follows
{{164,173},{196,205},{220,230},{241,252},{259,271},{278,290},
{297,309},{318,327},{341,350},{458,468},{476,590}}
where the one with the biggest extend is the last one {476,590}. The final result looks (with 1/2 filter region padding)
Conclusion
Please don't be discouraged by the length of my answer. I tried to explain everything in detail. The implementation is really just some loops:
one loop to create the zero-crossings list {0,0,..,1,0,...}
one nested loop for the moving average filter (or you use some library Gaussian filter). Here you can at the same time extract the maximum value
one loop to extract all regions
one loop to extract the largest region if you haven't already extracted it in the above step