Expression Evaluation Oz/Mozart - arithmetic-expressions

I am trying to create a function that takes an expression and evaluates it. Expressions can contain the following operations:
Integers - described by a tuple int(N), where N is an integer.
Addition - described by a tuple add(X Y), where both X and Y are arithmetic expressions.
Multiplication - described by a tuple mul(X Y), where both X and Y are arithmetic
expressions.
Variables - described by a tuple var(A), where A is an atom giving the variable name
An environment - described by a record env(a:5 b:5), where a and b are variables with values of 5.
For example: {Eval add(var(a) mul(int(3) var(b))) env(a:5 b:5)}. Which should evaluate to 20.
So far, I have implemented integers, addition, and multiplication. But I'm not really sure where to start for the variables and the environment.
My current code:
fun {Eval X}
case X of int(N) then N
[] add(X Y) then {Eval X} + {Eval Y}
[] mul(X Y) then {Eval X} * {Eval Y}
end
end

You need to get the value of the variable from the environment. This can be done by passing the env() as parameter to the Eval function, in order to access it from inside.
I have solved it for you. It should be easy to understand.
fun {Eval Statements Env}
case Statements of int(N) then N
[] add(X Y) then {Eval X Env} + {Eval Y Env}
[] mul(X Y) then {Eval X Env} * {Eval Y Env}
[] var(X) then Env.X
end
end
As a side note, this is practically how a common interpreter runs a programming script. By using statement stack and environment to store variable mappings.

Related

Pattern matching with a record in Oz

i'm having some trouble wrapping my head on how to utilize the elements of a record in Oz with pattern matching. Below is my code
declare
fun {Eval X E}
case X
of int(N) then N
[] var(X) then E.X
[] mul(X Y) then X*Y
[] add(X Y) then X+Y
end
end
end
{Eval add(var(a) mul(int(3) var(b))) env(a:2 b:4)}
This is the input I have to utilize, the var(a) is supposed to return 2, (and var(b) return 4) from the env record in the input, I just cannot figure it out for anything.
In your code, you need to call Eval recursively whenever you haven't reached a number or var. Try this instead:
declare
fun {Eval Node Env}
if {IsNumber Node} then Node
else
case Node
of var(X) then Env.X
[] mul(X Y) then {Eval X Env} * {Eval Y Env}
[] add(X Y) then {Eval X Env} + {Eval Y Env}
end
end
end
Additionally, Oz requires the return value of functions to be bound to a variable, so try something like:
declare
Ans = {Eval add(var(a) mul(3 var(b))) env(a:2 b:4)}
You can then view Ans with the Browser to verify the code is correct.

Solving non-linear system of equations in MATLAB

I encountered a non-linear system of equations that has to be solved.
The system of equations can be written as:
Ax + exp(x) = b with b a known Nx1 matrix, A a known NxN matrix, and x the unknown Nx1 vector for which has to be solved. The exp is defined element-wise on the x vector. I tried to search the MATLAB-manual but I'm having a hard time finding how to solve this kind of equations with MATLAB, so I hope someone can help me out.
You can use Newton-Raphson. Re-arrange your system into a zero residual:
R = A * x + exp(x) - b
Then take the derivative of R with respect to x:
dRdx = A + diag(exp(x))
Then iterate. An example is shown below:
n = 3;
a = rand(n, n);
b = rand(n, 1);
% solve a * x + exp(x) = b for x
x = zeros(n, 1);
for itr = 1: 10
x = x - (a + diag(exp(x))) \ (a * x + exp(x) - b);
end
Of course, you could make this more intelligent by stopping iteration after the residual is small enough.
I would solve it iteratively starting with the solution of the linearized system [A+1]x(0)=b-1 as an initial guess, where 1 is an identity matrix. At the each step of the iterative procedure I would add the exponential of the previous solution at the right-hand side: Ax(j)=b-exp(x(j-1))
I just saw this is a cross post.
This is my solution for the other posting:
The function can be written in the form:
$$ f \left( x \right) = A x + \exp \left( x \right) - b $$
Which is equivalent to the above once a root of $ f \left( x \right) $ is found.
One could use Newton's Method for root finding.
The Jacobian (Like the Transpose of Gradient) of $ f \left( x \right) $ is given by:
$$ J \left( f \left( x \right) \right) = A + diag \left( \exp \left( x \right) \right) $$
Hence the newton iteration is given by:
$$ {x}^{k + 1} = {x}^{k} - { J \left( f \left( {x}^{k} \right) \right) }^{-1} f \left( {x}^{k} \right) $$
You can see the code in my Mathematics Q1462386 GitHub Repository which includes both analytic and numerical derivation of the Jacobian.
This is the result of one run:
Pay attention that while it finds a root for this problem there are more than 1 root hence the solution is one of many and depends on the initial point.

Matlab - define a general variable

I want to calculate Fourier series for some function func.
I build this method:
function y = CalcFourier(accurate, func, a, b, val_x)
f = #(x) eval(func);
% calculate coefficients
a0 = (2 / (b - a)) * calcArea(func, a , b);
an = (2 / (b - a)) * calcArea(strcat(func, '*cos(2*n*pi*x / (b - a))'), a , b);
an = (2 / (b - a)) * calcArea(strcat(func, '*sin(2*n*pi*x / (b - a))'), a , b);
partial = 0;
an_f = #(n) an;
bn_f = #(n) bn;
for n = 1:accurate
partial = partial + an_f(n)* cos(2*n*pi*val_x / (b - a)) + bn_f(n) * sin(2*n*pi*val_x / (b - a));
end
y = (a0 / 2) + partial;
end
And this - to approximate the coefficient's:
function area = calcArea(func, a, b)
f = #(x) eval(func);
area = (a - b) * (f(a) - f(b)) / 2;
end
On line an = (2 / (b - a)) * calcArea(strcat(func, '*cos(2*n*pi*x / (b - a))'), a , b); I'm getting error:
??? Error using ==> eval
Undefined function or variable 'n'.
Error in ==> calcArea>#(x)eval(func) at 2
f = #(x) eval(func);
Error in ==> calcArea at 3
area = (a - b) * (f(a) - f(b)) / 2;
Error in ==> CalcFourier at 5
an = (2 / (b - a)) * calcArea(strcat(func,
'*cos(2*n*pi*x / (b - a))'), a , b);
>>
Is there any option to declate n as "some constant"? Thanks!
You try to use a variable called n in line 4 of your code. However at that time n is not defined yet, that only happens in the for loop. (Tip: Use dbstop if error at all times, that way you can spot the problem more easily).
Though I don't fully grasp what you are doing I believe you need something like this:
n=1 at the start of your CalcFourier function. Of course you can also choose to input n as a variable, or to move the corresponding line to a place where n is actually defined.
Furthermore you seem to use n in calcArea, but you don't try to pass it to the function at all.
All of this would be easier to find if you avoided the use of eval, perhaps you can try creating the function without it, and then matlab will more easily guide you to the problems in your code.
if the symbolic toolbox is available it can be used to declare symbolic variables , which can be treated as 'some variable' and substituted with a value later.
however a few changes should be made for it to be implemented, generally converting anonymous functions to symbolic functions and any function of n to symbolic functions. And finally the answer produced will need to be converted from a symbolic value to some more easy to handle value e.g. double
quickly implementing this to your code as follows;
function y = test(accurate, func, a, b, val_x)
syms n x % declare symbolic variables
%f = symfun(eval(func),x); commented out as not used
The two lines above show the declaration of symbolic variables and the syntax for creating a symbolic function
% calculate coefficients
a0 = symfun((2 / (b - a)) * calcArea(func, a , b),x);
an = symfun((2 / (b - a)) * calcArea(strcat(func, '*cos(2*n*pi*x / (b - a))'),...
... a , b),[x n]);
bn = symfun((2 / (b - a)) * calcArea(strcat(func, '*sin(2*n*pi*x / (b - a))'),...
... a , b),[x n]);
partial = 0;
the function definitions in in your code are combined into the lines above, note they functions are of x and n, the substitution of x_val is done later here...
for n = 1:accurate
partial = partial + an(val_x,n)* cos(2*n*pi*val_x / (b - a)) +...
... bn(val_x,n) * sin(2*n*pi*val_x / (b - a));
end
The for loop which now replaces the symbolic n with values and calls the symbolic functions with x_val and each n value
y = (a0 / 2) + partial;
y = double(y);
end
Finally the solution is calculated and then converted to double;
Disclaimer: I have not checked if this code generates the correct solution, however I hope it gives you enough information to understand what has been changed and why to carry out the process given in your code above, using the symbolic toolbox to address the issue...

Isabelle: degree of polynomial multiplied with constant

I am working with the library HOL/Library/Polynomial.thy.
A simple property didn't work. E.g., the degree of 2x *2 is equal to the degree of 2x-
How can I prove the lemmas (i.e., remove "sorry"):
lemma mylemma:
fixes y :: "('a::comm_ring_1 poly)" and x :: "('a::comm_ring_1)"
shows "1 = 1" (* dummy *)
proof-
have "⋀ x. degree [: x :] = 0" by simp
from this have "⋀ x y. degree (y * [: x :] ) = degree y" sorry
(* different notation: *)
from this have "⋀ x y. degree (y * (CONST pCons x 0)) = degree y" sorry
.
From Manuel's answer, the solution I was looking for:
have 1: "⋀ x. degree [: x :] = 0" by simp
{
fix y :: "('a::comm_ring_1 poly)" and x :: "('a::comm_ring_1)"
from 1 have "degree (y * [: x :]) ≤ degree y"
by (metis Nat.add_0_right degree_mult_le)
}
There are a number of issues here.
First of all, the statement you are trying to show simply does not hold for all x. If x = 0 and y is nonconstant, e.g. y = [:0,1:], you have
degree (y * [: x :]) = degree 0 = 0 ≠ 1 = degree y
The obvious way to fix this is to assume x ≠ 0.
However, this is not sufficient either, since you only assumed 'a to be a commutative ring. However, in a commutative ring, in general, you can have zero divisors. Consider the commutative ring ℤ/4ℤ. Let x = 2 and y = [:0,2:].
Then y * [:x:] = [:0,4:], but 4 = 0 in ℤ/4ℤ. Therefore y * [:x:] = 0, and therefore, again,
degree (y * [: x :]) = degree 0 = 0 ≠ 1 = degree y
So, what you really need is one of the following two:
the assumption x ≠ 0 and 'a::idom instead of 'a::comm_ring. idom stands for “integral domain” and, that is simply a commutative ring with a 1 and without zero divisors
more generally, the assumption that x is not a zero divisor
even more generally, the assumption that x * y ≠ 0 or, equivalently, x times the leading coefficient of y is not 0
Also, the usage of ⋀ in Isar proofs is somewhat problematic at times. The “proper“ Isar way of doing this would be:
fix x :: "'a::idom" and y :: "'a poly"
assume "x ≠ 0"
hence "degree (y * [:x:]) = degree y" by simp
The relevant lemmas are degree_mult_eq and degree_smult_eq, you will see that they require the coefficient type to be an idom. This works for the first case I described above, the other two will require some more manual reasoning, I think.
EDIT: just a small hint: you can find theorems like this by typing
find_theorems "degree (_ * _)"
If you try to apply the degree_mult_eq it shows to your situation (with comm_ring), you will find that it fails, even though the terms seem to match. If that is the case, it is usually a type issue, so you can write something like
from [[show_sorts]] degree_mult_eq
to see what the types and sorts required by the lemma are, and it says idom.

How take coordinates from Vector in maple

Is any way to get coordinates from Vector in maple? For example if I would like have function f(V) = sin(V[0]) + cos(V[1]) + V[2]
Where V = (x,y,z). Is it possible in maple?
In Maple a Vector starts its indexing from 1 (not from 0). So the first entry is V[1], rather than V[0].
Also, a Vector can be constructed with either the Vector command or its angle-bracket shortcut notation. Round brackets do not construct a Vector, as they are delimiters for either grouping or arguments of function application.
restart:
f := V -> sin(V[1]) + cos(V[2]) + V[3]:
W := Vector([a,b,c]):
f(W);
sin(a) + cos(b) + c
Y := <3,7,11>:
f(Y);
sin(3) + cos(7) + 11
An Array is more flexible and can be constructed so as to start its indexing from 0.
g := V -> sin(V[0]) + cos(V[1]) + V[2]:
W := Array(0..2,[q,r,s]):
g(W);
sin(q) + cos(r) + s
Note that the LinearAlgebra package deals with Matrix and Vector. Also, some arithmetic operations (such as .) act in an elementwise manner for Array and not a way you might expect for doing computational linear algebra.
restart:
F := Array(1..3,[q,r,s]):
F . F;
[ 2 2 2]
[q , r , s ]
U := Vector[row]([q,r,s]):
U . U;
_ _ _
q q + r r + s s
Note the complex conjugation occuring in the last example. And in contrast with Matrix structures, 2-dimensional Arrays are also multiplied elementwise under the . operator.