Sometimes Sympy gives me alternate answers, that depend on assumptions on the function arguments, e.g.
integrate(sin(pi*x/L), (x, 0, L))
⎧ π
⎪ 0 for ─ = 0
⎪ L
⎨
⎪2⋅L
⎪─── otherwise
⎩ π
I know that the value L is positive and is limited, so that the first answer is of no relevance to me... how can I tell Sympy that π/L is strictly greater than zero or, as I said in the title, that L is bounded?
SymPy symbols can represent infinities (oo, -oo, zoo) as well. Some arithmetics with these is possible. When L is infinite, pi/L is zero, so we get the integral of 0, which is zero. In this sense, SymPy's answer is correct. If L is meant to be finite, declaring it as such with
L = symbols("L", finite=True)
is enough to get 2*L/pi as an answer.
Or you can leave L as is and tell SymPy to not worry about the edge cases with conds="none" parameter of the integration.
integrate(sin(pi*x/L), (x, 0, L), conds="none") # 2*L/pi
Aside: real=True does not exclude the possibility of L being oo or -oo, as these are considered real: oo.is_real is True (this is a contentious point in SymPy development).
Related
If I try to have an expression whose value depends on another expression
from sympy import *
x = symbols('x')
y1 = x/cos(x)
y2 = y2 if y1>0 else nan
but an exception is raised
File /usr/lib/python3.10/site-packages/sympy/core/relational.py:511, in Relational.__bool__(self)
510 def __bool__(self):
--> 511 raise TypeError("cannot determine truth value of Relational")
TypeError: cannot determine truth value of Relational
Is there a chance of having the effect that I'd want?
In case my problem is a X-Y problem, what I ultimately want to do is to plot x/cos(x) only where the function is positive.
UPDATE
I used the useful suggestion of #Oscar Benjamin (that completely answers my original question) but I have other issues when plotting the Piecewiswe function, that I'll expose in another question, as well as a wrong plot when I use the plot_implicit solution they suggested.
What you're looking for is Piecewise:
In [8]: p = Piecewise((x/cos(x), x/cos(x) > 0), (S.NaN, True))
In [9]: p
Out[9]:
⎧ x x
⎪────── for ────── > 0
⎨cos(x) cos(x)
⎪
⎩ nan otherwise
A more direct solution to your problem though would be something like
plot_implicit(Eq(y, x/cos(x)) & (x/cos(x) > 0))
I am new to Standard ML. I am trying to compute x squared i, where x is a real and i is an non-negative integer. The function should take two parameters, x and i
Here is what I have so far:
fun square x i = if (i<0) then 1 else x*i;
The error that I am getting is that the case object and rules do not agree
The unary negation operator in SML is not - as it is in most languages, but instead ~. That is likely what is causing the specific error you cite.
That said, there are some other issues with this code. L is not bound in the example you post for instance.
I think you may want your function to look more like
fun square (x : real) 0 = 1
| square x i = x * (square x (i - 1))
You'll want to recurse in order to compute the square.
With Prolog I want to simplify algebra expression represented as as list of list:
algebra equation
f = 3x+2
list of list
[[3,1],[2,0]]
3 and 2 are coefficients
1 and 0 are exponents
That should be obvious.
I am looking for some tips or suggestions on how to code the simplifications for this example:
f = 3x+2x+1+2
[[3,1],[2,1],[1,0],[2,0]]
simplified:
f = 5x+3
[[5,1],[3,0]]
I have tried some built in functions but did not get the proper idea about how to use them.
One liner, similar to what's proposed by joel76:
simplify(I,O) :-
bagof([S,E],L^(bagof(C,member([C,E],I),L),sum_list(L,S)),O).
The inner bagof collects C (coefficients) given E (exponents), the resulting list L is summed into S, and paired with E becomes [S,E], an element (monomial) of O.
If you omit the universal quantification specifier (that is L^) you get single monomials on backtracking.
You can solve your problem in this way:
simplify(_,_,S,S,[]):- !.
simplify(L,I,Sum,NTot,[[I,S]|T]):-
Sum =< NTot,
findall(X,member([X,I],L),LO),
length(LO,N),
S1 is Sum + N,
sum_list(LO,S),
I1 is I+1,
simplify(L,I1,S1,NTot,T).
write_function([]).
write_function([[D,V]|T]):-
write(' + '),write(V),write('x^'),write(D),
write_function(T).
test:-
L = [[3,1],[2,1],[1,0],[2,0]],
length(L,N),
simplify(L,0,0,N,LO),
LO = [[D,V]|T],
write('f='),write(V),write('x^'),write(D),
write_function(T).
The main predicate is simplify/5 which uses findall/3 to find all the coefficients with the same degree and then sums them using sum_list/2. Then you can write the result in a fancy way using write_function/1.
In SWI-Prolog You can use aggregate :
pred(>, [_,X], [_,Y]) :- X > Y.
pred(<, [_,X], [_,Y]) :- X < Y.
pred(=, [_,X], [_,X]).
simplify(In, Out) :-
aggregate(set([S,X]), aggregate(sum(P), member([P,X], In), S), Temp),
predsort(pred, Temp, Out).
For example :
?- simplify([[3,1],[2,1],[1,0],[2,0]], Out).
Out = [[5, 1], [3, 0]] ;
false.
boost::number::ublas contains the M::size_type lu_factorize(M& m) function. Its name suggests that it performs the LU decomposition of a given matrix m, i.e. should produce two matrices that m = L*U. There seems to be no documentation provided for this function.
It is easy to deduce that it returns 0 to indicate successful decomposition, and a non-zero value when the matrix is singular. However, it is completely unclear where is the result. Taking the matrix by reference suggests that it works in-place, however it should produce two matrices (L and U) not one. So what does it do?
There is no documentation in boost, but looking at the documentation of SciPy's lu_factor one can see, that it's not uncommon to return one result for the LU decomposition.
This is enough, because in a typical approach to LU decomposition, L's diagonal consists of ones only, as presented in this answer from Mathematics, for example.
So, it is possible to fit both L and U into one matrix, putting L in result's lower part, omitting the diagonal (which is assumed to contain only ones), and U in the upper part. For example, for a 3x3 problem the result is:
u11 u12 u13
m = l21 u22 u23
l31 l32 u33
which implies:
1 0 0
L = l21 1 0
l31 l32 1
and
u11 u12 u13
U = 0 u22 u23
0 0 u33
Inspecting boost's void lu_substitute(const M& m, vector_expression<E>& e) function, from the same namespace seems to confirm this. It solves the equation LUx = e, where both L and U are contained in its m argument in two steps.
First solve Lz = e for z, where z = Ux, using lower part of m:
inplace_solve(m, e, unit_lower_tag ());
then, having computed z = Ux (with e modified in place), Ux = e can be solved, using upper part of m:
inplace_solve(m, e, upper_tag ());
inplace_solve is mentioned in the documentation, and it:
Solves a system of linear equations with triangular form, i.e. A is triangular.
So everything seems to make sense.
The boost doesn't have document of LU factorization (a lower triangular matrix L and upper triangular matrix U), but the source code shared with the public.
If the code is hard to follow, please check the webpage by Nick Higham. It had an detailed explanation. Here are an example from the link:
Let's say we need to solve Ax = b.
(1) Make LU from input matrix, A
[3 -1 1 1]
[-1 3 1 -1] ->
[-1 -1 3 1]
[1 1 1 3]
Low
[1 0 0 0]
[-1/3 1 0 0]
[-1/3 -1/2 1 0]
[1/3 1/2 0 1]
Upper
[3 -1 1 1]
[0 8/3 4/3 -2/3]
[0 0 4 1]
[0 0 0 3]
This example looks straight forward to human but algorithm wise could be numerous steps. This is why LU Factorization came. Methodically, Relation with Gaussian Elimination, Schur Complements, and Block Implementations are some.
(2) Solve the triangular systems Ly = b and Ux = y, since then b = L(Ux).
This should be an easy fix, but I can't seem to tackle this, and it's getting frustrating. I've coded a program which computes or verifies that two lists are related because the elements of the second list are all incremented by one from the elements of the first list. This works when two lists are given, but not when it needs to compute a list.
Code is as follows:
inc([], []).
inc([X|XS],[Y|YS]) :-
Y =:= X+1,
inc(XS,YS).
ERROR: =:=/2: Arguments are not sufficiently instantiated
Any help would be greatly appreciated!
Your problem is essentially that =:=/2 is for testing rather than establishing bindings, though is/2 still doesn't really do what you want. For instance, while 2 is 1 + 1 is true, 2 is X+1 will not result in X being bound to 1, because is/2 expects there to be just one variable or value on the left and one expression on the right, and it does not behave "relationally" like the rest of Prolog. If you want arithmetic that behaves this way, you should check out clpfd; looking at the complexity it adds is a good explanation for why things are the way they are.
Fortunately, you don't need all of arithmetic to solve your problem. The succ/2 builtin will do exactly what you need, and bonus, you get a one line solution:
inc(X, Y) :- maplist(succ, X, Y).
In use:
?- inc([1,2,3], [2,3,4]).
true.
?- inc([1,2,3], X).
X = [2, 3, 4].
?- inc(X, [1,2,3]).
X = [0, 1, 2].
Your code also works fine if you use succ/2 instead of =:=/2:
inc([], []).
inc([X|XS],[Y|YS]) :-
succ(X, Y),
inc(XS,YS).
This must be the "easy fix" you suspected. :)
I'm not sure what #mbratch is referring to about there being "too many variables" for one predicate. I suspect this is a misunderstanding of Prolog on their part, perhaps a holdover from other languages where a function can return one value or something. There is no technical limitation here; predicates can take as many ground or nonground arguments and bind as many of them as you want; the limiting factor is your creativity.
Similarly, I don't think "asymmetry" is a meaningful concept here. It's quite normal to define predicates that have just a single instantiation pattern, but it's also normal and preferable to make predicates that are flexible about instantiation—you can't know ahead of time what uses may be needed in the future. You might think to yourself that an instantiation pattern that destroys information might preclude the inverse instantiation pattern, but in practice, frequently you can turn it into a generator instead.
To give a trite example, append/3's name seems to imply this pattern:
?- append([1,2], [3,4], X).
X = [1,2,3,4]
That's a perfectly good use, but so is:
?- append(X, Y, [1,2,3,4]).
This is a non-deterministic instantiation pattern and will produce five solutions:
X = [], Y = [1,2,3,4]
X = [1], Y = [2,3,4]
X = [1,2], Y = [3,4]
X = [1,2,3], Y = [4]
X = [1,2,3,4], Y = []
This seems to stand in contradiction to some of #mbratch's ideas, but there's no explicit testing for ground/nonground in the usual definition of append/3, because it isn't necessary, and likewise with the second calling pattern you get two "return values" from one input. SWI source:
append([], L, L).
append([H|T], L, [H|R]) :-
append(T, L, R).
Edit: Negative numbers. I forgot that succ/2 is defined only on positive integers. We can apply #mbratch's technique and still get a tidy solution with the desired properties:
isucc(X, Y) :- var(X), X is Y-1.
isucc(X, Y) :- Y is X+1.
inc(X, Y) :- maplist(isucc, X, Y).
In action:
?- inc(X, [-1,2]).
X = [-2, 1] ;
false.
Edit: Using clp(fd) (via #mat):
fdsucc(X,Y) :- Y #= X + 1.
inc(X, Y) :- maplist(fdsucc, X, Y).
This generates even for the most general query:
?- inc(X, Y).
X = Y, Y = [] ;
X = [_G467],
Y = [_G476],
_G467+1#=_G476 ;
X = [_G610, _G613],
Y = [_G622, _G625],
_G610+1#=_G622,
_G613+1#=_G625 ;
X = [_G753, _G756, _G759],
Y = [_G768, _G771, _G774],
_G753+1#=_G768,
_G756+1#=_G771,
_G759+1#=_G774
...
The utility of this is questionable, but presumably since you're using clp(fd) you'll eventually impose other constraints and get something useful.
inc([],[]).
inc([X|XS],[Y|YS]) :-
nonvar(X),
Z is X + 1,
Y = Z,
inc(XS,YS), !.
inc([X|XS],[Y|YS]) :-
nonvar(Y),
Z is Y - 1,
X = Z,
inc(XS,YS), !.
Here we need to get a real computation for the addition, then attempt instantiation with =. The predicate had to be split to deal with the case where X was not instantiated, versus when Y wasn't. The ! at the end of each is to prevent it from trying for more solutions after it has found one through one of the two similar paths.