project job scheduling: Multiple job parallel problems - optaplanner

In the same project, I don't want two jobs to run in parallel. How should I design it?
Is there a rule in the drl file that does not allow two jobs under the same project to run at the same time?
If there is no such thing, how should two jobs under the same project not run simultaneously?
rule "nonrenewableResourceCapacity"
when
$resource : Resource(renewable == false, $capacity : capacity)
accumulate(
ResourceRequirement(resource == $resource,
$executionMode : executionMode,
$requirement : requirement)
and Allocation(executionMode == $executionMode);
$used : sum($requirement);
$used > $capacity
)
then
scoreHolder.addHardConstraintMatch(kcontext, 0, $capacity - $used);
end
rule "renewableResourceUsedDay"
salience 1 // Do these rules first (optional, for performance)
when
ResourceRequirement(resourceRenewable == true, $executionMode : executionMode, $resource : resource)
Allocation(executionMode == $executionMode,
$startDate : startDate, $endDate : endDate)
then
for (int i = $startDate; i < $endDate; i++) {
insertLogical(new RenewableResourceUsedDay($resource, i));
}
end
rule "renewableResourceCapacity"
when
RenewableResourceUsedDay($resource : resource, $capacity : resourceCapacity, $usedDay : usedDay)
accumulate(
ResourceRequirement(resource == $resource,
$executionMode : executionMode,
$requirement : requirement)
and Allocation(executionMode == $executionMode, $usedDay >= startDate, $usedDay < endDate);
$used : sum($requirement);
$used > $capacity
)
then
scoreHolder.addHardConstraintMatch(kcontext, 0, $capacity - $used);
end
// ############################################################################
// Soft constraints
// ############################################################################
rule "totalProjectDelay"
when
Allocation(jobType == JobType.SINK, endDate != null, $endDate : endDate,
$criticalPathEndDate : projectCriticalPathEndDate)
then
scoreHolder.addSoftConstraintMatch(kcontext, 0, $criticalPathEndDate - $endDate);
end
rule "totalMakespan"
when
accumulate(
Allocation(jobType == JobType.SINK, $endDate : endDate);
$maxProjectEndDate : max($endDate)
)
then
scoreHolder.addSoftConstraintMatch(kcontext, 1, - (Integer) $maxProjectEndDate);
end

In task assignment, when you never want to run 2 jobs in parallel (so its a hard constraint, for all jobs), I'd probably make it a build-in hard constraint and basically model it like TSP.
If it's just pairs of specific jobs that shouldn't run in parallel, I'd have the variable listener detect that the 2 jobs would be run at the same time and delay the start time of the job that can start the latest. If they can both start at the same time, the one with the lowest id starts first and the other is delayed. This last bit is to avoid score corruption with incremental calculation.

Related

How to filter rows before and after a certain period (date)?

My objective is to select dates before/after a certain period. I have a start period and an end period. I want to filter rows where close_time is included between two periods (and some other filters, like category and origin): start period <= close_time >= end period.
I have tried using:
var StartTime == '2017-03-14'
var EndTime == '2017-03-14'
val df1 = df.withColumn(
"X_Field",
when($"category" === "incident" and $"origin" === "phone" and StartTime <== $"close_time" >== EndTime, 1).otherwise(0)
)
I have errors. What is the right syntax to do this ? Thx !
First - unlike with equality, the right operators to use for greater-or-equal and little-or-equal are <= and >= and not <== and >==.
Second, the expression StartTime <= $"close_time" >= EndTime is not valid - the first part (StartTime <= $"close_time") evaluates into a Boolean condition, which you then try to compare to another String (>= EndTime).
Instead, you can use between:
val df1 = df.withColumn("X_Field", when(
$"category" === "incident" and
$"origin" === "phone" and
($"close_time" between (StartTime, EndTime)), 1).otherwise(0)
)
Which is simply shorthand for:
val df1 = df.withColumn("X_Field", when(
$"category" === "incident" and
$"origin" === "phone" and
($"close_time" >= StartTime and $"close_time" <= EndTime), 1).otherwise(0)
)

Writing rule in Drools - conditional sum

I am stuck in writing a rule for a particular problem statement.
I have an excel file having columns id, specialty,salary. Specialty can take values such as "oncology","urology" etc. I have to calculate total salary corresponding to each specialty.
There are two ways of doing this.
First:
rule "Total salary of Oncology"
no-loop
lock-on-active
salience 100
when
$m : Masterclass( $id : phyid , $p : p,spec=="Oncology")
not Masterclass( spec=="Oncology", phyid < $id)
$total : Number() from accumulate ( Masterclass( $salary : salary ,spec=="Oncology") ,
init( double total =0;),
action(total+=$salary;),
result( new Double (total)))
then
System.out.println($m.getSpec());
System.out.println("Total target pay is : " + $total + " of specialty : "+ $m.getSpec());
retract($m);
end
And similarly for other specialties.
This rule works fine.
Second:
Write only a single rule which reads the value of specialty and then sums up the salaries corresponding to it.
I tried to implement this but didn't succeed.
Any help will be appreciated.
This is far from perfect. But note that you don't have to insert some specific string. Running the rule without a string to match will produce the accumulated sums for all specialities anyway.
And you should wrap the String into a Java class - I was just too lazy to invent a proper Java class with one field.
rule "trigger read"
when
not String()
then
String s = read_any_way_you_want();
insert( s );
end;
rule "Total salary of something"
when
$spec: String()
$m : Masterclass( $id: phyid , spec == $spec)
not Masterclass( spec == $spec, phyid < $id)
$total : Number() from
accumulate ( Masterclass($salary: salary, spec == $spec) ,
init( double total =0;),
action(total+=$salary;),
result( new Double (total)))
then
System.out.println($m.getSpec());
System.out.println("Total target pay is : " + $total +
" o specialty : "+ $m.getSpec());
retract($spec);
end

drools code for score calculation logic

I want to schedule events using optaplanner in which required resource by event is a soft constraint.
I have done score calculation in java code like :
int resources = 0;
int quantity = 0;
for(ResourceAvailability availability : eventDate.getResourceAvailabilities()){
for(ResourceAvailability required : event.getResourceAvailabilities()){
if(availability.equals(required)){
resources += required.getQuantity();
quantity += availability.getQuantity();
}
}
}
// Soft constraints
int resourcesAvailable = quantity - resources;
if (resourcesAvailable < 0) {
softScore += resourcesAvailable;
}
This is working but it is slow,i want to get equivalent drools code for this soft score calculation logic.
So how to write drools code for this??
I checked drools file of machine reassignment problem,but could not relate it with my problem.
Here Event is my planning entity and EventDate is planning variable.
I am writing drools rule like :
rule "requiredResources"
when
$eventDate : EventDate()
$requiredResources : Number(intValue > 1) from accumulate(
Event(
eventDate == $eventDate,
//here logic for comparing required and available resource and then find
//sum of required resources and available resoulces
//add difference to score
),
sum($quantity)
)
then
System.out.println($requiredResources+$availableResources);
end
From the machine reassignment example:
rule "machineUsage"
when
$machineCapacity : MrMachineCapacity($machine : machine, $resource : resource)
accumulate(
$processAssignment : MrProcessAssignment(machine == $machine),
$usageTotal : sum($processAssignment.getUsage($resource))
)
then
scoreHolder.addHardConstraintMatch($capacity - $usage); // see docs chapter score calculation
end

Drools Fusion De-duplication

I defined a class which acts as event to the rule engine
It has the following members
1. phone number
2. latitude
3. longitude
How do I formulate a rule wherein
1. The rule counts the number of distinct people in the same location
2. Same person if crossing the same location more than once during a 1 minute interval should be counted only as one and should not be duplicated
I made the below rule but it doesn't seem to be working
import locationbasedservices.LocationEvent;
declare LocationEvent
#role(event)
#expires(1m)
end
rule "footfallcount"
when
LocationEvent ( $msisdn : msisdn )
$footfallcnt : Number(intValue > 0)
from accumulate( LocationEvent(latitude=="77.77", longitude=="77.77",
age>31 && <40, arpu>40.00, gender=="MALE")
from entry-point LocationSvc,
not ArrayList( size >= 2 )
from collect( LocationEvent( msisdn == $msisdn )
from entry-point LocationSvc),
count(1))
then
System.out.println("Footfall: " + $footfallcnt);
end
Can someone help?
Regards
Subbu
This is what I had in mind:
$m2e: Map( $size: size )
from accumulate ( $le: LocationEvent ( latitude == "77.77", longitude == "77.77",
age > 31 && < 40, arpu > 40.00,
gender == "MALE", $msisdn : msisdn )
over window:time( 1m ),
init( Map m2e = new HashMap(); ),
action( m2e.put( $msisdn, $le ); ),
result( m2e ) )
Note carefully what the Drools manual says in the section on accumulate: It is better practice to develop an accumulate function in Java code, implementing org.drools.core.runtime.rule.TypedAccumulateFunction and running this using simple syntax.

How to check equivalence in guvnor web decision table?

I have two facts that I am inserting into my drools session. I want to check the following:
(shipment1 != null && shipment1.shipToCustomerNo == waypoint1.shipToNumber) || shipment1 == null
How do I do add this condition in the guvnor web based decision table? I've tried using a predicate, and waypoint1 and shipment1 are bound variables that are being inserted into the session successfully. If I use the predicate and add what I have above, my test cases work fine, but when I actually run these rules in my java app, the conditions never evaluate true even though the data is equivalent. I've tried many different ways to structure this query. Below is the generated source:
//from row number: 1
rule "Row 1 Arrive Destination"
salience 3
activation-group "arrive-destination"
dialect "mvel"
when
waypoint1 : Waypoint( type == "Destination" )
clm1 : CarLocationMessage( sightCode == "Z" , loaded == true )
shipment1 : Shipment( eval( (shipment1 != null && shipment1.shipToCustomerNo == waypoint1.shipToNumber) || shipment1 == null ))
then
TripEventRuleResult tripEventRuleResult1 = new TripEventRuleResult();
tripEventRuleResult1.setEventType( "Arrive" );
insert( tripEventRuleResult1 );
end
If I understood your domain and problem description correctly, you should be able to do the rule like this.
//from row number: 1
rule "Row 1 Arrive Destination"
salience 3
activation-group "arrive-destination"
dialect "mvel"
when
waypoint1 : Waypoint( type == "Destination" )
clm1 : CarLocationMessage( sightCode == "Z" , loaded == true )
Shipment( shipToCustomerNo == waypoint1.shipToNumber) or
not Shipment()
then
TripEventRuleResult tripEventRuleResult1 = new TripEventRuleResult();
tripEventRuleResult1.setEventType( "Arrive" );
insert( tripEventRuleResult1 );
end
In short, you don't need to have null check for the Shipment object. It either is or is not in the Working Memory

Resources