Which one will suit for complete workflow design Temporal or Cadence - cadence-workflow

I wanted to design a complete end-to-end workflow orchestration engine.
It has the following requirements
Linear workflow
Parallel workflow - I wanted to execute n no of activities parallelly. After validates the results from all the activities I wanted to
proceed to the next state or will fail the workflow
Batch - say I have 30 activities to be completed but I want this to be done in a batch fashion. Like if the window size is 5 then I wanted
to execute 5 activities at a time T. After executing all the activities
and validates the results will proceed further or fail the workflow.
Loop - wanted to run an activity infinitely until some condition meets
Child Workflow
Polling

All 1-5 are supported easily in Cadence workflow. I am not sure what you mean by Polling. If you can provide more details, I will update this answer to help you.
Here is the sample to execute activities in Leaner+parallel/batch+loop:
#Override
public long calculate(long a, long b, long c) {
LOGGER.info("workflow start...");
long result = 0;
// Async.invoke takes method reference and activity parameters and returns Promise.
Promise<Long> ab = Async.function(activities::multiple, a, b);
Promise<Long> ac = Async.function(activities::multiple, a, c);
Promise<Long> bc = Async.function(activities::multiple, b, c);
// Promise#get blocks until result is ready.
this.abPlusAcPlusBc = result = ab.get() + ac.get() + bc.get();
// waiting 30s for a human input to decide the factor N for g(n), based on a*b+a*c+b*c
// the waiting timer is durable, independent of workers' liveness
final boolean received = Workflow.await(Duration.ofMinutes(2), () -> this.factorForGn > 1);
if (!received) {
this.factorForGn = 10;
}
long fi_1 = 0; // f(0)
long fi_2 = 1; // f(1)
this.currentG = 1; // current g = f(0)*f(0) + f(1)*f(1)
long i = 2;
for (; i < this.factorForGn; i++) {
// get next fibonacci number
long fi = fi_1 + fi_2;
fi_2 = fi_1;
fi_1 = fi;
this.currentG += activities.multiple(fi, fi);
}
result += this.currentG;
return result;
}
And this is the sample of using ChildWorkflow.

Related

How to generate a model for my code using boolector?

I'm experimenting a bit with boolector so I'm trying to create model for simple code. Suppose that I have the following pseudo code:
int a = 5;
int b = 4;
int c = 3;
For this simple set of instructions I can create the model and all works fine. The problem is when I have other instructions after that like
b = 10;
c = 20;
Obviously it fails to generate the model because b cannot be equal to 4 and 10 within the same module. One of the maintainer suggested me to use boolector_push and boolector_pop in order to create new Contexts when needed.
The code for boolector_push is :
void
boolector_push (Btor *btor, uint32_t level)
{
BTOR_ABORT_ARG_NULL (btor);
BTOR_TRAPI ("%u", level);
BTOR_ABORT (!btor_opt_get (btor, BTOR_OPT_INCREMENTAL),
"incremental usage has not been enabled");
if (level == 0) return;
uint32_t i;
for (i = 0; i < level; i++)
{
BTOR_PUSH_STACK (btor->assertions_trail,
BTOR_COUNT_STACK (btor->assertions));
}
btor->num_push_pop++;
}
Instead for boolector_pop is
void
boolector_pop (Btor *btor, uint32_t level)
{
BTOR_ABORT_ARG_NULL (btor);
BTOR_TRAPI ("%u", level);
BTOR_ABORT (!btor_opt_get (btor, BTOR_OPT_INCREMENTAL),
"incremental usage has not been enabled");
BTOR_ABORT (level > BTOR_COUNT_STACK (btor->assertions_trail),
"can not pop more levels (%u) than created via push (%u).",
level,
BTOR_COUNT_STACK (btor->assertions_trail));
if (level == 0) return;
uint32_t i, pos;
BtorNode *cur;
for (i = 0, pos = 0; i < level; i++)
pos = BTOR_POP_STACK (btor->assertions_trail);
while (BTOR_COUNT_STACK (btor->assertions) > pos)
{
cur = BTOR_POP_STACK (btor->assertions);
btor_hashint_table_remove (btor->assertions_cache, btor_node_get_id (cur));
btor_node_release (btor, cur);
}
btor->num_push_pop++;
}
In my opinion, those 2 functions maintains track of the assertions generated using boolector_assert so how is it possible to obtain the final and correct model using boolector_push and boolector_pop considering that the constraints are going to be the same?
What am I missing?
Thanks
As you suspected, solver's push and pop methods aren't what you're looking for here. Instead, you have to turn the program you are modeling into what's known as SSA (Static Single Assignment) form. Here's the wikipedia article on it, which is quite informative: https://en.wikipedia.org/wiki/Static_single_assignment_form
The basic idea is that you "treat" your mutable variables as time-varying values, and give them unique names as you make multiple assignments to them. So, the following:
a = 5
b = a + 2
c = b + 3
c = c + 1
b = c + 6
becomes:
a0 = 5
b0 = a0 + 2
c0 = b0 + 3
c1 = c0 + 1
b1 = c1 + 6
etc. Note that conditionals are tricky to deal with, and generally require what's known as phi-nodes. (i.e., merging the values of branches.) Most compilers do this sort of conversion automatically for you, as it enables many optimizations down the road. You can either do it by hand, or use an algorithm to do it for you, depending on your particular problem.
Here's another question on stack-overflow, that's essentially asking for something similar: Z3 Conditional Statement
Hope this helps!

Anylogic Variable Not Updating

I an using a discrete event simulator in AnyLogic. I am having an issue with some code which updates a variable in my simulation. I store both the datetime at which the agent leaves the source block and the datetime at which it enters the sink block. I am trying to record the number of "rule breaks" for all agents. The rule break is defined below (two ways to break):
1) If the agent is received before a certain time (called SDC) and the agent is not completed by 5pm the same day, then the agent has broken the rule
2) If the agent is not completed by the next day at a certain time (called NDC), then the agent has broken the rule
I record a zero or a one for each agent if they break either rule in the variable called RuleBreak. However, in my simulation runs, the variable does not update at all. I hope I am just missing something small. Would appreciate any help! (code below)
Calendar received = Calendar.getInstance();
received.setTime(ReceivedDate);
Calendar completion = Calendar.getInstance();
completion.setTime(Completion);
Calendar SD_at_5 = Calendar.getInstance();
SD_at_5.setTime(ReceivedDate);
SD_at_5.set(Calendar.HOUR_OF_DAY,17);
SD_at_5.set(Calendar.MINUTE, 0);
SD_at_5.set(Calendar.SECOND, 0);
Calendar Tomorrow_at_NDC = Calendar.getInstance();
Tomorrow_at_NDC.setTime(ReceivedDate);
if(Tomorrow_at_NDC.get(Calendar.DAY_OF_WEEK) == 6)
Tomorrow_at_NDC.add(Calendar.DATE, 3);
else
Tomorrow_at_NDC.add(Calendar.DATE, 1);
Tomorrow_at_NDC.add(Calendar.DATE, 1);
Tomorrow_at_NDC.set(Calendar.HOUR_OF_DAY,NDC);
Tomorrow_at_NDC.set(Calendar.MINUTE, 0);
Tomorrow_at_NDC.set(Calendar.SECOND, 0);
int Either_rule_break = 0;
double time_diff_SDC = differenceInCalendarUnits(TimeUnits.SECOND,completion.getTime(),SD_at_5.getTime());
double time_diff_NDC = differenceInCalendarUnits(TimeUnits.SECOND,completion.getTime(),Tomorrow_at_NDC.getTime());
if((received.get(Calendar.HOUR_OF_DAY) < SDC) && (time_diff_SDC <= 0))
Either_rule_break = Either_rule_break + 1;
else
Either_rule_break = Either_rule_break + 0;
if((received.get(Calendar.HOUR_OF_DAY) >= SDC) && (time_diff_NDC <= 0))
Either_rule_break = Either_rule_break + 1;
else
Either_rule_break = Either_rule_break + 0;
if((Either_rule_break >= 1))
RuleBreak = RuleBreak + 1;
else
RuleBreak = RuleBreak + 0;
You haven't really explained where this code is used and what it receives. I assume the code is in a function, called in the sink's on-enter action, where ReceivedDate and Completion are Date instances stored per agent (source exit time and sink entry time, as dates, captured via AnyLogic's date() function).
And looks like your SDC hour-of-day is stored in SDC and your NDC hour-of-day in NDC (with RuleBreak being a variable in Main or similar storing the total number of rule-breaks).
Your calculations look OK except that the Tomorrow_at_NDC Calendar calculation seems wrong: you add 1 day twice (if not Saturday) or 3 days plus 1 day (if Saturday; in a Java Calendar, day-of-week 1 is Monday).
(Your Java is also very 'inefficient' with unnecessary extra local variables and performing logic when you don't need to; e.g., no point doing all the calendar preparation and check for your type 1 rule-break if the receive time is after the SDC hour.)
But are you sure there are any rule-breaks; how have you set up your model to ensure that there are (to test it)? Plus is RuleBreak definitely a variable outside of the agents that flow through your DES (i.e., in Main or similar)? Plus are Completion and ReceivedDate definitely stored per agent so, for example, if your function was called checkForRuleBreaks you would be doing something like the below in your sink on-exit action:
agent.Completion = date(); // Agent received date set earlier in Source action
checkForRuleBreaks(agent.ReceivedDate, agent.Completion);
(In fact, you don't need to store the completion date in the agent at all since that will always be the current sim-date inside your function and so you can just calculate it there.)

Promela system with unranged values

int rq_begin = 0, rq_end = 0;
int av_begin = 0, av_end = 0;
#define MAX_DUR 10
#define RQ_DUR 5
proctype Writer() {
do
:: (av_end < rq_end) -> av_end++;
if
:: (av_end - av_begin) > MAX_DUR -> av_begin = av_end - MAX_DUR;
:: else -> skip;
fi
printf("available span: [%d,%d]\n", av_begin, av_end);
od
}
proctype Reader() {
do
:: d_step {
rq_begin++;
rq_end = rq_begin + RQ_DUR;
}
printf("requested span: [%d,%d]\n", rq_begin, rq_end);
(rq_begin >= av_begin && rq_end <= av_end);
printf("got requested span\n");
od
}
init {
run Writer();
run Reader();
}
This system (only an example) should model a reader/writer queue where the reader requests a certain span of frames [rq_begin,rq_end], and the writer should then make at least this span available. [av_begin,av_end] is the span of available frames.
The 4 values are absolute frame indices, rq_begin gets incremented infinitley as the reader reads the next span of frames.
The system cannot be directly verified because the values are unranges (generating infinitely many states). Does Promela/Spin (or a similar software) has support to verify a system like this, and automatically transform it such that it becomes finite?
For example if all the 4 values were incremented by the same amount, the situation would still be the same. Or it could be reformulated into a model which instead has variables for the differences of these values, for example av_end - rq_end.
I'm using Promela/Spin to verify a more complex queuing system which uses absolute frame indices like this.

How does Test and Set Instruction provide Bounded Waiting in below code?

In the below code how is bounded waiting condition satisfied ,I am unable to get the usage of these statements ,why have they applied the condition j!=i and j=(j+1)%n and then the condition mentioned inside if clause using (j==i),please clarify this ,according to me it should only check for waiting[j] , so as to confirm if any other process is waiting for lock or not ,I am unable to get the idea of working of this algorithm ,please explain it .
while ((j != i) && !waiting[j])
j = (j + 1) % n;
if (j == i)
lock = false;
do {
waiting[i] = true;
while (waiting[i] && test_and_set(&lock)) ;
waiting[i] = false;
/* critical section */
j = (i + 1) % n;
while ((j != i) && !waiting[j])
j = (j + 1) % n;
if (j == i)
lock = false;
else
waiting[j] = false;
/* remainder section */
} while (true);
Bounded waiting means no process should wait for a resource for infinite amount of time.
You have n processes, process i is currently executing, when it enters the critical section, it sets its waiting to false.
Now, what happens when process i has finished ?
Process i will look for an index j (process j) that is waiting to run in critical section. In other words, we are looking for a process that is waiting to enter the critical section that is different from the current process that ran in critical section.
if (i==j), then no such process exists, we set lock to false. Otherwise, we set the process that is waiting to run and prevent starvation. And this way you satisfy Bounded Waiting.
This is achieved because you do a circular search, you first check processes
i+1, i+2, .... n, 0, 1, ... ,(i-1)

PID controller in C# Micro Framework issues

I have built a tricopter from scratch based on a .NET Micro Framework board from TinyCLR.com. I used the FEZ Mini which runs at 72 MHz. Read more about my project at: http://bit.ly/TriRot.
So after a pre-flight check where I initialise and test each component, like calibrating the IMU and spinning each motor, checking that I get receiver data, etc., it enters a permanent loop which then calls the flight controller method on each loop.
I'm trying to tune my PID controller now using the Ziegler-Nichols method, but I am always getting a progressively larger overshoot. I was eventually able to get a [mostly] stable oscillation using proportional control only (setting Ki and Kd = 0); timing the period K with a stopwatch averaged out to 3.198 seconds.
I came across the answer (by Rex Logan) on a similar question by chris12892.
I was initially using the "Duration" variable in milliseconds which made my copter highly aggressive, obviously because I was multiplying the running integrator error by thousands on each loop. I then divided it by another thousand to bring it to seconds, but I'm still battling...
What I don't understand from Rex's answer is:
Why does he ignore the time variable in the integral and differential parts of the equations? Is that right or is it a typo?
What he means by the remark
In a normal sampled system the delta term would be one...
One what? Should this be one second under normal circumstances? What
if this value fluctuates?
My flight controller method is below:
private static Single[] FlightController(Single[] imuData, Single[] ReceiverData)
{
Int64 TicksPerMillisecond = TimeSpan.TicksPerMillisecond;
Int64 CurrentTicks = DateTime.Now.Ticks;
Int64 TickCount = CurrentTicks - PreviousTicks;
PreviousTicks = CurrentTicks;
Single Duration = (TickCount / TicksPerMillisecond) / 1000F;
const Single Kp = 0.117F; //Proportional Gain (Instantaneou offset)
const Single Ki = 0.073170732F; //Integral Gain (Permanent offset)
const Single Kd = 0.001070122F; //Differential Gain (Change in offset)
Single RollE = 0;
Single RollPout = 0;
Single RollIout = 0;
Single RollDout = 0;
Single RollOut = 0;
Single PitchE = 0;
Single PitchPout = 0;
Single PitchIout = 0;
Single PitchDout = 0;
Single PitchOut = 0;
Single rxThrottle = ReceiverData[(int)Channel.Throttle];
Single rxRoll = ReceiverData[(int)Channel.Roll];
Single rxPitch = ReceiverData[(int)Channel.Pitch];
Single rxYaw = ReceiverData[(int)Channel.Yaw];
Single[] TargetMotorSpeed = new Single[] { rxThrottle, rxThrottle, rxThrottle };
Single ServoAngle = 0;
if (!FirstRun)
{
Single imuRoll = imuData[1] + 7;
Single imuPitch = imuData[0];
//Roll ----- Start
RollE = rxRoll - imuRoll;
//Proportional
RollPout = Kp * RollE;
//Integral
Single InstanceRollIntegrator = RollE * Duration;
RollIntegrator += InstanceRollIntegrator;
RollIout = RollIntegrator * Ki;
//Differential
RollDout = ((RollE - PreviousRollE) / Duration) * Kd;
//Sum
RollOut = RollPout + RollIout + RollDout;
//Roll ----- End
//Pitch ---- Start
PitchE = rxPitch - imuPitch;
//Proportional
PitchPout = Kp * PitchE;
//Integral
Single InstancePitchIntegrator = PitchE * Duration;
PitchIntegrator += InstancePitchIntegrator;
PitchIout = PitchIntegrator * Ki;
//Differential
PitchDout = ((PitchE - PreviousPitchE) / Duration) * Kd;
//Sum
PitchOut = PitchPout + PitchIout + PitchDout;
//Pitch ---- End
TargetMotorSpeed[(int)Motors.Motor.Left] += RollOut;
TargetMotorSpeed[(int)Motors.Motor.Right] -= RollOut;
TargetMotorSpeed[(int)Motors.Motor.Left] += PitchOut;// / 2;
TargetMotorSpeed[(int)Motors.Motor.Right] += PitchOut;// / 2;
TargetMotorSpeed[(int)Motors.Motor.Rear] -= PitchOut;
ServoAngle = rxYaw + 15;
PreviousRollE = imuRoll;
PreviousPitchE = imuPitch;
}
FirstRun = false;
return new Single[] {
(Single)TargetMotorSpeed[(int)TriRot.LeftMotor],
(Single)TargetMotorSpeed[(int)TriRot.RightMotor],
(Single)TargetMotorSpeed[(int)TriRot.RearMotor],
(Single)ServoAngle
};
}
Edit: I found that I had two bugs in my code above (fixed now). I was integrating and differentiating with the last IMU values as opposed to the last error values. That got rid of the runaway sitation completely. The only problem now is that it seems to be a bit slow. When I perturb the system, it responds very quickly and stop it from continuing, but it takes a long time to get back to the setpoint (0), about 10 seconds or more. Is this now just down to tuning the PID? I'll give the suggestions below a go, and let you know if any of them make a difference.
One question I have is:
being a .NET board, I don't want to bank on any kind of accurate timing, so instead of trying to work out at what frequency I am executing that method, surely if I calculate the actual time and factor that into the equations, it should be better, or am I misunderstanding something?