Evaluate rules in prolog - prolog

I want to convert the following decision rules to Prolog language
------Decision Rules---------
if (Right-Weight <= 2.5) and (Left-Weight > 2.5) and (Left-Distance > 1.5) then class: R (proba: 95.4%) | based on 87 samples
if (Right-Weight > 2.5) and (Right-Distance <= 2.5) and (Left-Weight > 1.5) then class: R (proba: 71.08%) | based on 83 samples
if (Right-Weight <= 2.5) and (Left-Weight <= 2.5) and (Left-Distance > 2.5) then class: R (proba: 63.41%) | based on 41 samples
if (Right-Weight > 2.5) and (Right-Distance > 2.5) and (Left-Weight > 2.5) then class: L (proba: 63.54%) | based on 96 samples
if (Right-Weight > 2.5) and (Right-Distance > 2.5) and (Left-Weight <= 2.5) then class: L (proba: 98.48%) | based on 66 samples
if (Right-Weight > 2.5) and (Right-Distance <= 2.5) and (Left-Weight <= 1.5) then class: L (proba: 77.78%) | based on 27 samples
if (Right-Weight <= 2.5) and (Left-Weight <= 2.5) and (Left-Distance <= 2.5) then class: L (proba: 65.22%) | based on 23 samples
if (Right-Weight <= 2.5) and (Left-Weight > 2.5) and (Left-Distance <= 1.5) then class: L (proba: 50.0%) | based on 14 samples
-----------------------------
Tried to come up with the following rules in prolog.
classR(Right-Weight, Left-Weight, Left-Distance) :-
(Right-Weight <= 2.5) , (Left-Weight > 2.5) , (Left-Distance > 1.5);
(Right-Weight > 2.5) , (Right-Distance <= 2.5) , (Left-Weight > 1.5);
(Right-Weight <= 2.5) , (Left-Weight <= 2.5) , (Left-Distance > 2.5)
classL(Right-Weight, Left-Weight, Left-Distance) :-
(Right-Weight > 2.5) , (Right-Distance > 2.5) , (Left-Weight > 2.5);
(Right-Weight > 2.5) , (Right-Distance > 2.5) , (Left-Weight <= 2.5);
(Right-Weight > 2.5) , (Right-Distance <= 2.5) , (Left-Weight <= 1.5);
(Right-Weight <= 2.5) , (Left-Weight <= 2.5) , (Left-Distance <= 2.5);
(Right-Weight <= 2.5) , (Left-Weight > 2.5) , (Left-Distance <= 1.5)

evaluate(RW, LW, LD, RD, OP) :-
((RW =< 2.5),(LW > 2.5),(LD > 1.5) -> OP = 'R';
(RW > 2.5) , (RD =< 2.5) , (LW > 1.5) -> OP = 'R';
(RW =< 2.5) , (LW =< 2.5) , (LD > 2.5) -> OP = 'R';
(RW > 2.5) , (RD > 2.5) , (LW > 2.5) -> OP = 'L';
(RW > 2.5) , (RD > 2.5) , (LW =< 2.5) -> OP = 'L';
(RW > 2.5) , (RD =< 2.5) , (LW =< 1.5) -> OP = 'L';
(RW =< 2.5) , (LW =< 2.5) , (LD =< 2.5) -> OP = 'L';
(RW =< 2.5) , (LW > 2.5) , (LD =< 1.5) -> OP = 'L').

Related

How to refactor round method with 3 digits

I would like to round float numbers like this :
125.212 = 125.250
125.249 = 125.250
125.268 = 125.250
125.280 = 125.275
125.999 = 126.000
I have do a method, how can I refactor it ?
def round_km(n)
n = n * 1000
m = n % 100
if (m <= 25)
"%.3f" % ((n - m + 25) / 1000).round(3)
elsif (m <= 50)
"%.3f" % ((n - m + 50) / 1000).round(3)
elsif (m <= 75)
"%.3f" % ((n - m + 75) / 1000).round(3)
else
"%.3f" % ((n - m + 100) / 1000).round(3)
end
end
I found a better solution :
def round_km(n)
"%.3f" % ((n/0.250).ceil * 0.250)
end

SWITCH with clauses differing by a constant increment

Below is my SWITCH. I want to put it in a loop. I want to constantly increase my SWITCH by 2.5, because I have a lot of different values from 0 to 1000.
Order Amount =
SWITCH (
TRUE(),
Order[Amount Order] >= 0 && Order[Amount Order] < 5 , "< 5",
Order[Amount Order] >= 5.1 && Order[Amount Order] <= 7.5, "5 - 7.5",
Order[Amount Order] >= 7.51 && Order[Amount Order] <= 10, "7.51 - 10",
Order[Amount Order] >= 10.01 && Order[Amount Order] <= 12.5, "10.01 - 12.5",
Order[Amount Order] >= 12.51 && Order[Amount Order] <= 15, "12.51 - 15",Blank())
Maybe This can help you, just let me know if it does. Thanks.
This formula succeeded for me:
Order Amount =
VAR _ceil = CEILING('Order'[Amount Order] / 2.5, 1) * 2.5
VAR _big_result = CONVERT(_ceil-2.49, STRING) & " - " & CONVERT(_ceil, STRING)
RETURN SWITCH(TRUE(),
'Order'[Amount Order] >= 0 && 'Order'[Amount Order] < 5 , "< 5",
'Order'[Amount Order] >= 5 && 'Order'[Amount Order] <= 7.5, "5 - 7.5",
_big_result)

how to make arcsin not cyclical and have it be evaluated at each point

So I'm solving a set of four differential equations in mathematica using NDSolve. I also use ArcSin as a part of the equations. Now, my ArcSin value is insensitive to the value of y, causing the solution to get periodic.
For example, for x=1,y=1, I get ArcSin as pi/4. IF I make it x=1,y=-1, it still remains pi/4. How do I avoid the cyclic behavior? I know, that the condition should be like if y<0, add pi to the solution. I'm failing to write it correctly.
Any help appreciated.
ClearAll["Global`*"]
\[Alpha]1 = 0.5;
\[Sigma]1 = -1;
Subscript[\[CapitalTheta], N] = \[Pi]/2;
traceractive =
NDSolve[{x'[
t] == ((-\[Alpha]1*(x[t] -
X[t]))/((x[t] - X[t])^2 + (y[t] - Y[t])^2)^(3/
2)) - (2*
Cos[Subscript[\[CapitalTheta], N] -
ArcSin[(x[t] - X[t])/((x[t] - X[t])^2 + (y[t] - Y[t])^2)^(1/
2)]]*\[Alpha]1*\[Sigma]1)/((x[t] - X[t])^2 + (y[t] -
Y[t])^2)^(3/
2) + ((y[t] - Y[t])*
Sin[Subscript[\[CapitalTheta], N] -
ArcSin[(x[t] - X[t])/((x[t] - X[t])^2 + (y[t] - Y[t])^2)^(1/
2)]]*\[Alpha]1*\[Sigma]1)/((x[t] - X[t])^2 + (y[t] -
Y[t])^2)^2,
y'[t] == ((-\[Alpha]1*(y[t] -
Y[t]))/((x[t] - X[t])^2 + (y[t] - Y[t])^2)^(3/
2)) - (2*
Cos[Subscript[\[CapitalTheta], N] -
ArcSin[(x[t] - X[t])/((x[t] - X[t])^2 + (y[t] - Y[t])^2)^(1/
2)]]*\[Alpha]1*\[Sigma]1)/((x[t] - X[t])^2 + (y[t] -
Y[t])^2)^(3/
2) - ((x[t] - X[t])*
Sin[Subscript[\[CapitalTheta], N] -
ArcSin[(x[t] - X[t])/((x[t] - X[t])^2 + (y[t] - Y[t])^2)^(1/
2)]]*\[Alpha]1*\[Sigma]1)/((x[t] - X[t])^2 + (y[t] -
Y[t])^2)^2, X'[t] == 0, Y'[t] == 0, x[0] == 0.1,
y[0] == 0.02, X[0] == 0, Y[0] == 0}, {x, y, X, Y}, {t, 0, 1000}]
xlist = Flatten[Table[x[t] /. traceractive, {t, 0, 100}]];
ylist = Flatten[Table[y[t] /. traceractive, {t, 0, 100}]];
Xlist = Flatten[Table[X[t] /. traceractive, {t, 0, 100}]];
Ylist = Flatten[Table[Y[t] /. traceractive, {t, 0, 100}]];
Tracer = Transpose#{xlist, ylist};
Length[Tracer];
Activep = Transpose#{Xlist, Ylist};
P1 = ListPlot[Tracer, Joined -> True]
P2 = ListPlot[Activep, PlotMarkers -> Automatic]
Show [P1, P2, Graphics[{PointSize[0.025], Point[{Tracer[[1]]}]}],
Graphics[{PointSize[0.025], Red, Point[{Tracer[[Length[Tracer]]]}]}],
PlotRange -> All, AxesOrigin -> {0, 0}]
(*Black point: Tracer initial position, Red point: Tracer final \
position*)

How to group combined AND with OR statements using the Sequel GEM in Ruby?

I am fairly good at PHP (OOP & flat). And for the past year or so I have been tasked with maintaining a Ruby codebase; a skill I am still learning. I am not too clear on how to properly structure a filtering chain using Sequel so AND as well OR statements can be properly contained.
This is the MySQL query structure I want to have:
SELECT * FROM `some_objects`
WHERE (
(
((`datebegin` >= 1950) AND (`datebegin` <= 1959)) OR ((`dateend` >= 1950) AND (`dateend` <= 1959))
)
OR
((`datebegin` <= 1950) AND (`dateend` >= 1959))
AND
(NOT `datebegin` = 0) AND (NOT `dateend` = 0)
)
;
And this is the Sequel code fragment I am using:
some_objects = where{((datebegin >= start_year) & (datebegin <= end_year)) | ((dateend >= start_year) & (dateend <= end_year))}.
or{(datebegin <= start_year) & (dateend >= end_year)}.
where(~:datebegin => 0, ~:dateend => 0)
And this is what I am actually getting:
SELECT * FROM `some_objects`
WHERE (
(
((`datebegin` >= 1950) AND (`datebegin` <= 1959)) OR ((`dateend` >= 1950) AND (`dateend` <= 1959))
OR
((`datebegin` <= 1950) AND (`dateend` >= 1959))
)
AND
(NOT `datebegin` = 0) AND (NOT `dateend` = 0)
)
;
I have also tried different variations on the same Sequel code such as this:
some_objects = where(:datebegin => start_year..end_year).
or(:dateend => start_year..end_year).
or{|o|(o.datebegin <= start_year) & (o.dateend >= end_year)}.
where(~:datebegin => 0, ~:dateend => 0)
And this:
some_objects = where(:datebegin => start_year..end_year).
or(:dateend => start_year..end_year).
or{(datebegin <= start_year) & (dateend >= end_year)}.
where(~:datebegin => 0, ~:dateend => 0)
But I still end up with the first SQL structure where this whole chunk is basically ((AND OR AND OR)):
(
((`datebegin` >= 1950) AND (`datebegin` <= 1959)) OR ((`dateend` >= 1950) AND (`dateend` <= 1959))
OR
((`datebegin` <= 1950) AND (`dateend` >= 1959))
)
When I want ((AND OR AND) OR):
(
((`datebegin` >= 1950) AND (`datebegin` <= 1959)) OR ((`dateend` >= 1950) AND (`dateend` <= 1959))
)
OR
((`datebegin` <= 1950) AND (`dateend` >= 1959))
The issue with your initial query is that you are depending on the OR/AND precedence rules instead of using explicit parentheses. Your initial query could be expressed as:
SELECT * FROM `some_objects`
WHERE (
((`datebegin` >= 1950) AND (`datebegin` <= 1959))
OR
((`dateend` >= 1950) AND (`dateend` <= 1959))
OR
((`datebegin` <= 1950) AND (`dateend` >= 1959) AND (NOT `datebegin` = 0) AND (NOT `dateend` = 0))
)
You could express this in Sequel as:
DB[:some_objects].where{((datebegin >= start_year) & (datebegin <= end_year)) | ((dateend >= start_year) & (dateend <= end_year))}.
or{((datebegin <= start_year) & (dateend >= end_year)) & Sequel.negate(:datebegin => 0)}
Which yields the following SQL:
SELECT * FROM `some_objects` WHERE (
((`datebegin` >= 1950) AND (`datebegin` <= 1959))
OR
((`dateend` >= 1950) AND (`dateend` <= 1959))
OR
((`datebegin` <= 1950) AND (`dateend` >= 1959) AND (`datebegin` != 0))
)
This should perform the same as the SQL you used, but it is a bit more readable (e.g. datebegin != 0 instead of NOT datebegin = 0). Note that you don't need the NOT dateend = 0 filter, because it is a subset of the dateend >= 1959 filter.
Remember with Sequel if you're really up against the wall, just spell out your conditions the hard way:
records = where(%Q[
(
(`datebegin` >= 1950 AND `datebegin` <= 1959)
OR (`dateend` >= 1950 AND `dateend` <= 1959)
)
OR (`datebegin` <= 1950 AND `dateend` >= 1959)
])
Those "zero" dates are kind of annoying from a query perspective, they'd be better off as NULL so they wouldn't need to be excluded here. Since NULL is never greater than, less than, or equal to anything, it's invisible to these queries. Zero, on the other hand, is a valid number and has to be excluded.
As an example of how this works with ranges:
records = where(datebegin: (1950..1959)).or(dateend: (1950..1959))
Those are expressed with the BETWEEN operator. From an indexing perspective that's usually at least a little faster than a bounded range using AND.

how to assign integration limits in mathematica after solving a set of inequalities

I have a set of inequalities, for example,
2 x1 >=3 x2 && 0<=x1<=1 && 0<=x2<=1
which can be solved with Reduce. Then I want to do an integration for the function f(x1,x2)=1/x1 in the area defined by the inequalities above. In this case, Reduce gives a result
(x1 == 0 && x2 == 0) || (0 < x1 <= 1 && 0 <= x2 <= (2 x1)/3)
Then I can do integration by using
Integrate[Integrate[1/x1, {x2, 0, 2 x1/3}], {x1, 0, 1}]
But these all need my manual intervention. How do I do this in a streamline fashion? Many thanks!
Integrate[1/x1 Boole[2 x1 >= 3 x2 && 0 <= x1 <= 1 &&0 <= x2 <= 1], {x1, -\[Infinity], \[Infinity]}, {x2, -\[Infinity], \[Infinity]}]

Resources