Reducing a boolean expression - language-agnostic

I am having an expression, suppose,
a = 1 && (b = 1 || b != 0 ) && (c >= 35 || d != 5) && (c >= 38 || d = 6)
I expect it to be reduced to,
a = 1 && b != 0 && (c >= 38 || d = 6)
Does anyone have any suggestions? Pointers to any algorithm?
Nota Bene: Karnaugh Map or Quine-McCluskey are not an option here, I believe. As these methods don't handle grey cases. I mean, expression can only be reduced as far as things are like, A or A' or nothing, or say black or white or absense-of-colour. But here I'm having grey shades, as you folks can see.
Solution: I have written the program for this in Clojure. I used map of a map containing a function as value. That came pretty handy, just a few rules for a few combinations and you are good. Thanks for your helpful answers.

I think you should be able to achieve what you want by using Constraint Handling Rules. You would need to write rules that simplify the OR- and AND-expressions.
The main difficulty would be the constraint entailment check that tells you which parts you can drop. E.g., (c >= 35 || d != 5) && (c >= 38 || d = 6) simplifies to (c >= 38 || d = 6) because the former is entailed by the latter, i.e., the latter is more specific. For the OR-expressions, you would need to choose the more general part, though.
Google found a paper on an extension of CHR with entailment check for user-defined constraints. I don't know enough CHR to be able to tell you whether you would need such an extension.

I believe these kinds of things are done regularly in constraint logic programming. Unfortunatly I'm not experienced enough in it to give more accurate details, but that should be a good starting point.
The general principle is simple: an unbound variable can have any value; as you test it against inequalities, it's set of possible values are restricted by one or more intervals. When/if those intervals converge to a single point, that variable is bound to that value. If, OTOH, any of those inequalities are deemed unsolvable for every value in the intervals, a [programming] logic failure occurs.
See also this, for an example of how this is done in practice using swi-prolog. Hopefully you will find links or references to the underlying algorithms, so you can reproduce them in your platform of choice (maybe even finding ready-made libraries).
Update: I tried to reproduce your example using swi-prolog and clpfd, but didn't get the results I expected, only close ones. Here's my code:
?- [library(clpfd)].
simplify(A,B,C,D) :-
A #= 1 ,
(B #= 1 ; B #\= 0 ) ,
(C #>= 35 ; D #\= 5) ,
(C #>= 38 ; D #= 6).
And my results, on backtracking (line breaks inserted for readability):
10 ?- simplify(A,B,C,D).
A = 1,
B = 1,
C in 38..sup ;
A = 1,
B = 1,
D = 6,
C in 35..sup ;
A = 1,
B = 1,
C in 38..sup,
D in inf..4\/6..sup ;
A = 1,
B = 1,
D = 6 ;
A = 1,
B in inf.. -1\/1..sup,
C in 38..sup ;
A = 1,
D = 6,
B in inf.. -1\/1..sup,
C in 35..sup ;
A = 1,
B in inf.. -1\/1..sup,
C in 38..sup,
D in inf..4\/6..sup ;
A = 1,
D = 6,
B in inf.. -1\/1..sup.
11 ?-
So, the program yielded 8 results, among those the 2 you were interested on (5th and 8th):
A = 1,
B in inf.. -1\/1..sup,
C in 38..sup ;
A = 1,
D = 6,
B in inf.. -1\/1..sup.
The other were redundant, and maybe could be eliminated using simple, automatable logic rules:
1st or 5th ==> 5th [B == 1 or B != 0 --> B != 0]
2nd or 4th ==> 4th [C >= 35 or True --> True ]
3rd or 1st ==> 1st ==> 5th [D != 5 or True --> True ]
4th or 8th ==> 8th [B == 1 or B != 0 --> B != 0]
6th or 8th ==> 8th [C >= 35 or True --> True ]
7th or 3rd ==> 3rd ==> 5th [B == 1 or B != 0 --> B != 0]
I know it's a long way behind being a general solution, but as I said, hopefully it's a start...
P.S. I used "regular" AND and OR (, and ;) because clpfd's ones (#/\ and #\/) gave a very weird result that I couldn't understand myself... maybe someone more experienced can cast some light on it...

Related

OCaml : recursive function dealing with parity between list elements and an int

This function should take two arguments a list and an int. if an element of the list and the number “a” parity is equal then they’d have to be summed, else the two numbers should be subtracted.
The calculation should be done in this order :
At the beginning, the residual value r is the value of a,
Each element e of lst (taken in the order given by the list) affects the residual value: if e and r are of the same parity (both odd or both even) then the new r’ is equal to the sum of r + e, if not then it should be equal to the subtraction of r - e,
The last r is the result expected.
To put this into an example:
par [4;7;3;6] 5
should return -1, it would work as follows :
5 and 4 have a different parity so we subtract -> 5 - 4 = 1
1 and 7 are both odd, so we add them together -> 1 + 7 = 8
8 and 3 have a different parity -> 8 - 3 = 5
Finally, 5 and 6 have different parity -> 5 - 6 = -1
I have thought of something like this below :
let rec par lst a =
match lst with
| [] -> 0
| h::t -> if (h mod 2 == 0 && a mod 2 == 0) || (h mod 2 == 1 && a mod 2 == 1) then a + h
| h::t -> if (h mod 2 == 0 && a mod 2 == 1) || (h mod 2 == 1 && a mod 2 == 0) then a - h :: par t a ;;
EDIT1 : Here is the error I get from the compiler :
Line 4, characters 83-88: Error: This expression has type int but an
expression was expected of type unit because it is in the result of a
conditional with no else branch
The idea is to build this function using no more than the following predefined functions List.hd, List.tl et List.length.
What is disturbing in my proposition above and how to remediate it? Anyone can help me resolve this, please?
EDIT 2:
I was able to do what is needed with if...then... else syntax (not the best I know for OCaml) but I personally have more difficulties sometimes understanding the pattern matching. Anyhow here's what I got :
let rec par lst a = (* Sorry it might hurt some sensible eyes *)
if List.length lst = 0 then a
else
let r = if (List.hd lst + a) mod 2 == 0 then (a + (List.hd lst))
else (a - (List.hd lst)) in
par (List.tl lst) r ;;
val par : int list -> int -> int = <fun>
Suggestions and help to put it into a pattern-matching syntax are welcomed.
Your code doesn't compile. Did you try compiling it? Did you read the errors and warnings produced by the compiler? Could you please add them to your question?
A few comments about your code:
| h::t -> if ... then ... should be | h::t when ... -> ...;
(h mod 2 == 0 && a mod 2 == 0) || (h mod 2 == 1 && a mod 2 == 1) can be simplified to (h - a) mod 2 == 0;
The compiler likes to know that the matching was exhaustive; in particular, you don't need to repeat the test in the third line of the matching (the third line will only be read if the test was false in the second line);
You are missing the recursive call in the second line of the matching;
In the third line of the matching, you are returning a list rather than a number (the compiler should have explicitly told you about that type mismatch!! did you not read the compiler error message?);
In the first line of the matching, in case the list is empty, you return 0. Are you sure that 0 is the value you want to return, when you've reached the end of the list? What about the residual value that you have calculated?
Once you have fixed this version of your code as a recursive function, I recommend trying to write a code solving the same problem using List.fold_left, rather than List.hd and List.tl as you are suggesting.
When I first wrote my answer, I included a fixed version of your code, but I think I'd be doing you a disservice by handing out the solution rather than letting you figure it out.

Finding generators of a finite field

How to find generators of a finite field Fp[x]/f(x) with f(x) is a irreducible polynomial over Fp.
Input: p (prime number), n (positive number), f (irreducible polynomial)
Output: g (generator)
I have p = 2, n =3, f = x^3 + x + 1
I am a newbie so I don't know where to start.
Do you have any solution? Plese help me step by step
To find a generator (primitive element) α(x) of a field GF(p^n), start with α(x) = x + 0, then try higher values until a primitive element α(x) is found.
For smaller fields, a brute force test to verify that powers of α(x) will generate every non-zero number of a field can be done.
cnt = 0
m = 1
do
cnt = cnt + 1
m = (m*α)%f(x)
while (m != 1)
if cnt == (p^n-1) then α(x) is a generator for GF(p^n).
For a faster approach with larger fields, find all prime factors of p^n-1. Let q = any of those prime factors. If α(x) is a generator for GF(p^n), then while operating in GF(p^n):
α(x)^(p^n-1) % f(x) == 1
α(x)^((p^n-1)/q) % f(x) != 1, for all q that are prime factors of p^n-1
In this case GF(2^3) is a 3 bit field and since 2^3-1 = 7, which is prime, then it's just two tests, shown in hex: x^3 + x + 1 = b (hex)
α(x)^7 % b == 1
α(x)^1 % b != 1
α(x) can be any of {2,3,4,5,6,7} = {x,x+1,x^2,...,x^2+x+1}
As another example, consider GF(2^4), f(x) = x^4 + x^3 + x^2 + x + 1 (hex 1f). The prime factors of 2^4-1 = 15 are 3 and 5, and 15/3 = 5 and 15/5 = 3. So the three tests are:
α(x)^f % 1f == 1
α(x)^5 % 1f != 1
α(x)^3 % 1f != 1
α(x) can be any of {3,5,6,7,9,a,b,e}
For larger fields, finding all prime factors of p^n-1 requires special algorithms and big number math. Wolfram alpha can handle up to around 2^128-1:
https://www.wolframalpha.com/input/?i=factor%282%5E64-1%29
This web page can factor large numbers and includes an explanation and source code:
https://www.alpertron.com.ar/ECM.HTM
To test for α(x)^(large number) = 1 or != 1, use exponentiation by repeated squaring while performing the math in GF(p^n).
https://en.wikipedia.org/wiki/Exponentiation_by_squaring
For large fields, where p^n is greater than 2^32 (4 billion), a primitive polynomial where α(x) = x is searched for, using the test mentioned above.

MIPS Programming instruction count issue

I wrote this mips code to find the gcf but I am confused on getting the number of instructions executed for this code. I need to find a linear function as a function of number of times the remainder must be calculated before an answer. i tried running this code using Single step with Qtspim but not sure on how to proceed.
gcf:
addiu $sp,$sp,-4 # adjust the stack for an item
sw $ra,0($sp) # save return address
rem $t4,$a0,$a1 # r = a % b
beq $t4,$zero,L1 # if(r==0) go to L1
add $a0,$zero,$a1 # a = b
add $a1,$zero,$t4 # b = r
jr gcf
L1:
add $v0,$zero,$a1 # return b
addiu $sp,$sp,4 # pop 2 items
jr $ra # return to caller
There is absolutely nothing new to show here, the algorithm you just implemented is the Euclidean algorithm and it is well known in the literature1.
I will nonetheless write an informal analysis here as link only questions are evil.
First lets rewrite the code in an high level formulation:
unsigned int gcd(unsigned int a, unsigned int b)
{
if (a % b == 0)
return b;
return gcd(b, a % b);
}
The choice of unsigned int vs int was dicated by the MIPS ISA that makes rem undefined for negative operands.
Out goal is to find a function T(a, b) that gives the number of step the algorithm requires to compute the GDC of a and b.
Since a direct approach leads to nothing, we try by inverting the problem.
What pairs (a, b) makes T(a, b) = 1, in other words what pairs make gcd(a, b) terminates in one step?
We clearly must have that a % b = 0, which means that a must be a multiple of b.
There are actually an (countable) infinite number of pairs, we can limit our selves to pairs with the smallest, a and b2.
To recap, to have T(a, b) = 1 we need a = nb and we pick the pair (a, b) = (1, 1).
Now, given a pair (c, d) that requires N steps, how do we find a new pair (a, b) such that T(a, b) = T(c, d) + 1?
Since gcd(a, b) must take one step further then gcd(c, d) and since starting from gcd(a, b) the next step is gcd(b, a % b) we must have:
c = b => b = c
d = a % b => d = a % c => a = c + d
The step d = a % c => a = c + d comes from the minimality of a, we need the smallest a that when divided by c gives d, so we can take a = c + d since (c + d) % c = c % c d % c = 0 + d = d.
For d % c = d to be true we need that d < c.
Our base pair was (1, 1) which doesn't satisfy this hypothesis, luckily we can take (2, 1) as the base pair (convince your self that T(2, 1) = 1).
Then we have:
gcd(3, 2) = gcd(2, 1) = 1
T(3, 2) = 1 + T(2, 1) = 1 + 1 = 2
gcd(5, 3) = gcd(3, 2) = 1
T(5, 3) = 1 + T(3, 2) = 1 + 2 = 3
gcd(8, 5) = gcd(5, 3) = 1
T(8, 5) = 1 + T(5, 3) = 1 + 3 = 4
...
If we look at the pair (2, 1), (3, 2), (5, 3), (8, 5), ... we see that the n-th pair (starting from 1) is made by the number (Fn+1, Fn).
Where Fn is the n-th Fibonacci number.
We than have:
T(Fn+1, Fn) = n
Regarding Fibonacci number we know that Fn ∝ φn.
We are now going to use all the trickery of asymptotic analysis, particularly in the limit of the big-O notation considering φn or φn + 1 is the same.
Also we won't use the big-O symbol explicitly, we rather assume that each equality is true in the limit. This is an abuse, but makes the analysis more compact.
We can assume without loss of generality that N is an upper bound for both number in the pair and that it is proportional to φn.
We have N ∝ φn that gives logφ N = n, this ca be rewritten as log(N)/log(φ) = n (where logs are in base 10 and log(φ) can be taken to be 1/5).
Thus we finally have 5logN = n or written in reverse order
n = 5 logN
Where n is the number of step taken by gcd(a, b) where 0 < b < a < N.
We can further show that if a = ng and b = mg with n, m coprimes, than T(a, b) = T(n, m) thus the restriction of taking the minimal pairs is not bounding.
1 In the eventuality that you rediscovered such algorithm, I strongly advice against continue with reading this answer. You surely have a sharp mind that would benefit the most from a challenge than from an answer.
2 We'll later see that this won't give rise to a loss of generality.

Outputs of a program

I am new to programming and I would like to know how to solve questions like this. I was told to expect questions like this on the exam. Can someone please tell me how I would go about solving something like this? Thanks.
x = 0
for num in range(5):
if num % 2 == 0:
x = x + 2
else:
x = x + 1
print(x)
You need to work on a skill which is to "be the compiler", in the sense that you should be able to run code in your head. Step through line by line and make sure you know what is happening. In you code example, you have
for num in range(5) means you will be iterating with num being 0,1,2,3 and 4. Inside the for loop, the if statement num % 2 == 0 is true when num/2 does not have a remainder (how % mods work). So if the number is divisible by 2, x = x+2 will execute. The only numbers divisible by 2 from the for loop are 0,2 and 4. so x=x+2 will execute twice. The else statement x = x +1 runs for all other numbers (1,3) which will execute 2 times.
Stepping through the for loop:
num = 0 //x=x+2, x is now 2
num = 1 //x=x+1, x is now 3, print(x) prints 3
num = 2 //x=x+2, x is now 5
num = 3 //x=x+1, x is now 6, print(x) prints 6
num = 4 //x+x+2, x is now 8
Therefore the answer is that 3 and 6 will be printed
In my opinion,
Whatever language you are using, you need to learn some common elements of the modern programming languages, such as flow-control (if...else in your case), loop(for, in your case)
Some common used functions, in your case, you need to what does range do in Python,
docs.python.org is a good place for you.
As you are new to programming, you can go with the flow in you mind or draw it on the paper.
Using x to store our final result
loop through every item in [0, 1, 2, 3, 4] <- range(5)
a. if
the number is divisible by 2
then increase x by adding 2 to it.
b. else
increase x by adding 1 and print it out
So the result would be :
3
6

Languages where 3 > 2 > 1 is true

I have written a decimal floating point unit for LaTeX3 (pure macros... that was tough). In particular, I have to decide how x < y < z should be parsed. I see three options:
Treat < as a left-associative binary operator, so x < y < z would be equivalent to (x < y) < z. This is what C does: -1 < 0 < 1 becomes (-1 < 0) < 1, thus 1 < 1, which is 0.
Treat < as a right-associative binary operator, so x<y<z would be equivalent to x < (y < z). I see no advantage to that option.
When encountering <, read ahead for more comparison operators, and treat x < y < z as equivalent to (x < y) && (y < z), where y would be evaluated only once. This is what most non-programmers would expect. And quite a few LaTeX users are non-programmers.
At the moment I am using the first option, but it does not seem very natural. I think that I can implement the second case whithout too much overhead. Should I?
Since that question is subjective, let me ask an objective question: what mainstream languages pick option 3? I'm interested in the details of what happens with mixed things like a < b > c == d < e != f. I'm also interested in other choices if they exist.
Short answer: it only makes sense to parse comparison sequences if they are "pointing into the same direction", and when you don't use !=.
Long answer: In Python, 3 > 2 > 1 evaluates to True. However, I have to say that the implementation used is overly simplistic, because it allows for expressions like a < b > c == d < e != f, which are nonsensical in my opinion. The expression would be interpreted as (a < b) and (b > c) and (c == d) and (d < e) and (e != f). It's an easy rule, but because it allows for surprising results, I don't like that interpretation.
I propose a more predictable option:
Consider a proposition xAyBzCw. If this proposition is "sensical", it is equivalent to xAy and yBz and zCw. For "sensicality", it is necessary that...
the values (x, y, z, w) are part of the same set X (or their types can be unified as such), and
the relations (A, B, C) are transitive binary relations on X, and
for every ordered pair of relations A and B, there exists a relation C, such that xAy and yBz implies xCz for all x, y, z; this relation is also subject to these restrictions.
Regarding the last rule, you want to be able to say that 1 < 2 = a < 4 is equivalent to 1<2 and 2=a and a<4, but also that 1<2 and 1<a and 1<4. To say the latter, you must know how = and < interact.
You can't use != in my option, because it isn't transitive. But you also can't say 1 < 3 > 2, 2 < 3 > 1, or 1 < 3 > 1, unless you have a relation ? such that 1?2, 2?1 and 1?1 (basically, it would be a relation allows any pair).
From a syntactical standpoint: you want to treat relational operators as special operators (+ is more of a functional operator), kind of like in your third option.
Python chains relational operators. Which gets interesting when you hit in and is, since they're considered relational as well.
>>> 1 < 2 in [True, False]
False
>>> 1 < 2 in [2, 4]
True
J evaluates statements right-to-left so that:
3 > 2 > 1
Becomes first
2 > 1
Which resolves to true, represented as 1, thus:
3 > 1
Which also resolves to true, thus 1. The opposite operator < would result in false, whereas the whole statement happens to be true. So you're no further with J.
Your main issue is that your initial representation:
3 > 2 > 1
is human shorthand for
(3 > 2) AND (2 > 1)
So while reading ahead seems icky, it's really what the representation needs. Unless of course there's some Python magic, as others have stated.