This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Symbolic simplification in Haskell (using recursion?)
The simplifications I have in mind are
0*e = e*0 = 0
1*e = e*1 = 0+e = e+0 = e-0 = e
and simplifying constant subexpressions, e.g. Plus (Const 1) (Const 2) would become Const 3. I would not expect variables (or variables and constants) to be concatenated: Var "st" is a distinct variable from Var "s".
For example simplify(Plus (Var "x") (Const 0))= Var "x"
Well, can't you apply pattern matching to the individual cases?
simplify (Plus (Const 0) (Expr x)) = simplify (Expr x)
simplify (Plus (Expr x) (Const 0)) = simplify (Expr x)
simplify (Mult (Const 0) _) = Const 0
simplify (Mult _ (Const 0)) = Const 0
– … and so on
EDIT: Yes, of course … recursion added.
I don't know much about haskell, but essentially your are going to want to do an expression tree traversal.
the tree is
EXP: (operator) (EXP) (EXP)
EXP: (const)
EXP: (var)
then your simplify becomes
heres the psuedo code
simplify(Exp e)
if (e is const) return e
else if (e is var) return e
else
{//encode simplification rules
Exp left = simplify(e.left)
Exp right = simplify(e.right)
if(operator is PLUS)
{
if(left == 0) return right;
if(right == 0) return left;
}
else if(operator is MULT)
{
if(left == 1) return right;
if(right == 1) return left;
if(left == 0) return 0;
if(right == 0) return 0;
}
//and so on for other operators
}
this is sort of java esque but i think the idea is there, essentially youre going to have to do a tree traversal.
Related
I have just tried rewriting some code, originally a short Javascript function, in Haskell. The original has 2 nested loops and the inner loop contains a check for equality against both loop counters:
function f(x, points){
var i, j;
var n = points.length;
var result = 0;
for(i=0; i<n; i++){
var xprod = 1;
for(j=0; j<n; j++){
if(j != i){
xprod *= (x - points[j][0]);
}
}
result += points[i][1] * xprod;
}
return result;
}
I was hoping to be able to simplify it in Haskell, but I couldn't figure out how get hold of the i and j values without effectively writing out every step of the original recursively. In Javascript Array.map passes the list position into the callback function as the second parameter, but it seems that map in Haskell doesn't do this. My current Haskell version looks awful to me as I'm passing in 2 copies of the array (one for each loop):
xproduct :: Int -> Int -> Double -> [(Double,Double)] -> Double
xproduct _ _ _ [] = 1
xproduct i j x (pt:todo)
| i == j = (xproduct i (j+1) x todo)
| otherwise = (xproduct i (j+1) x todo) * (x - (fst pt))
solvestep :: Int -> Double -> [(Double,Double)] -> [(Double,Double)] -> Double
solvestep _ _ _ [] = 0
solvestep i x pts (pt:todo) = ((snd pt) * xprod) + (solvestep (i+1) x pts todo)
where xprod = xproduct i 0 x pts
solve :: Double -> [(Double,Double)] -> Double
solve x points = solvestep 0 x points points
Is there a better way to do this?
I generally avoid using any indices at all, if possible. In this case, what you're really working with is: any one element of the list with all the other elements. No need to express that with index comparison, instead write a function that will give you a suitable look into the list:
pickouts :: [a] -> [(a,[a])]
pickouts [] = []
pickouts (x:xs) = (x,xs) : (second (x:) <$> pickouts xs)
Then, the actual computation becomes just
f :: Double -> [(Double,Double)] -> Double
f x points = sum [q * product [x-p | (p,_)<-ps] | ((_,q),ps) <- pickouts points]
Assuming the following definitions:
type Index = Int
data BExp = Prim Bool | IdRef Index | Not BExp | And BExp BExp | Or BExp BExp
deriving (Eq, Ord, Show)
type NodeId = Int
type BDDNode = (NodeId, (Index, NodeId, NodeId))
type BDD = (NodeId, [BDDNode])
I want to build a ROBDD from a boolean expression. So far, I've been able to construct a BDD that doesn't satisfy the no-redundancy or sharing properties.
buildBDD :: BExp -> [Index] -> BDD
buildBDD e idxs
= buildBDD' e 2 idxs
buildBDD' :: BExp -> NodeId -> [Index] -> BDD
buildBDD' (Prim bool) _ []
| bool = (1, [])
| otherwise = (0, [])
buildBDD' e nodeId (idx : idxs)
= (nodeId, [newNode] ++ tl ++ tr)
where
newNode = (nodeId, (idx, il, ir))
(il, tl) = buildBDD' (restrict e idx False) (2 * nodeId) idxs
(ir, tr) = buildBDD' (restrict e idx True) (2 * nodeId + 1) idxs
The naming and style may not be the best, as this is still work in progress.
The nodes are internally represented by a unique id. It starts from 2. The root node of the left subtree will be labelled 2n and the root node of the right subtree will be labelled 2n + 1.
The function will take as input the boolean expression and a list of indices for the variables that appear in the expression.
For example, for the following expression:
And (IdRef 7) (Or (IdRef 2) (Not (IdRef 3)))
The call buildBDD bexp [2,3,7] will return
(2,[(2,(2,4,5)),(4,(3,8,9)),(8,(7,0,1)),(9,(7,0,0)),(5,(3,10,11)),(10,(7,0,1)),
(11,(7,0,1))])
I've made the following changes to account for the no-redundancy property (this has not been tested thoroughly, but appears to be working)
checkEqual (_, l, r)
| l == r = True
| otherwise = False
getElemFromTuple (_, _, e)
= e
getTuple = snd . head
buildROBDD' e nodeId (idx : idxs)
= (nodeId, [newNode] ++ left ++ right)
where
newNode = (nodeId, (idx, lId, rId))
(il, tl) = buildROBDD' (restrict e idx False) (2 * nodeId) idxs
(ir, tr) = buildROBDD' (restrict e idx True) (2 * nodeId + 1) idxs
lId = if (not . null) tl && (checkEqual . getTuple) tl then (getElemFromTuple . getTuple) tl else il
rId = if (not . null) tr && (checkEqual . getTuple) tr then (getElemFromTuple . getTuple) tr else ir
left = if (not . null) tl && (checkEqual . getTuple) tl then [] else tl
right = if (not . null) tr && (checkEqual . getTuple) tr then [] else tr
(excuse the clumsy expressions above)
However, I don't know how to approach the sharing property, especially because the shared node might be anywhere in the graph and I am not storing the current tree. The formula for the unique node ids can be changed if needed.
Note: this is meant as an exercise, so the types and style involved might not be optimal. I am also not supposed to change them (I am free to change the function though).
I'm just learning Haskell and still trying to figure out how things work.
So I'm creating a list class that can hold a mixture of Int and Char.
data Algebra = Empty
| Nmbr Int Algebra
| Smbl Char Algebra
Then I try to make it an instance of Eq
instance Eq Algebra where
Empty == Empty = True
(Nmbr x xl) == (Nmbr y yl) = (x == y) && (xl==yl)
(Smbl x xl) == (Smbl y yl) = (x == y) && (xl==yl)
_ == _ = False
and I get an Ambiguous occurrence == compile error. It can't tell the difference between Main.== and Prelude.==. If I manually replace all == with Main.== or Prelude.== then it compiles fine.
I don't see why the compiler is having so much difficulty here. x and y are clearly defined as being Int or Char in each case. I've compared what I am doing to the numerous tutorial examples (eg http://www.haskell.org/tutorial/classes.html) and I can't determine why the compiler is being such a jerk in this situation :P
You need to indent the body of your instance definition:
instance Eq Algebra where
Empty == Empty = True
(Nmbr x xl) == (Nmbr y yl) = (x == y) && (xl==yl)
(Smbl x xl) == (Smbl y yl) = (x == y) && (xl==yl)
_ == _ = False
Otherwise the compiler sees it as two things:
An instance Eq Algebra with an empty body, producing the default definitions of a == b = not (a /= b) and vice versa.
A definition of a new infix operator named ==.
Then using == in your code now produces an ambiguity between the == from Eq (defined in Prelude) and the == in your code (Main).
And yes, deriving Eq gives you exactly this kind of structural equality.
I want to check the condition of the previous if condition to determine the next if condition is to be executed or not. Each if condition may return a value.
Edit: Sorry for that the example I provided before look a bit odd...:(
This is my real example, and I want to simplify the if-then-else for goingToMove
goingToMove p routes points w h =
if canMove p points
-- the point can be moved in the map
then let r = routes ++ [p]
l = remainList p points
in move p r l w h
-- the point cannot be moved in the maps
else []
move p routes points w h =
if (length routes) == 2
then routes
else let one = goingToMove (tallRightCorner p) routes points w h in
if (null one)
then let two = goingToMove(tallRightBCorner p) routes points w h in
if (null two)
then let three = goingToMove (tallLeftBCorner p ) routes points w h in
if (null three)
then ....
...... -- until, let eight = ..
else three
else two
else one
Edit:Bad example
When this thing is written in java, I may use a mutable boolean flag, and return a mutable data.
public String move (int number){
// base case
if (number == 0){
return "Finished the recursion";
}
// general case
else {
String result;
boolean isNull = false;
if ((result = move(3)) == null){
isNull = true;
}
else {
return result;
}
// continue to execute the if-conditions if the previous condition failed
if (isNull){
if((result = move(2)) == null){
isNull = true;
}
else {
return result;
}
}
if (isNull){
if((result = move(1)) == null){
isNull = true;
}
else {
return result;
}
}
return null;
}
}
But in Haskell, there is no mutable data, and only if-then-else condition. Then the code will looks like this, and I want to simplify this because in my real work, there are 8 levels of if-then-else which look terrible and messy....
move 0 = "Finished the recursion"
move n =
let one = move 3 in
if null one
then let two = move 2 in
if null two
then let three = move 1 in
then null
else three
else two
else one
In Java if I wanted to do the following:
result = func1(arg);
if (result == null){
result = func2(arg);
if (result == null){
result = func3(arg);
if (result == null){
result = func4(arg);
}
}
}
return result;
What I'm essentially doing is finding the first result from func1(args), func2(args), func3(args), func4(args) that returns non-null.
In Haskell, I'd model func1, func2, func3, and func4 as functions that returned a Maybe a value, so that they could return Nothing if they failed.
func1, func2, func3, func4 :: Int -> Maybe Result
Then I can use the <|> operator (from Control.Applicative), which has the following definition for Maybe a:
Nothing <|> x = x
x <|> _ = x
So I can convert the above Java to
func1 arg <|> func2 arg <|> func3 arg <|> func4 arg
And due to the miracle of lazy evaluation, func2 arg is only evaluated if func1 arg returns Nothing, same as in the Java example.
Apart from the nice employment of <|> that rampion gave and the similar suggestion of sclv, another common way is to use guards, and exploit laziness,
move :: Int -> Maybe String
move n
| n == 0 = Just "Finished the recursion"
| isJust move3 = move3
| isJust move2 = move2
| isJust move1 = move1
| otherwise = Nothing
where
move3 = move 3
move2 = move 2
move1 = move 1
Due to laziness, move i (i = 3, 2, 1) is only evaluated if it's needed.
In the given case, move 3 <|> move 2 <|> move 1 is much nicer, but in cases where the conditions require evaluating different functions with different return types, the use of guards and lazy bindings in a where clause can be the natural solution to avoid awkward nested ifs.
edit: Here's some code for the new example:
move p routes points w h
| length routes == 2 = routes
| otherwise = find (not . null) . map gtm [tallRightCorner, tallRightBCorner, tallLeftBCorner]
where gtm f = goingToMove (f p) routes points w h
Note that this returns a maybe. You can use fromMaybe to stick in a default case.
Here's the old (but typechecking) code from the first proposed example
move 0 = "Finished the recursion"
move n = concat . maybeToList . msum $ map move' [3,2,1]
where move' x = let mx = move x in if null mx then Nothing else Just mx
You want routes if its length is 2 or the first non-null result from a series of applications of goingToMove that vary by which corner function is applied to p.
move p routes points w h
| length routes == 2 = routes
| otherwise = head
$ filter (not . null)
$ map tryMove corners
where tryMove f = goingToMove (f p) routes points w h
corners = [ tallRightCorner
, tallRightBCorner
, tallLeftBCorner
-- et cetera
]
An option without Maybe could be to add a flag to the recursion (in the example below, you would call the function with the flag set to one):
move p routes points w h 1
move p routes points w h flag
| (length routes) == 2 = routes
| otherwise =
if null result then move p routes points w h (flag+1)
else result
where result = case flag of
1 -> goingToMove (tallRightCorner p) routes points w h
2 -> goingToMove (tallRightBCorner p) routes points w h
3 -> goingToMove (tallLeftBCorner p) routes points w h
--...etc.
_ -> []
How can I give a general rule that includes all the expressions below?
E.g one expression, another one for sub and one for mult.
I need to use recursion but i got confused...
simplify :: Expr->Expr
simplify (Mult (Const 0)(Var"x"))
= Const 0
simplify (Mult (Var "x") (Const 0))
= Const 0
simplify (Plus (Const 0) (Var "x"))
= Var "x"
simplify (Plus (Var "x") (Const 0))
= Var "x"
simplify (Mult (Const 1) (Var"x"))
= Var "x"
simplify (Mult(Var"x") (Const 1))
= Var "x"
simplify (Minus (Var"x") (Const 0))
= Var "x"
simplify (Plus (Const x) (Const y))
= Const (x + y)
simplify (Minus (Const x) (Const y))
= Const (x - y)
simplify (Mult (Const x) (Const y))
= Const (x * y)
simplify x = x
First up: I know reasonably little about Haskell, and my total time spent programming the language is no more than 8 hours spread over 5 years or so, though I have read plenty about the language. Thus, forgive my no doubt horrible style.
I tackled this problem since it looked like an easy way to get into a little bit of Haskell programming. First up, I made a data type inspired by the sample:
data Expr = Const Int | Mult Expr Expr | Plus Expr Expr | Var String
I made it a little simpler than the original, and left out Minus, but otherwise it's the same.
I quickly found out that values constructed using e.g. "Const 4" were not printable with the above, as there was no show function applicable. I made Expr an instance of the Show type class, and provided a simple definition of show, taking operator precedence into account:
instance Show Expr where
show (Const n) = show n
show (Var n) = show n
show (Plus a b) = (show a) ++ "+" ++ (show b)
show (Mult a b) = "(" ++ (show a) ++ ") * (" ++ (show b) ++ ")"
Next up was the simplification task itself. As Glomek hints, there's an issue with trying to evaluate everything just using pattern matching in one function.
Specifically, for any given operation (all operations in the example are binary) you'd like to first simplify the left tree, then the right tree, and then simplify the current Expr based on what those subtrees evaluated to; e.g. if both simplified to Const, then you can replace the entire subtree with the evaluated operation. However, pattern matching forces you to choose what to do based on the immediate node's children, rather than what the subtrees return after being simplified themselves.
Thus, to get pattern-matching to do the job of deciding whether to evaluate the current node or not as a constant subexpression, it's important to simplify the subtrees, then dispatch based on the simplified whole.
I did this using a separate function I called eval, whose purpose is to pattern-match on things that can be reduced, assuming that subtrees have already been reduced. It also handles multiplication by 0 and 1, and addition of 0:
-- Tries to evaluate any constant expressions.
eval :: Expr -> Expr
eval (Mult (Const a) (Const b)) = Const (a * b)
eval (Mult (Const a) b)
| a == 0 = Const 0
| a == 1 = b
| otherwise = (Mult (Const a) b)
eval (Mult a (Const b))
| b == 0 = Const 0
| b == 1 = a
| otherwise = (Mult a (Const b))
eval (Plus (Const a) (Const b)) = Const (a + b)
eval (Plus (Const a) b)
| a == 0 = b
| otherwise = (Plus (Const a) b)
eval (Plus a (Const b))
| b == 0 = a
| otherwise = (Plus a (Const b))
eval e = e
Now that I have eval, and I know it's safe to call at the top level of an expression tree (i.e. it won't infinitely recurse), I can call it from simplify after I've simplified the subtrees:
-- Tries to match evaluation rules after simplifying subtrees.
simplify :: Expr -> Expr
simplify (Plus a b) = eval (Plus (simplify a) (simplify b))
simplify (Mult a b) = eval (Mult (simplify a) (simplify b))
simplify e = e
This version of simplify has many limitations: it won't distribute a multiplication over a non-Const subtree, it won't reorder the expression to bring constant expressions together (so the equivalent of 1+a+2 won't get simplified to a+3), etc. However, it gets the basic jobs done.
The recursion comes in when you need to deal with nested expressions. For instance, how do you simply (Plus (Plus 2 3) (Plus 4 5))?
One approach is to break it into two functions. Move the one level logic (which you show above) into its own function. The main simplify function might have a rule similar to the following for Plus:
simplify (Plus x y) = simplify_one_level (Plus (simplify x) (simplify y))