Drools - Find matching object from a list of unconnected objects - drools

I have a Mutation class with 3 variables, m1, m2, and m3. I also have a list of independent objects of a class Strain with 1 variable v. I need to be able to match a number of these objects i a list to the variables m1, m2 and m3.
Here is the Mutation class
class Mutation{
String m1;
String m2;
String m3;
}
The class Strain has a single variable m and is shown below:
class Strain {
String m;
}
I want to find the Strains that match the mutation. Here is what I tried with no success.
rule "Find the mathcing strains for the mutation"
when
$m: Mutation ( $m1: m1, $m2: m2, $m3: m3)
$s1: Strain( m == $m1 )
$s2: Strain( m == $m2 )
$s3: Strain ( m == $m3)
then
System.out.println("Found matching Strains");
end
However, this does not work. I have all the Strain objects and the Mutation objects inserted in the session. I also print out the values of the list of Mutation objects and the list of Strain objects and see the m values of the Strain objects that match the Mutation values, m1, m2 ad m3.
What am I doing wrong? Is this achievable using Drools? I'm sure it's my solution which has the problem. I would really appreciate finding a solution to this problem. I have scoured the net looking for a similar problem but haven't come across a solution that could fix this problem.
I summary, List mutations ... variables, m1,m2 and m3
List strains .. variable m
Please would really appreciate help in pointing me where I am going wrong, thanks in advance.

Related

Conditional declaration by array of records

I try to create many components depending on the value of constant elements. These elements are organized in an array of records.
Dymola prints the translation log for the example below:
But I'm sure to use fixed conditions because I only perform allowed operations on constant values.
Here is the simple example of what I wantet to do:
model ConditionalComponent
type Enum = enumeration(one,two,three);
record Tmp
parameter Integer ID;
parameter Boolean active;
end Tmp;
record TmpNamed
parameter Enum name;
extends Tmp;
end TmpNamed;
function reorder
input TmpNamed inp[:];
output Tmp out[size(inp,1)];
algorithm
for elem in inp loop
out[elem.name] := Tmp(elem.ID, elem.active);
end for;
end reorder;
constant TmpNamed testIn[:] = {
TmpNamed(Enum.two,20,true),
TmpNamed(Enum.one,10,true),
TmpNamed(Enum.three,30,true)};
constant Tmp testOut1[:] = reorder({
TmpNamed(Enum.two,20,true),
TmpNamed(Enum.one,10,true),
TmpNamed(Enum.three,30,true)});
constant Tmp testOut2[:] = reorder(testIn);
constant Boolean active1 = testOut1[Enum.one].active;
constant Boolean active2 = testOut2[Enum.one].active;
Real t1=0 if testOut1[Enum.one].active;
//Real t2=0 if testOut2[Enum.one].active;
//Real t3=0 if active1;
//Real t4=0 if active2;
end ConditionalComponent;
The function reorder is intended to ease the management of large lists of named active components. Normally the constant testOut2 is used and created within the package ConditionalComponent. But for testing purposes ConditionalComponent is a model here. Actually I only want to use the line
Real t2=0 if testOut2[choice].active;
parameter Enum choice = Enum.one;
within other components, that have a parameter of type Enum. The declarations for t1, t3, t4 are only some tests that work, depending on what is left uncommented.
For example leaving the declaration for t1 and t3 uncommented works. But if one uses only the declaration for t1, it is not translated by Dymola.
The difference between t1 and t2 is, that the argument for reorder is passed directly or via the constant testIn.
I'm sure, that most parameter and constant prefixes are unnecessary and I tried hard to figure out the problem. But unfortunately I cannot decide whether Dymola is not working correctly or I did something wrong. And I've got no idea how to debug the translation process to figure it out by myself.
Can anyone tell me, what am I doing wrong?
Not something wrong, but it's just currently seen as too complicated and not handled.
A work-around is to split subscripting and element access:
constant Tmp testOut1_one=testOut1[Enum.one];
Real t1=0 if testOut1_one.active;

Exists condition in Drools

The context is employee shift rostering in OptaPlanner with Drools rules. Assume that I have some shifts and that I need to check if any of the shifts is in a list of pre-defined shifts to assign. The latter list of shifts to assign is, say, [S1,S2,S3]; I need to match the following condition (I use a colon as a "such that"):
exists s in [S1,S2,S3] : forall shift (shift != s)
How could I implement such a rule in Drools?
The following pattern will match if there is no Shift that is member of [S1, S2, S3].
not Shift( this memberOf [S1, S2, S3] )
Not sure if the list literal [S1, S2, S3] is Drools-compatible but I assume it's going to be something dynamic that will be inserted into working memory as a fact.
I think you need to represent the list of shifts to be assigned [S1, S2, S3] as a different type of fact (ShiftToAssign):
Shift { // planning entity
String id;
LocalDateTime: time;
Emploee employee;
}
ShiftToAssign { // planning fact
String id;
}
Then, instead of adding/removing elements to the pre-defined list of shifts to assign, you simply add them to #ProblemFactCollectionProperty. They will be automatically inserted into Drools working memory and so you'll be able to match your condition like this:
$s : ShiftToAssign // equivalent to: for each Si in [S1, S2, S3]
not Shift(id == $s.id) // equivalent to: there is no Shift whose id is member of the list

pythonic way to delete edge attributes

In order to remove attributes from a networkx graph I have the following code:
for (n1,n2) in graph.edges(data=False):
for att in att_list:
graph[n1][n2].pop(att, None)
Is there a more pythonic way to do so?
If you only want to delete a few attributes in some list, say att_list
for n1, n2, d in graph.edges(data=True):
for att in att_list:
d.pop(att, None)
Or you can replace the last line with if att in d: del d[att] if it bothers you that pop returns something that you aren't using. The improvement compared to your code is that by having data=True I get d immediately, rather than having to reference graph[n1][n1] later.
See Removing multiple keys from a dictionary safely for how to remove multiple keys from a dictionary (which is what d is). Fundamentally that's what your problem reduces to once you've got d.
Alternately, if you want to clear all of the attributes, then note that if we set data=True, then graph.edges also returns a dictionary with the attributes. Clear this dictionary.
for (n1, n2, d) in graph.edges(data=True):
d.clear()
Here's a complete example
import networkx as nx
G=nx.Graph()
G.add_edge(1,2,weight=2)
G.edge[1][2]
> {'weight': 5}
for (n1, n2, d) in G.edges(data=True):
d.clear()
G.edge[1][2]
> {}
#just to check the edge in the opposite order
G.edge[2][1]
> {}

A simple model in Winbugs but it says "This chain contains uninitialized variables"

I have some simple time to event data, no covariates. I was trying to fit a Weibull distribution to it. So I have the following code. Everything looks good until I load my initials. It says "this chain contains uninitialized variables". But I don't understand. I think Weibull dist only has 2 parameters, and I already specified them all. Could you please advise? Thanks!
model
{
for(i in 1 : N) {
t[i] ~ dweib(r, mu)I(t.cen[i],)
}
mu ~ dexp(0.001)
r ~ dexp(0.001)
}
# Data
list(
t.cen=c(0,3.91,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,21.95,23.98,33.08),
t=c(2.34,NA,5.16,5.63,6.17,6.8,7.03,8.05,8.13,8.36,8.83,10.16,
10.55,10.94,11.48,11.95,13.05,13.59,16.02,20.08,NA,NA,
NA),
N=23
)
# Initial values
list(
r=3,mu=3
)
The other uninitialised variables are the missing (NA) values in the vector of t. Remember that the BUGS language makes no distinction between data and parameters, and that supplying something as data with the value NA is equivalent to not supplying it as data.

MATLAB: is fieldnames' order defined?

For the same input structure, will fieldnames always return the same cell array, even on different computers, different OS's, and different MATLAB versions? Or could it order the field names differently? E.g.:
myStructure = load myStructure;
x = fieldnames(myStructure);
% days later, diff computer, diff OS, and diff version of MATLAB...
y = fieldnames(myStructure);
x == y %?
The documentation for fieldnames does not seem to promise that the same order is returned every time. But on the other hand, the existence of orderfields seems to imply that fieldnames predictably returns an underlying, normally unchanging order.
I believe the structure fields are ordered as they created. If you save the structure into mat-file and open it later with another MATLAB, the order will be kept. You can always reorder fields with ORDERFIELDS function. You can order in many different ways (sort alphabetically, using a cell arrays, another structure or permutation vector), see the documentation for more details.
By the way, fields order does not affect structures comparison.
s1 = struct('a',0,'b',1)
s1 =
a: 0
b: 1
s2 = struct('b',1,'a',0)
s2 =
b: 1
a: 0
isequal(s1,s2)
ans =
1
s1=orderfields(s1,s2)
s1 =
b: 1
a: 0
UPDATE:
Here is the quote from the MATLAB documentation for structure data type under "Listing the Fields of a Structure" subtitle:
The fields appear in the order in which they were created.
Hope this answers your question.