I'm new to prolog and i can't find a solution to filter list by 2 conditions, save result into 2 variables and then evaluate answer base on them.
In my case, if list contains more numbers that greater then 0, then numbers lesser then 0.
For example i get a list with elements:
checklist([-2, 3.3, 12, -10.1, 14, -11, 123]) # true
checklist([-2.1, -3, -4, 14, 16.7]) # false
checklist([11.5, 2.5, -34.1, -1]) # false
I'd write something like this in python:
bigger_count = 0
lesser_count = 0
for num in list:
if num > 0:
bigger_count += 1
elif num < 0:
lesser_count += 1
print(bigger_count > lesser_count)
Especially i doesn't understand how to work with 2 variables at one time.
https://www.swi-prolog.org/pldoc/doc_for?object=include/3
https://www.swi-prolog.org/pldoc/doc_for?object=convlist/3
If you have 2 conditions, you need to traverse the list twice, but is the complexity of code that can handle two different predicates worth the trouble?
Anyway, if you're writing from scratch, you can simplify your life by using DCGs:
filter(_Pred, []) --> [].
filter(Pred, [X|Xs]) -->
( { call(Pred, X) }
-> [X]
; []
),
filter(Pred, Xs).
filter(Pred, List, Result) :-
phrase(filter(Pred, List), Result).
even(X) :- 0 is X mod 2.
?- filter(even, [1,2,3,4,5], X).
X = [2, 4]
Another possible solution is:
check(List) :-
check(List, Balance),
Balance > 0.
check([], 0).
check([X|Xs], B) :-
check(Xs, B0),
( X > 0 -> B is B0 + 1
; X < 0 -> B is B0 - 1
; B is B0 ).
Examples:
?- check([-2, 3.3, 12, -10.1, 14, -11, 123]).
true.
?- check([-2.1, -3, -4, 14, 16.7]).
false.
?- check([11.5, 2.5, -34.1, -1]).
false.
?- check([1,-1]).
false.
The easiest way is to use a worker predicate that carries the required extra state.
checklist( Ns, P, N ) :- checklist(Ns, 0, 0, P, N )
checklist( [] , P , N , P , N ) .
checklist( [X|Xs] , P0 , N0 , P , N ) :- X > 0, P1 is P0+1, checklist(Xs,P1,N0,P,N).
checklist( [X|Xs] , P0 , N0 , P , N ) :- X < 0, B1 is N0+1, checklist(Xs,P0,N1,P,N).
If you add up all the values in the list, you'll get a positive or negative result which varies with how big the numbers are, instead of how many there are. There is a mathematical function sign or signum which turns all negative values into -1, and all positive values into +1, then you can add them up and if there were more positive inputs, the answer is positive, if there are more negative inputs, the answer is negative. Or they will cancel out and the sum will be 0.
If you maplist signthat over the inputs:
?- maplist(sign, [-2, 3.3, 12, -10.1, 14, -11, 123], X).
X = [-1, 1.0, 1, -1.0, 1, -1, 1]
Then:
?- sum_list(X, S).
S = 1.0
a positive result, so more positives than negatives in this case.
you could partition/4 the input list into the smaller vs larger values:
?- partition(>(0), [-2, 3.3, 12, -10.1, 14, -11, 123], Lesser, Greater).
Lesser = [-2, -10.1, -11],
Greater = [3.3, 12, 14, 123]
Then use length/2 and compare the result to see which one is longer.
(This might not be useful if any of the inputs are 0, they are not in your examples. I think this will use more memory to make a copy of the list.).
As the question suggests, I'm trying to define linear constraints for the condition "if x1 ≤ 0, then x2 ≤ 0" with x1, x2 in [-10, 10]. I have tried doing this as follows, where B1 is a binary variable and M is a very large number:
X2 - M * X1 * B1 ≤ 0
X1 ≤ 11 * B1
-11 * B1 ≤ X1
The idea is that b1=1 if x>0 and b1=0 if x1≤0. However, this is incorrect because when x1 = 0, we have that b1 can be both 0 or 1. I don't know how to change this without using strict inequalities, which is not possible. Can anyone help?
X2 - M * X1 * B1 ≤ 0 looks non-linear to me. Here is my proposal:
x1 ≥ 0.001 - 10.001*b
x2 ≤ 10*(1-b)
b ∈ {0,1}
The 0.001 is there to force b=1 when x1=0.
Having the following theory:
theory BitVector
imports Main
begin
datatype bitvector = BTM | BITV bool bitvector
lemma "∀ x1 x2 y1 y2. (BITV x1 x2 = BITV y1 y2) = (x1=y1) ∧ (x2=y2)"
I get the following proof state:
proof (prove): step 0
goal (1 subgoal):
1. ∀x1 x2 y1 y2. (BITV x1 x2 = BITV y1 y2) = (x1 = y1) ∧ x2 = y2
Auto Quickcheck found a counterexample:
x1 = False
x2 = BITV True BTM
y1 = False
y2 = BTM
What kind of equality is this here? It is obvious that it is not the structural equality that is of Standard ML. Or, is there a bug in this formalisation?
Be careful with equality of boolean-type expressions. Due to operator precedence, the proposition of your lemma is actually the following:
lemma "∀ x1 x2 y1 y2. ((BITV x1 x2 = BITV y1 y2) = (x1=y1)) ∧ (x2=y2)"
This is obviously false. What you should write is:
lemma "∀ x1 x2 y1 y2. (BITV x1 x2 = BITV y1 y2) = ((x1=y1) ∧ (x2=y2))"
In fact, due to these operator precedence issues, I prefer using ⟷ for equality of boolean expressions:
lemma "∀ x1 x2 y1 y2. BITV x1 x2 = BITV y1 y2 ⟷ x1 = y1 ∧ x2 = y2"
Moreover, one would normally write a lemma such as this without the HOL universal quantifiers and instead use the following, which is equivalent:
lemma "BITV x1 x2 = BITV y1 y2 ⟷ x1 = y1 ∧ x2 = y2"
All of these lemmas are easily proven by the simplifier, as they are direct consequences of the injectivity lemmas that are automatically provided by the datatype command.
I should also mention that instead of defining bit vectors yourself, you may want to use the predefined formalisation of bit vectors in src/HOL/Word. Some examples exist in src/HOL/Word/Examples.
I have problem:
Write a function called minimum6 that takes 6 arguments and returns the smallest one.
Example: minimum6 10 20 30 40 50 60 = 10
and this is what i got so far:
let min a b = if a < b then a else b;;
let minimum6 x1 x2 x3 x4 x5 x6 = min (min (min (min (min x1 x2) x3) x4) x5) x6);;
however, i get 'This expression has type int but an expression was expected of type 'a -> 'b' pointing to the first '10'
I'm new to the language, what did i do wrong? was it because i used a function in a function?
You have some parentheses problems. :)
You could also do something more general. Something like:
let rec list_min min = function
| [] -> min
| x::xs -> if x < min then list_min x xs else list_min min xs
let min6 x1 .. x6 = list_min x1 [x2; ...; x6]