My student gives me an answer in the form:
x=4 and y=3
Now I want to find out what x and y is in maxima, and give feedback. For example, "x is correct, but y is incorrect". I know that if the student gives the answer as a list, I can do:
solve([x=4, y=3], [x,y])
Is there a way to either convert this and expression to a list, or make maxima find out for me what x and y is directly?
If the input expression is a string, then you can use parse_string:
a: "x=3 and y = 4"$
inpart(parse_string(a),1);
(%o1) x = 3
exp: map(lambda([i],inpart(parse_string(a),i)), [1,2]);
(%o2) [x = 3, y = 4]
solve(exp, [x,y]);
(%o3) [[x = 3, y = 4]]
I assume that you can obtain a Maxima expression from the input via parse_string or some other means.
Let e be the expression. Then subst("and"="[", e) returns an expression which has the operator "[" (i.e., a list) instead of "and".
Another way is to use split:
str:"x=4 and y=3";
spl:split(str,"and");
>>> ["x=4 "," y=3"]
eq:map(parse_string,spl);
>>> [x=4,y=3]
Related
I'm using z3py, how do I check whether an expression contains a given variable or expression? For example,
x = Int('x')
expr = x + 1
So, expr should contains variable x.
I've checked the z3.py source code, but I didn't find a solution. Any idea? Thanks.
You can write a simple recursive descent walk over the expression:
from z3 import *
def contains(x, e):
return x.__repr__() == e.__repr__() or any([contains(x, c) for c in e.children()])
x, y, z = Ints('x y z')
expr = x + 2 * y
print(contains(x, expr))
print(contains(y, expr))
print(contains(z, expr))
print(contains(x+2, expr))
print(contains(2*y, expr))
print(contains(y*2, expr))
print(contains(1, IntVal(2)))
print(contains(1, IntVal(1)))
print(contains(x, x))
print(contains(x, y))
This prints:
True
True
False
False
True
False
False
True
True
False
However, I should caution that in typical z3 programming you already know what your variables are. (After all, you have to declare them explicitly!) So, unless you're writing some high-level library code, you should simply keep track of what variables you have and just check in this list. Recursive-descents like this can be expensive for large expressions.
I'm trying to understand traversing quantified formula in z3 (i'm using z3py). Have no idea how to pickup the quantified variables. For example in code shown below i'm trying to print the same formula and getting error.
from z3 import *
def traverse(e):
if is_quantifier(e):
var_list = []
if e.is_forall():
for i in range(e.num_vars()):
var_list.append(e.var_name(i))
return ForAll (var_list, traverse(e.body()))
x, y = Bools('x y')
fml = ForAll(x, ForAll (y, And(x,y)))
same_formula = traverse( fml )
print same_formula
With little search i got to know that z3 uses De Bruijn index and i have to get something like Var(1, BoolSort()). I can think of using var_sort() but how to get the formula to return the variable correctly. Stuck here for some time.
var_list is a list of strings, but ForAll expects a list of constants. Also, traverse should return e when it's not a quantifier. Here's a modified example:
from z3 import *
def traverse(e):
if is_quantifier(e):
var_list = []
if e.is_forall():
for i in range(e.num_vars()):
c = Const(e.var_name(i) + "-traversed", e.var_sort(i))
var_list.append(c)
return ForAll (var_list, traverse(e.body()))
else:
return e
x, y = Bools('x y')
fml = ForAll(x, ForAll (y, And(x,y)))
same_formula = traverse( fml )
print(same_formula)
I am working on a simple function that should, given x, return a tuple (y, z) such that y <= abs(5) + z * 10 = x, where z the smallest possible value.
In C, I would loop over z++ and y++, until their sum matches x.
Currently, I am trying to solve this problem functionally. Please consider the following example:
let foo x =
let rec aux (y, z, q) =
match (y + z * 10) with
q -> (y, z)
|_ -> aux(y + 1, z + 1, q) //How to correctly set the increments?
aux(0, 0, x)
This approach always returns (0, 0), no matter what. I referred to this question, while thinking a solution. I am aware that mutable variables should be avoided, and that is what I do. Unfortunately, I am afraid I missed the point, somewhere, thus I am approaching the problem from the wrong side.
You're introducing a new q binding for the result of the expression evaluated in your first case match rather than comparing against it. What you want is something like this:
match (y + z * 10) with
| r when r = q -> (y, z)
| _ -> aux(y + 1, z + 1, q)
In F# you are generally either within a value expression or a pattern matching expression. When you do this:
match (y + z * 10) with
q -> (y, z)
You're effectively saying: "Calculate y + z * 10 and then always assign the result to a new variable q, ignore this new variable and return (y, z)". This is because q is written in a pattern matching expression as it's just after with.
This is also why you're getting a warning on the next line saying "This rule will never by matched". This is a very common misunderstanding when people are learning F#.
You're not really making use of pattern matching at all when you do this. So I would recommend using an if expression instead:
if y + z * 10 = q
then (y, z)
else aux (y + 1, z + 1, q)
This is actually equivalent to using the ternary operators ? and : in C because it's an expression, not a statement, but it reads more clearly.
exchangeSymbols "a§ b$ c. 1. 2. 3/" = filter (Char.isAlphaNum) (replaceStr str " " "_")
The code above is supposed to first replace all "spaces" with "_", then filter the String according to Char.isAlphaNum. Unfortunately the Char.isAlphaNum part absorbs the already exchanged "_", which isn't my intention and i want to hold the "_". So, i thought it would be nice just add an exception to the filter which goes like:
exchangeSymbols "a§ b$ c. 1. 2. 3/" = filter (Char.isAlphaNum && /='_') (replaceStr str " " "_")
You see the added && not /='_'. It produces a parse error, obviously it is not so easily possible to concatenate filter options, but is there a smart workaround ? I thought about wrapping the filter function, like a 1000 times or so with each recursion adding a new filter test (/='!'),(/='§') and so on without adding the (/='_'). However it doesn't seem to be a handy solution.
Writing
... filter (Char.isAlphaNum && /='_') ...
is actually a type error (the reason why it yields a parse error is maybe that you used /= as prefix - but its an infix operator). You cannot combine functions with (&&) since its an operator on booleans (not on functions).
Acutally this code snipped should read:
... filter (\c -> Char.isAlphaNum c && c /= '_') ...
Replace your filter with a list comprehension.
[x | x <- replaceStr str " " "_", x /= '_', Char.isAplhaNum x]
Naturally, you probably want to have multiple exceptions. So define a helper function:
notIn :: (Eq a) => [a] -> a -> Bool
notIn [] _ = True
notIn x:xs y = if x == y
then False
else notIn xs
EDIT: Apparently you can use notElem :: (Eq a) => a -> [a] -> Bool instead. Leaving above code for educational purposes.
And use that in your list comprehension:
[x | x <- replaceStr str " " "_", notElem x "chars to reject", Char.isAlphaNum x]
Untested, as haskell isn't installed on this machine. Bonus points if you are doing a map after the filter, since you can then put that in the list comprehension.
Edit 2: Try this instead, I followed in your footsteps instead of thinking it out myself:
[x | x <- replaceStr str " " "_", Char.isAlphaNum x || x == ' ']
[x | x <- replaceStr str " " "_", Char.isAlphaNum x || x `elem` "chars to accept"]
At this point the list comprehension doesn't help much. The only reason I did change it was because I you requested an &&, for which using a list comprehension is great.
Since it seems that you don't quite understand the principle of the list comprehension, its basically applying a bunch of filters and then a map with more than one source, for example:
[(x, y, x + y) | x <- [1, 2, 3, 4, 5], y <- [2, 4], x > y]
i would like to add 1 items to a list which has only one item and add items(after using toInt to convert to integer) in a list y if number of items greater than 1 and the last items are the same
How to do?
import Data.List.Split
z = splitOn "+" "x^2+2*x^3+x^2"
y = map (splitOn "*") z
x = map head y
toInt :: [String] -> [Int]
toInt = map read
u = filter ((map length y)>1) y
Couldn't match expected type `a0 -> Bool' with actual type `Bool'
In the first argument of `filter', namely `((map length y) > 1)'
In the expression: filter ((map length y) > 1) y
In an equation for `u': u = filter ((map length y) > 1) y
Failed, modules loaded: none.
Your definition of u is obviously bad. It helps if you give type signatures, so we understand a little better what you are trying to do (even when you don't tell us in words).
You commented that you want all lists of length > 1, this is the same as getting all non-null lists after dropping the first element. So use filter, which tests each element separately (so you don't need map), and build a function that either tests a single list for length > 1 or it's sublist for null:
-- Use the O(n) length for your filter
u = filter ((> 1) . length) y
-- Or use an O(1) drop + null test
u' = filter (not . null . drop 1) y
Without using function composition (.) these functions are:
u = filter (\sublist -> length (sublist) > 1) y
u' = filter (\sublist -> not (null (drop 1 sublist))) y
The compiler is telling you that map length y > 1 is a boolean value, but filter wants a function there. I am not sure what you really want do to with y, please specify what you expect for different values of y.