I have to write a program that tests whether two algebraic expressions are equivalent. It should follow MDAS precedence and parenthesis grouping. To solve the problem about precedence, I'm thinking I should implement a Infix to Postfix Notation converter for these expressions. But by doing this, I could not conclude their equivalence.
The program should look like this:
User Input: a*(a+b) = a*a + a*b
Output : Equivalent
For this problem I'm not allowed to use Computer Algebraic Systems or any external libraries. Please don't post the actual code if you have one, I just need an idea to work this problem out.
If you are not allowed to evaluate the expressions, you will have to parse them out into expression trees.
After that, I would get rid of all parenthesis by multiplying/dividing all members so a(b - c) becomes a*b - a*c.
Then convert all expressions back to strings, making sure you have all members alphabetically sorted (a*b, not b*a) ,remove all spaces and compare strings.
That's an idea:
You need to implement building expression tree first because it's a very natural representation of expression.
Then maybe you'll need to simplify it by open brackets and etc. using associative or distributive algebraic properties.
Then you'll have to compare trees. It's not obvious because you need to take care of all branch permutations in commutative operations and etc. E.g. you can sort them (I mean branches) and then compare for equality. Also you need to keep in mind possible renaming of parameters, i.e. a + b need to be equal x + y.
Related
I am trying to create a predicate split_exp, which takes an algebraic expression that uses only "+" functor and generates two lists, one of the atoms and one of numbers. For example, 1+a+b+3 should generate [1,3] and [a,b]. The expression can be of any length.
I have tried.
split_exp(X,[X|[]],[]):-number(X).
split_exp(X,[],[X|[]]):-atom(X).
split_exp(X+Y,[X|Ns],Na):-number(X),split_exp(Y,Ns,Na).
split_exp(X+Y,Ns,[X|Na]):-atom(X),split_exp(Y,Ns,Na).
Kindly explain to me where i am going wrong in this implementation.
Should be easy to spot from your code, corrected and simplified:
split_exp(X,[X],[]):-number(X).
split_exp(X,[],[X]):-atom(X).
split_exp(Y+X,[X|Ns],As):-number(X),split_exp(Y,Ns,As).
split_exp(Y+X,Ns,[X|As]):-atom(X),split_exp(Y,Ns,As).
Note the recursive call, still using Y. Since (+)/2 is left associative (?- current_op(_,A,+) yields A=yfx as second result, since there is also the unary form), you must recurse on the left branch, which I did swapping X and Y subterms in the head(s).
You can show the expression shape using the ISO builtin ?- write_canonical(E) or ?- display(E).
I am trying to write an algorithm for presenting the below mathematical expression in a binary tree in order to present the post fixed and prefixed expression.
I know the precedence levels of common used operators, and i know how to deal with normal mathematical expressions, but i am not familiar with the use of inequalities like < >= , add for that the use of AND.
any help will be appreciated
Operator precedence usually goes
arithmetic > equality > logical
so the < and >= would evaluate before the AND.
Treat them like normal arithmetic operators when building the parse tree but give equality operators lower precendence than arithmetic, and logical lower than that.
for example check the java operator precendence
How can I realize/understand what is the preferential order/precedence of operators while converting infix notation to postfix notation :
" * ", " / ", " + ", " - ", " ^ ", " ) ", " ( ".
I understand that one can just look at an algorithm for this and solve this but I don't want to do that. What should be my thought process?
Operator precedence is a convention and property of a formal infix language to indicate which operations should evaluate first. A higher precedence operation means that it should operate before lower precedence operations.
Grouping parentheses are not part of the operator precedence. (Note that other kinds of parentheses such as function call parentheses may be however I am assuming you do not refer to those here) They are used to explicitly indicate the order of operations. Parentheses are only useful to indicate an order of operations in infix notation. The purpose of the operator precedence convention in a given language is to avoid using parentheses in most case. So, for example, if I want to multiply 4 by 5 and then add 7 to the result, I can write:
4*5+7
This is valid under normal arithmetic operator precedence rules because multiplication ('*') has higher precedence than addition ('+'). But if I want to add 3 and 4 and then multiply this result by 8, I need to write:
(3+4)*8
In this case I want the order of operations to be different than the normal order of "higher precedence operations first." In other words, parenthesis are only necessary when we are using infix notation and want operations to execute in an order other than precedence-order.
In standard arithmetic, exponentiation ("^") has highest precedence. Next is multiplication and division (equal precedence) and finally addition and subtraction. Therefore, an infix expression written using these operators without parenthesis will evaluate all exponentiation first, then all multiplications and divisions (in left to right order) and finally all additions and subtractions, again in left to right order.
If you want to infer the operator precedence of an unknown language, you would need to look at the places where parentheses are and are not used. Since it is valid to use parentheses everywhere even when unnecessary, this is only a heuristic. For the examples above, I can write:
((4*5)+7)
And this gives no hint about operator precedence. It is because every binary operator in this case has parentheses, and therefore at least one of the two sets is redundant assuming the precedence of addition and multiplication are not the same.
Similarly, looking at the next example:
(3+4)*8
since parentheses were used around the addition but not the multiplication, we can infer that probably in this language addition has lower precedence than multiplication. Otherwise, the parenthesis would be redundant. So look for the pattern where parentheses are and are not used to try to figure out operator precedence in unknown languages. It is more common to assume a certain precedence level based on the formal specification of the language under consideration. Most formal languages have an operator precedence chart for the infix form to avoid this ambiguity.
We never need parentheses in prefix or postfix languages because the order of terms and operators already makes the order of evaluation explicit. Therefore this issue is really an infix-language-specific problem.
If parentheses are balanced properly you can always find a parenthesis-free subexpression, which reduces the problem to that case.
Now just ask yourself, according to precedence rules, which operation in such an expression should be performed first?
I am studying on Ivan Bratko book: "Programming for artificial intelligence"
Now I am studying the operators and I have some doubts about it, on the book I can read the following thing:
So the precedence of the operators decides what is the correct interpretation of expressions. For example, the expression a + b*c can be, in principle, understood either as:
1. +(a, *(b,c))
or as:
2. *(+(a,b), c)
And now I havde the first doubt: "what it means this thing? it seems me very strage because these two expressions give different three and different result !!!
For example if I have: a=2, b=3, c=4
The result of the first one is 14 and the result of the second one is 20 so there are different: different thress means different order of operator execution that means different result !!!
So I think that (using the usual priority of arithmetic operator: execute first the multiplications and after the sums) the correct expression is the first one and the second one is wrong.
Is it correct?
Continuing to read the book I can read also:
The general rule is that operator with the highest precedence is the principal functor of the term. If expression containing + and * are to be understood according to our normal convention, then + have a higher precedence then * operator
and now I have the second doubt: as I said, in normal convention of arithmetic I execute first the multiplications and after the sums,so in my opinion is the * operator that have the precedence and not +
What I am missing about it? Why on the book say that + has higher precedence then *?
"The principal functor of the term" means the last operation to be executed, or the outermost one in prefix notation. This definition is the inverse of yours, thus the contradiction.
So the precendence of the operators decides what is the correct interpretation of expressions. For example, the expression a + b*c can be, in principle, understood either as:
+(a, *(b,c))
or as:
*(+(a,b), c)
It says that without precedence, those are 2 possible ways to interpret the expression (and different way of parsing the expression will give different result). You only know to group a + (b * c) when you know that * should be executed before +. (I avoid explaining with precedence here, since it is confusing as pointed out below).
+ and * are just symbols, and it just happens that they are used as operator with some defined precedence. Generally speaking, you can define anything to be an operator, and give it a precedence.
The general rule is that operator with the highest precedence is the principal functor of the term. If expression containing + and * are to be understood according to our normal convention, then + have a higher precedence than * operator
The definition of precedence in English is "The condition of being considered more important than someone or something else; priority in importance, order, or rank". As long as something has to happen before some other thing, we have a precedence.
In C, operator precedence is the order of binding in an expression. Higher precedence operator in C will get executed before lower precedence operators.
In Prolog, the precedence is the order of getting the functor, which is the reverse of the case of C operator's order of binding. Higher precedence operator will appear earlier when we analyze the expression with =...
I have a question about abstract syntax trees.
In particular I want to sort several trees with an particular
term order.
How can one define a term order for an AST with the following properties:
For allmost all terms, the order behaves exactly
like the standard built-in order of terms.
Deeply nested in the AST there are terms of functor
pos/6 which denote source-positions.
These functors should be ignored in the term order, i.e. all terms of functor pos should compare as equal.
Is is possible to extend the built-in term-order with
a special case for 'pos' ?
What is the most efficient solution, what is the most
readable solution ?
Maybe I should also mention that our ASTs can be quite big, I just benchmarked one AST, which has 217479 proper functors (ignoring the nullary atoms)
I would define a relation ast_without_pos/2 that relates an AST A0 to a term A that is the same as A0 except that all pos/6 subterms are replaced by the same term, say the atom t, and then use the standard term order on these resulting terms. I think this is very readable, and also reasonably efficient.
You could look at Zippers over the AST?
Here is an example over lists:
http://blog.logtalk.org/2013/04/zipper-lists-in-prolog/
If you get the sources for Termite, I think you will find a more general implementation over trees.
http://www.complang.tuwien.ac.at/adrian/termite/Manual/Contents.html
Any help to you?