# mini-Tutorial ¿Com es fa amb wxMaxima?

 Aquest document conté una informació molt bàsica perquè no més preten ser
un document d'introducció a wxMaxima o de consulta ràpida i ajuda d'urgència.


José Sánchez Marín.- Departament de Química Física- Universitat de València.- octubre-2010

Traduït a l'octubre-novembre de 2016 per Alfredo M.J. Sánchez de Merás

/* Provat wxMaxima 11.04.0 (MacOSX 10.5.8 Intel Core 2 Duo) */  octubre-2011
/* Provat wxMaxima 15.04.0 (MacOSX 10.11.6 Intel Quadcore i7) */  novembre-2016

## Ús bàsic

Un clic de ratolí en la pantalla fa aparèixer el cursor horitzontal.
Una cel·la d'input es genera, on estigui el cursor horitzontal, simplement teclejant-ho.

Cada instrucció de input acaba amb ";".  
S'executa la cel·la en què està el cursor vertical d'escriptura, prement alhora Mayuscula+Enter. 
Totes les instruccions d'una cel·la s'executen, consecutivament,

100;  100+100;
100+50;

"$" en lloc de ";" inhibeix l'output. Malgrat això, la instrucció s'executa.
EN QUALSEVOL CAS, ÉS CONVENIENT NO UTILITZAR-HO PRÀCTICAMENT MAI 

100;  100+100$  100+50;

"/*    */" El que s'escriu entre /* i */ es considera "comentari" i no s'executa
NO obstant això, Maxima llig els comentaris i produeix error si troba accents. 
En canvi, en les cel·les de text sí es pot usar accents

100; /* 100 + 200 */ 100+50;

Si es fa clic en el triangle superior del símbol de cel·la, solament es mostra la primera línia d'input.

"%" fa sempre referència al resultat de l'última instrucció executada, siga o no visible

/* En aquest exemple % val 5, (el resultat no mostrat de 4+1)  */
4+1$ 
%*2;

Moltes instruccions apareixen com a instruccions tipus "comando amb arguments".
Per exemple: 
abs(num) dóna el valor absolut del nombre num

abs(-5); abs(0); abs(5);

Operador ' (apòstrofe o "single quote") 
S'usa com a prefix d'una expr: 'expr o d'una expressió entre parèntesi '(expr) 
Aplicat a certs símbols, inhibeix l'avaluació dels mateixos.
(Es veuran exemples del seu ús en altres llocs d'aquest document).

Operador ''  (apòstrofe-apòstrofe o "quote-quote")
S'usa com a prefix d'una expr: ''expr o d'una expressió entre parèntesi ''(expr) 
Aplicat a certs símbols, provoca l'avaluació dels mateixos.
(Es veuran exemples del seu ús en altres llocs d'aquest document, especialment en la secció de derivades).

Només se salven els resultats en format XML de wxMaxima (extensió .xwmx), 
però no en el format simple de wxMaxima (extensió .xwm)

## Aritmètica elemental i resultats numèrics

Els operadors aritmètics simples són "+" , "-", "" i "/" . 
Un espai en blanc no opera com a multiplicador. "x" tampoc.

2+3; 2-3; 2*3; 2/3;

expr, numer;    
Dóna el valor numèric "en coma flotant" (és a dir, "amb decimals") de l'expressió "expr" .

2/3 , numer;

Si es desitja més informació sobre com controlar el nombre de dígits que es mostren,
consulteu la secció "input/output" (entrada/eixida).

El operador "elevado a" es "^" .  
També pot usar-se "" (com en llenguatge FORTRAN)

3^2; 3**2;

3^-2;

3^(1/2);

3^(1/2), numer;

El factorial d'un nombre n es calcula amb l'operador sufix "!"

0!; 5!; 50!;

Per als nombres "en coma flotant" ("floating point") s'usa el punt decimal "." (no la coma decimal ",") 
Per a usar nombres com a potències de 10 s'usa el format "en coma flotant" amb la lletra E

1.00E3; 5.111E-6; 1.E12; 1.E24; 1.E126;

Un milió per una milionèsima.

1.E6 * 1.E-6;

A més s'admeten D ("Double precision") i B ("Big floating point")

2.D-20 ^ 2;  1.5B-30 ^2;

5D7*1E-3;5D7*1B3;

## Constants predefinides

Alguns valors predefinits s'introdueixen amb noms que comencen per "%"

%pi; %e; %i;

%pi , numer; %e ,numer ; %i, numer;

%pi és el nombre irracional pi    (relació entre la longitud de la circumferència i el seu diàmetre). 
%i és el nombre irracional i      (base dels logaritmes naturals)
%i és la unitat imaginària        (arrel quadrada de la unitat negativa)

(-2)^(1/2);

%i^2;

%pi*%e;
%, numer; 

En la línia d'abans el % té el seu significat habitual: resultat de l'última operació

%phi és la "raó àuria", que és la mitjana aritmètica entre 1 i arrel de cinc

%phi;

%phi, numer;

## Assignació de variables

### operador ":"

":"  L'operador ":" permet assignar un nom arbitrari a una expressió.

"var: expr"   assigna l'expresión "expr" a la variable "var"   

a: 10+10; /* a partir d'ara, on usem "a" estarem usant el valor "20" */
2*a;

"var" passa a ser un nom simbòlic para "expr"

a;

Per a poder tornar a usar una variable de forma simbòlica, cal "desassignar-la" 
remvalue(a);   "desassigna" la variable a
remvalue(all); "desassigna" totes les variables

remvalue(all);

L'operador prefixe "'" davant del nom d'una variable assignada, inhibeix l'avaluació
de la mateixa i la deixa en la seua "forma de nom" (noun form)

a: %pi * %phi$ 
'a;   /* retorna una "a" */
a;    /* retorna el valor de a declarat abans */
'a = a;

remvalue(all);

### declaracions

declare( xxx, prop) permet (entre moltes altres coses) declarar xxx com a
enter, racional, real, imaginària,...
declare( xxx, constant) declara xxx com a constant simbòlica

declare s'anul·la amb kill(xxx)  

assume(cond) permet assumir condicions com a igualtats o desigualtats del tipus n >= 0, L < 0 ....
forget(cond) anul·la l'efecte de assume

Es veuran exemples de la utilitat de declare i assume en les seccions de funcions, integrals, etc

declare(n,integer);

/* per a anul·lar el comandament declare anterior  */ 
kill(n);

assume(L>0);

/* per a anul·lar el comandament assume anterior */
forget(L>0);

Un exemple de l'efecte de forget i assume. 
La instrucció "is(condicion)" respon "true" si la condició és vertadera per a Maxima.

forget(T>0)$ 
is(T^(1/2)>0);

assume(T>0)$
is(T^(1/2)>0);

## Llistes

Una llista d'expressions té el format [expr1, expr2, expr3 ,...]

Usant una llista en el lloc d'un operand es pot generar una llista de resultats

3*[1,3,5];

/* podem assignar una variable a la llista var: [   ,   ,  .... ,   ] */
lis: [1,3,5]$

3+lis;
3-lis;
3*lis;
3/lis;
3^lis;

Llista de valors simbòlics 

ls: [a,b,c,d]$
3+ls;
3-ls;
3*ls;
3/ls;
3^ls;

si ls és una llista, ls[n] és l'element "n" de la llista ls.

remvalue(all)$

ls: [a,b,c,d]$ 
ls[1]*ls[4];

ls:[metre, segon, quilogram, ampere]$
unitat_velocitat: ls[1]/ls[2];
unitat_intensitat_electrica: ls[4];
unitat_forca: ls[3]*ls[1]*ls[2]^-2;  /* No s'admeten ni accents ni ces trencades */

si ls és una llista, part(ls,n) és l'element "n" de la llista ls.

ls: [a,b,c,d]$ 
part(ls,1)*part(ls,4);

Per a generar llistes:
makelist(expr_que_conté_var, var, inicial, final, increment) 
El valor d'increment és 1 per defecte i pot ometre's. Algunes versions de maxima poden no admetre aquest argument.

makelist( i+1/2, i, 0, 6);

makelist( 1/i, i, 5, 100, 5);

makelist admet aquesta altra forma:
makelist(expr_que_conté_var, var, llista_de_valors_de_var)

makelist( i/2, i, [a,b,c,d]);

/* La llista de valors de var pot ser generada per makelist */ 
/* D'aquesta forma, podem generar llistes amb valors de "i" que canvien
en salts diferents d'una constant */ 
makelist(b*i, i, makelist(2*k,k,-4,5));

## Vectors

Els vectors es representen com a llistes.
Un vector en l'espai tridimensional es representa amb una llista de tres elements.

v: [1,3,5]$
w: [2,4,6]$

/* Suma de vectors */
v+w;

/*  Resta de vectors */
v-w;

Producte ESCALAR ("dot product" en anglés): Operador "."  (el mateix operador que per a productes de matrius) 

v.w;

r: [r[x],r[y],r[z]]$
s: [s[x],s[y],s[z]]$

r.s;

Podem usar l'operador prefixe "'" per a inhibir l'expansió dels vectors

'r.'s  = r.s;

'(r.s) = r.s;

Producte VECTORIAL: No té un operador definit en la versió bàsica de MAXIMA. 
Per a treballar amb productes vectorials cal carregar un paquet addicional amb load(vect). 
Una vegada carregat el paquet "vect", l'operador per al producte vectorial (cross product) és "~"

remvalue(all);

load(vect)$

r: [r[x],r[y],r[z]]$
s: [s[x],s[y],s[z]]$

v: r~s;   
/* perque es desenvolupe el producte cal demanar express( ) */
v: express(v);

/* r~s ha de ser ortogonal als vectors r i s */
v.r;
v.s;
expand(v.r);
expand(v.s);

NOTA: El paquet "vect" defineix el producte escalar ("dot product") com a commutatiu.
Tanmateix, el producte matricial no és commutatiu. 
Conseqüentment, per a seguir calculant amb matrius, després de carregar el paquet "vect" , 
pot ser convenient executar la instrucció "kill(*all)"

Comprovem si el producte és commutatiu si vect ha sigut carregat

kill(all)$
load(vect)$

is(r.s = s.r);

Comprovem una altra vegada si el producte és commutatiu (però ara vect no està carregat)

kill(all)$

is(P.Q = Q.P);

## Matrius 

remvalue(all)$

matrix( fila1, fila2,... )  on cada fila és una llista

P: matrix(
[-3,1,-5], 
 [5,2,6], 
 [2,7,1]  );

determinant(P);

Q: matrix(
 [a,b,c], 
 [b,p,d], 
 [c,d,q]  );

determinant(Q);

inversió d'una matriu amb determinant no nul

invert(P);

determinant(invert(P));

multiplicació de matrius: operador "."  ("dot product")

M: matrix( [1,3,5], [7,11,13], [17,19,23] );

N: matrix( [1,2,3], [8,9,10], [11,22,33] );

A: M.N;

B: N.M;

A-B;

M.invert(M);

## Expresions algebraiques

### Manipulació bàsica d'expressions

expand(expr)

remvalue(all)$

(a+b)^5;

expand((a+b)^5);

expand((1+x^2+x^3)*100);

expand( (a/b +  c/d)^3 );

expand((a+b)*(a-b));

/* podem obtenir resultats de format tradicional */
(a+b)*(a-b) = expand((a+b)*(a-b));

/* Efecte de l'operador prefixe "'" */
'expand((a+b)*(a+b)) = expand((a+b)*(a+b));

factor(expr)

remvalue(all)$

factor(25468); factor(25469); factor(25470);

factor(50!);factor(100!);

factor(100!)/factor(50!);
factor(%);

expr: b^5+5*a*b^4+10*a^2*b^3+10*a^3*b^2+5*a^4*b+a^5;
factor(expr);

expr: 3*x^9+x^8+x^6+9*x^4+3*x^3+3*x;
factor(expr);

Suma de fraccions (es considera un tipus de simplificació: "simplificació racional").
ratsimp(expr)        

remvalue(all)$

expr: 1/a + 1/b;

ratsimp(expr);

ratsimp(expr+1/d);

expr: 1 + 1/(1+1/((a+1)));

ratsimp(expr);

expand(expr);

Simplificació: La simplificació ordinària es realitza sempre per defecte.

ratsimp(expr) es considera la forma general per a intentar simplificar més.

"expand" o "factor" poden ajudar a simplificar expressions.

fullratsimp(expr)     En casos especials fullratsimp pot simplifica més que ratsimp(expr)

remvalue(all)$

La simplificació ordinària s'efectua per defecte en molts casos

(4*x+2*x)/2;
(a*x+2*a*x)/a;

expr: (a^2 + a*b)/a^3;

ratsimp(expr);

expr: (a^2 + b^2)*(a^3 + b^3)/(a^3*b^3);

ratsimp(expr);

expand(expr);

/* En aquest cas fullratsimp no ajuda */
fullratsimp(expr)

/* AL contrari que en aquest... */
expr: (x^(b/2) + 1)^3*(x^(b/2) - 1)^3/((x^a - 1)*(x^b-1));

fullratsimp(expr);

ratsimp(expr);

L'operador prefixe "'" pot usar-se per a inhibir avaluacions durant el 
"parsing" o anàlisi sintàctica del input.

remvalue(all)$

/* En aquest exemple, l'analitzador de input ("parser") no substitueix a ni b pels seus valors
respectius */
a: x/2$   b: y$
'(a+b)^4 = expand((a+b)^4);

/* En aquest cas, al no estar l'operador prefixe " ' ", el "parser" o analitzador de input 
substitueix a pel seu valor i b pel seu */
(a+b)^4 = expand((a+b)^4);

### Substitucions

Hi ha diverses formes de substituir una expressió per una altra
substituix v1 per ex en expr : expr, v1=ex;  

remvalue(all)$

ex1: 6*x^3 - 2*x ;
ex1, x=(a+b);    /*  ex1 amb x substituÏda por (a+b) encara que ex1 no es modifica */
ex1;

Usant aquesta forma, totes les substitucions es fan en l'expressió inicial,
es a dir, no són consecutives

ex1: a + B*a;
ex1, a = B, B = T;  
ex1,  B=T,  a=B;

"substitute"
Pot abreujar-se per "subst". 

Té dues formes:
1) subst(expr1,expr2, expr)      reemplaça expr2 en expr col·locant en el seu lloc expr1. 
2) subst(expre2=expr1, expr )    equival a  expr, expr2=expr1;

remvalue(all)$

ex1: a + B*a;
subst(T,B,ex1);

ex1: a + B*a;
subst(a=B,ex1);
ex1, a=B;

at(expr, [v1=exp1, v2=exp2,...]) dóna el valor de expr per als valors de les variables.
Les substitucions no són recursivas (com en subst).
expr no canvia.

remvalue(all)$

ex1: a + B*a;
at(ex1, [ a = B, B = T]);
at(ex1, [ B = T , a = B]);
ex1;

## Funcions d'una variable (predefinides)

### Algunes funcions bàsiques

Les funcions matemàtiques més importants estan predefinides 
(en informàtica es pot dir
"són funcions intrínseques" de l'aplicació)

remvalue(all)$

arrel quadrada

sqrt(2);

sqrt(-1);

exponencial

exp(0); exp(1);

exp(a+b);

exp(a^b);

exp(minf); exp(inf);

logaritme

/* log(x) calcula el logaritmo natural o en base %e de x */
log(%e); log(10), numer;

log(a*b);
log(a*b), logexpand=all;

log(a/b);
log(a/b), logexpand=all;

/* el logaritme d'una potència s'expandeix per defecte */
log(a^4);

/* el logaritme decimal es  pot calcular dividint per log(10) */
log(2), numer;
log(2)/log(10), numer;

/* el logaritme decimal es  pot calcular dividint per log(10) */
log(2), numer;
log(2)/log(10), numer;

Cal recordar que els logaritmes de nombres negatius són nombres imaginaris

log(-5), numer;

El factorial d'un nombre no enter també es pot calcular perquè es
fa per mitjà 
d'una funció especial anomenada gamma. x! = gamma(x+1)

a: 2.5;
a!;
gamma(a+1);

trigonomètriques....

sin(x), cos(x), tan(x)
asin(x), acos(x), atan(x)
sec(x), csc(x), cot(x)
....  i les  corresponents funcions hiperbòliques sinh(x), cosh(x), tanh(x) ....

Els arguments de les funcions trigonomètriques s'expressen en radiants. 
Per a calcular en graus cal convertir-los en radiants
multiplicant per %pi/180

sin(%pi/6); sin(30 * %pi/180);

cos(%pi/3); cos(60 * %pi/180);

Utilització de declare(n, integer)  .... kill(n)

sin(2*%pi); cos(2*%pi);

sin(2*%pi*n);cos(2*%pi*n);

declare(n,integer);

sin(2*%pi*n);cos(2*%pi*n);

kill(n);

sin(2*%pi*n);cos(2*%pi*n);

Simplificacions trigonomètriques

cos(x)^2+sin(x)^2;  /* Aquesta suma no se simplifica al seu valor 1 fins que no se simplifica */
trigsimp(%);

sin(A+B);
trigexpand(%);

cosh(x)^2-sinh(x)^2;  /* Aquesta suma no se simplifica al seu valor 1 fins que no se simplifica */
trigsimp(%);

tan(A+B);
trigexpand(%);
trigsimp(%);

L'expressió anterior se simplifica en demanar la "forma canònica" ("canonical form")
usant trigrat (veure menú Simplificar)

trigrat(%);  

### Funció aplicada a llista d'arguments 

Es pot aplicar la funció f(x) a una llista usant map(f, llista).
Per exemple, per a aplicar la funció si a una llista d'angles expressats en graus

fpprintprec:4$  /* redueix el nombre de xifres significatives que es mostren */
lis: [-45,-30,30,45,60,90,120,270,360]*%pi/180;
sin(lis);   /* de vegades, no es produeix l'efecte desitjat */
map(sin, lis);
%,numer;

fpprintprec:0$ /* torna al nombre de xifres signifiacatives mostrades per defecte */
sin(%pi/4),numer;

En general les funcions predefinides sí apliquen el "mapatge" per defecte

exp(lis);
abs(lis);

log(abs(lis));
log(abs(lis)), numer;

map(log,abs(lis));
map(log,lis), numer;

Quan la llista mateixa és el argument, cal utilitzar "apply". Per exemple, per sumar tots el elements:

list:[1,2,3,4];
apply("+",list);

### Nombres complexos

Els nombres complexos en forma cartesiana s'escriuen segons a + %i*b

z1: a + %i*b;
z2: c + %i*d;

zsum: z1+z2;
zres: z1-z2;

Per a obtenir la forma "a + %i*b" pot usar-se rectform( expr )
També pot usar-se "collectterm(expr,%i)" per a agrupar els termes que contenen el factor %i

rectform(zsum);
collectterms(zsum,%i);

z1*z2;
expand(%);
rectform(%);

z1/z2;
expand(%);
rectform(%);

El valor absolut o mòdul del complex xxx s'obté amb abs(xxx)

abs(z1);

El complex conjugat de z s'obté amb conjugate(xxx)

zz1: conjugate(z1);
zz2: conjugate(z2);

El quadrat del mòdul del complex xxx s'obté com conjugate(xxx)**xxx

zz1*z1;
expand(%);

La forma polar del complex xxx s'obté amb polarform(xxx)

z: 3+7*%i;
polarform(z);
%, numer;
polarform(%);

La forma polar de xxx pot expressar-se com a forma de De Moivre

z: r*%e^(-%i*A);
demoivre(z);

Es pot extraure la part real i la part imaginària (sense la %i) del complex xxx amb
re

z1: a + %i*b;
z2: c + %i*d;
zp: z1*z2;

realpart(zp);

imagpart(zp);

## Funcions. L'operador ":="

És possible definir funcions usant l'operador  ":=" 

remvalue(all)$

remfunction(fun);

fun(x):= 1/(1+x);

fun(3); fun(P);

fun(fun(x));

fun(x)^5;

Un altre exemple ens serveix per tal de calcular logaritmes decimals:

log10(x):=log(x)/log(10);

log10(2), numer;

Podem usar la funció definida per a definir el pH d'una dissolució amb una 
concentració molar de protons "cH". Ara, pH és una variable (definida amb ":")

pH: -log10(cH)$
pH, cH=0.01;
%, numer;

O també definir una altra funció. I pH és ara una funció (definida amb ":=")

pH(cH):=-log10(cH);

pH(0.01)$
%,numer;

Les funcions definides poden ser de diverses variables

z(x,y):= x*y - x^2 - (y+1)^2;

z(2,5);

z(p,q);

z(1/p,1/q);
expand(%);

z(p^3,q^3);
expand(%);

/* per a calcular el logaritme de x en base b */
logxb(x,b):=log(x)/log(b);

logxb(100,2), numer;

logxb(b,b);

Poden definir-se les funcions part real i part imaginària
d'una funció que tinga forma complexa
(L'ús de ''(expr) força l'execució immediata de expr)

z: 4*x^2 + %i * 7/x;

f(x):= ''(realpart(z));   
g(x):= ''(imagpart(z));

## Equacions. L'operador "="

L'operador "=" pot entendre's com una igualtat suposada, una condició que s'estableix per l'usuari.

Establida l'equació, es pot resoldre amb solve(ecuacion, variable). Cal adonar-se que el resultat és 
una assignació temporal (amb "=") i no una vertadera assignació (que usaria ":")

solve ( x + (30-x) + 5*x = 300, x);
x;

solve(x^3+10*x^2-23*x-132 = 0 , x);

solve(x^4-7*x^3-11*x^2+87*x+90= 0 , x), numer;

solve(  (p+ a/V^2)*(V-b)= R*T, b);

La "igualtat" que imposa "=" sempre és de la forma
lhs = rhs     ("left hand side" = "right hand side")

remvalue(all)$

ec1:  4*x = 2/(x+2)$
lhs(ec1)-rhs(ec1);

solve(x^7-2 = 0 , x);

allroots(lhs = rhs) intenta trobar les solucions numèriques
realroots(*lhs = rhs) intenta trobar les solucions numèriques reals

allroots(x^10-2=0);

realroots(x^10-2=0);
%,numer;

Pot usar-se solve per a aïllar variables, variables amb subíndexs, i altres expressions 
(IMPORTANT: solve NO POT BUIDAR summes ni productes)

remvalue(all)$

ec1: p[1]*V=n[1]*R*T;
solve( ec1, p[1]);

El següent exemple no dóna cap resultat */

ec1: (a+b)/(c+d) = (A[1]+f(t))*B[1];
solve(ec1,(a+b));  
solve(ec1,f(t));

solve pot aïllar en alguns casos la potència de la summa o del producte

ec1: (a+b)^n / (p*q)^m = A/(B+1) ;
solve(ec1, (a+b)^n ); 
solve(ec1, (p*q)^m);

Per a resoldre sistemes d'equacions, cap donar-li a solve una llista d'equacions i 
una altra de variables:
solve(llista_d_equacions, llista_de_variables)

remvalue(all)$

solve([2*x+5*y=3, x-y=7], [x,y]);

solve([a^2+b=3, a-b=7], [a,b]);

solve([a^2+b=P, a-b=Q], [a,b]);

Si hi ha més variables que equacions...
algsys(llista_d_equacions, llista_de_variables)

El resultat queda en funció d'un paràmetre %r1
algsys crearà tantes variables %r com necessite

algsys([a^2+b=3], [a,b]);

Si hi ha més equacions que incògnites, poden eliminar-se algunes variables:

eliminate(llista_d_equacions, llista_de_variables_a_eliminar)

Les expressions resultants són iguals a zero (encara que no ho especifica)

remvalue(all)$

eliminate([a^2+b=P, a-b=Q], [a]);

solve(%,b);  /* Si no hi ha signe =, solve assumeix que  les expression valen 0 */1$

solve(Q^2-b*(-2*Q-1)-P+b^2=0, b);

eliminate([a+b+c=P, a-b=Q, 7*a+8*c=R], [a]);

## Estructures de programació: "if" , "for"

"if" cond_1 "then" expr_1 "else" expre_2 ; 

remvalue(all)$

n: 3;
a: tan(%pi/n);
if a <= 1 then print("menor") else print("major");

remvalue(all)$
a: [3,7,1]$
if a[1] <= a[3] 
   then c: 2*a[1]
c;

"for" variable: valor_inicial "step" increment "thru" límite "do" cos_del_bucle

remvalue(all)$

p:0$   /* valor inicial de p */
for i: 1/2 step 1/2 thru 10/2 do p: p+i ;
p;   /* valor final de p */
p, numer;

p:1;   /*  valor inicial de p */
for i: 100 step -4 thru 10 do p: p*i ;
p;   /* valor final de p */
p, numer$

A més, existeixen dues variants addicionals del comandament for : 
"while" (mentre) i "unless" (excpete)

"for" variable: valor_inicial "step" increment "while" condició  "do" cos_del_bucle

"for" variable: valor_inicial "step" increment "unless" condició  "do" cos_del_bucle

sum: 0;
for i:100 step -1 while i >= 50 do  sum: sum + 1/i; 
sum, numer;

sum: 0;
for i:100 step -1 unless i < 50 do  sum: sum + 1/i; 
sum, numer;

sum: 0;
for i:100 step -1 while i >= 50 do  sum: sum + 1/i; 
sum, numer;

Es poden fer diverses instruccions en el bloc do usant do(  ,  ,  )

(En la variable k es guarda el nombre de cicles realitzats; en sum, el resultat de la suma)

sum: 0;  k: 0;
for i:100 step -1 while i >= 90  
    do (sum: sum + 1/i ,  k: k+1 ); 
k;     
sum, numer;

Podem imprimir les etapes intermèdies... si no són moltes

sum: 0;  k: 0;
for i:100 step -1 while i >= 90  
    do (sum: sum + 1/i ,  k: k+1, print(" k ",k, " sum ",float(sum))); 
k;  
sum, numer;

prod: 1; k:0 $
for i:100 step -6.20 while i >= 75 do  (prod: prod*(i/2) , k: k+1 ); 
k;
prod;

remvalue(all)$

## Derivades 

diff(y(x))   calcula el diferencial de la funció y(x), 
on del(x) és el diferencial de la variable independent x  

Cal adonar-se que Maxima considera tots els símbols no 
declarats explícitament com constants com variables. 
(Veure més a baix "diff(cos(k*x))")

remvalue(all)$

diff(sin(x));
diff(log(x));
diff(cos(x))  /  del(x);
diff(cos(k*x));

diff(log(z^2));
diff(1/z);

diff(y(x),x)   calcula la derivada de y(x) respecte de la variable x

remvalue(all)$

diff(sin((1/k)*x),x);

diff(sin((1/k)*x),k);

diff(y(x),x,n)  calcula la n-èsima derivada de y(x) respecte de x

diff(sin(k*x),x,3);
diff(sin(k*x),x,5);

diff(expr)  calcula el diferencial TOTAL de expr 
(una altra vegada tots els símbols es consideren variables).

diff(a*x+b*y^2);

z(x,y):= a*x - 3*x*y + b*y^2;
diff(z(x,y),x);   /* derivada parcial */1$

diff(z(x,y));

L'ús del operador "'" (apòstrofe o "single quote") :  
Aplicat a certs símbols, inhibeix l'avaluació dels mateixos.
  
Pot usar-se per a obtenir expressions d'eixida més clares,tenint en compte 
que de l'ús del signe "=" és responsable l'usuari, no Maxima. Per tant, si 
es cometen errors poden aparèixer expressions matemàtiques inconsistents

y(x):= x^x$
'diff(y(x),x) = diff(y(x),x);

y(x):= sin(x)*cos(x)$
'diff(y(x),x) = diff(y(x),x);

L'ús del operador "''" (apòstrofe-strofe o "quote-quote") :  
Aplicat a certs símbols, provoca l'avaluació immediata dels mateixos 
pel "parser" o analitzador sintàctic.
   
Cal usar-ho per a definir funcions en les quals intervé l'operador diff

y(x):= x^2-x;
f1(x):= diff(y(x),x,1);
f2(x):= diff(y(x),x,2);
y1(x):= ''(diff(y(x),x,1));
y2(x):= ''(diff(y(x),x,2));
print("f1(5) = ",f1(5));
print("y1(5) = ",y1(5))$
print("f2(5) = ",f2(5));
print("y2(5) = ",y2(5))$

És a dir, sense els dos apòstrofes Màxima entén que volem derivar respecte a una constant numèrica
i dóna error. Açò mateix no succeeix en el següent exemple

y(x):= x^log(x);
f1(x):= diff(y(x),x,1);
f2(x):= diff(y(x),x,2);
y1(x):= ''(diff(y(x),x,1));
y2(x):= ''(diff(y(x),x,2));
print("f1(a) = ",f1(a))$
print("y1(a) = ",y1(a))$
print("f2(a) = ",f2(a))$
print("y2(a) = ",y2(a))$

Però sí en aquest
((Adoneu-vos que el penúltim resultat és incorrecte)

fun:x^3+3*x^2-x+3;
f(x):=fun;
y(x):=''fun;
print("f(x) = ",f(x))$
print("y(x) = ",y(x))$
print("f(a) = ",f(a))$
print("y(a) = ",y(a))$

Derivades parcials
diff(func, var1, n1, var2, n2 ....)

z(x,y):= a*x^3*y^2 - b*y^3*x^2;
'diff(z(x,y),x,1,y,1) = diff(z(x,y),x,1,y,1);

/* Importa l'ordre? */
'diff(z(x,y),x,1,y,1) = diff(z(x,y),x,1,y,1);
'diff(z(x,y),y,1,x,1) = diff(z(x,y),y,1,x,1);

'diff(z(x,y),x,2,y,2) = diff(z(x,y),x,2,y,2);

Desenvolupament en sèrie de potències de Taylor fins a ordre n entorn del punt x=a
taylor(expr, x, a, n);   expr pot ser una expressió que conté la x o pot ser una funció de x

remvalue(all)$

fun(x):= 1/x;
taylor(fun(x),x,1,6);

expand(%);

El desenvolupament de Taylor-McLaurin correspon al cas en què a = 0
taylor(expr, x, 0, n);

expr: sin(k*x)*cos(x)$
taylor(expr,x,0,6);
taylor(expr,k,0,6);

## Integrals 

integrate(f(x),x)       Integral indefinida.
integrate(f(x),x,a,b)   Integral definida entre x=a y x=b

(Maxima no inclou la constant d'integració indefinida)

remvalue(all)$

integrate((-1/x),x);

integrate(sin(w*x),x);

integrate((1/sqrt(1-x^2)),x);

integrate((1/sqrt(1+x^2)),x);

Pot usar-se l'operador "'" amb integrate per a inhibir l'avaluació

'integrate((1/sqrt(1-x^2)),x) = integrate((1/sqrt(1-x^2)),x);

'integrate((1/sqrt(1+x^2)),x) = integrate((1/sqrt(1+x^2)),x);

remvalue(all)$

'integrate((k*x^2),x,a,b) = integrate((k*x^2),x,a,b);

'integrate((1/(1-x^2)),x,a,b) = integrate(1/(1-x^2),x,a,b);

'integrate((1/(1-x^2)),x,5,10) = integrate(1/(1-x^2),x,5,10);
%,numer;

remvalue(all)$

integrate(log(k*x^2),x, 1, x);

Es poden establir condicions addicionals:
assume( cond  )        estableix condicions del tipus k > 0.
forget( cond  )        anul·la les condicions establides amb assume
declare( xxx, prop)    estableix condicions del tipus n és un nombre enter
kill(xxx)              anul·la les condicions establides amb declare

remvalue(all)$

/* ejemplo usando la variable x como limite de integracion */
assume (x > 1);
assume (k > 1);
integrate(log(k*x^2),x, 1, x);

remvalue(all)$

Si no s'ha declarat abans, potser que Maxima demane més informació

'integrate((x^2)*(sin(k*x))^2, x, 0, L)= integrate(x*(sin(k*x))^2, x, 0, L);

assume(L > 0);
'integrate(x*(sin(k*x))^2, x, 0, L) = integrate(x*(sin(k*x))^2, x, 0, L);

forget(L>0,n>0);

assume(L>0, n>0);
declare(n,integer);
integrate((sin(k*x))^2, x, 0, L);
subst((n*%pi)/L, k,%);

forget(L>0,n>0); 
kill(n);

assume(L>0, n>0);
integrate((sin(k*x))^2, x, 0, L);
subst((n*%pi)/L, k,%);

## Equacions diferencials

Per a resoldre equacions diferencials ordinàries (ODE):
ode2(ec1,y,x);
on ec1 és una equació on apareix la derivada en la forma 'diff(y,x,1). 
El "'" abans de diff és obligatori.


Considerarem ací sols equacions d'una sola variable. 


ode2 resol equacions diferencials ordinàries de primer i segon ordre. 
(Amb primeres i/o segones derivades com a màxim).


La solució general d'una equació diferencial d'ordre "n" conté "n" 
constants indeterminades. 
Maxima les introdueix com a %c, ... per a primer ordre 
i %k1, %k2... per a segon ordre.

y' = -a*y

remvalue(all)$

ed1: 'diff(y,x,1) + a* y = 0;
ode2(ed1, y, x);

Es poden establir condicions "inicials" per a una equació diferencial de primer ordre amb ic1
ic1 (soluc, x = x0, y = y0)  on (x0,y0)  és un punt conegut de la corba 
(valors "iniciales", encara que no és necessari que x0 siga zero )

ed1: 'diff(y,x,1) - a* y = 0;
ode2(ed1, y, x);
ic1(%, x=0, y= %pi);

En aquest exemple, la variable independent és t; la variable depenent, p

ed1: 'diff(p,t,1) = -k * p;
ode2(ed1, p, t);
ic1(%, t=0, y= p[0]);

Amb el símbol "\", es pot usar -entre altres coses- la notació tradicional 
en Química per a les concentracions molars. En el següent exemple, la  
concentració és la variable que depèn de la independent t (el temps)

ed1: 'diff(\[A\],t,1) = -k * \[A\];
ode2(ed1, \[A\], t);
ic1(%, t=0, \[A\] = \[A\][0]);

Exemple d'equació diferencial de segon ordre

remvalue(all)$

assume (k>0,L>0);
declare(k,constant,L,constant);
ed2: 'diff(y,x,2) = - k * y ;
sol: ode2(ed2, y, x);

sol;

bc2 (soluc, x=x1, y=y1, x=x2, y=y2) estableix condiciones de contorn ("boundary conditions") 
per a la solució proporcionada per ode2 d'una equació diferencial de segon ordre

bc2(sol, x=0,y=Y[0], x=L, y=Y[0]);

bc2(sol, x=0,y=0, x=L, y=Y[0]);

bc2(sol, x=0,y=0, x=L, y=0);

Per tal que Maxima trobe la "solució vertadera" 
(en Mecànica Quàntica), cal ajudar-lo

declare(n,integer);
assume(n>0);
sol1:sol,k=n^2*%pi^2/L^2;
bc2(sol1, x=0,y=0, x=L, y=0);

## Gráfiques: "plot".

Existeix un paquet "draw" que puga carregar-se amb load(draw) per a augmentar 
les capacitats gràfiques

El format general de plot té aquesta forma:

wxplot2d([ ],[ ],[ ],..... )
Totes les opcions tenen el format de llistes. 
Les dues primeres són necessàries: Llista d'expressions a representar i la variable independent [x, xmin, xmax] 
Altres opcions (no obligatòries):

[y, ymin, ymax] : El rang de l'eix vertical.
[xlabel, " etiqueta de l'eix horitzontal"]
[ylabel, "etiqueta de l'eix vertical"]
[logx] i [logy] : eixos logaritmicos, no necessiten paràmetres.
[legend, ["label1","label2",...] : etiquetes en la llegenda 
                                  (per defecte, usarà les expressions o noms donats en wxplot2d(...))

[grid,numx,numy] : reticle de càlcul (per defecte: [grid,30,30])
[style, [estil1, param1],[estil2,param2]] . Tants estils com a funcions o dades... 
    estils: 

        lines (segments lineals) [lines,grossor,color] (ex [lines,1,3])
       
        points [points, ràdio, color, objecte] (ex [points,1,2,5])
       
        linespoints (segments i punts) [linespoints, ample, ràdio, color], 
        dots (xicotets punts aïllats)
        impulses (acceptat per Gnuplot).
        Codis de color (per defecte, poden canviar, però, amb el terminal definit):
             
1, blau; 2, roig; 3, magenta; 4, taronja; 5, marró; 6, verda llima; 7, aguamarina.
        Codi d'objectes:
              1, cercles plens; 2, circumferències; 3, +; 4, x; 5 *, ; 6, quadrats plens; 
              7, quadrats buits; 8, triangles plens; 9, triangles buits;
              10, triangles plens invertits; 
              11, triangles buits invertits;
              12, rombes plens; 13, rombes buits.

Representació de punts dicrets

remvalue(all)$

pts1: [[1,1.3],[3,3.5],[5,6.7],[7,8.1],[9,10.7],[13,14.1],[15,16.9]];

pts2:[[3,2.5],[4, 2.8],[6.5,3.12],[10, 3.5],[14, 3.75]];

wxplot2d([discrete, pts1],[style, points]);

wxplot2d([[discrete, pts1],[discrete,pts2]],[style, points],[x,-5,25]);

Representació de funcions

remfunction(fun,fu1,fu2)$

fun(x):= 4*sin(2.5*x)+5*sin(4.3*x+%pi/6);

Codis de color (per defecte, però poden canviar amb el terminal definit):
        1, blau; 2, roig; 3, magenta; 4, taronja; 5, marró; 6, verda llima; 7, aguamarina.

/* opcion [style,[lines, grosor, color] */

wxplot2d([fun(x)],
 [x,-5,5],
[y,-20,20],
[style,[lines,2,3]])$

plot2d([fun(x)],
 [x,-5,5],
[y,-20,20],
[style,[lines,2,5]],[plot_format, xmaxima]);

wxplot2d([fun(x)],
 [x,-5,5],
[y,-20,20],
[style,[linespoints,0.1,0.2,4,13]])$

fu1(x):= 4*sin(2.5*x)+5*sin(4.3*x+%pi/6)$
fu2(x):= 4*sin(2.5*x)*sin(4.3*x+%pi/6)$

wxplot2d([fu1(x),fu2(x)],
 [x,-5,5],
[y,-15,15],
[style,[lines,2,2],[lines,3,1]])$

/* usant 'fu1(x) s'evita que s'expandisca tota la expressio en la llegenda  */
/*   */
wxplot2d(['fu1(x),'fu2(x)],
 [x,-5,5],
[y,-15,15],
[style,[lines,2,2],[lines,3,1]],
[xlabel,"t / segonss"],
[ylabel, "Intensitat / miliamperis "])$

wxplot2d(['fu1(x),'fu2(x)],
 [x,-5,5],
[y,-15,15],
[style,[lines,2,2],[lines,3,1]],
[xlabel,"t / segonss"],
[ylabel, "Intensitat / miliamperis "],
[legend, "suma d'ones desfasades", "producte d'ones desfasades"])$

Representació en polars

wxplot2d([cos(9*ph+2.5)], [ph,0,2*%pi],
 [gnuplot_preamble, "set polar; set zeroaxis;"])$

S'hauria de poder fer una representació que canvia en variar un paràmetre amd "with_slider"
Una vegada representat, seleccionant el gràfic amb un "clic" s'activa el comandament de reproducció
Els dos primers arguments són el paràmetre i la seua llista de valors; la resta, els de plot2d

(No funciona en la versió 15.04.0 per a MacOSX)

remvalue(all)$

with_slider(   n, makelist(i, i, 1, 30),
   [cos(9*ph + n)], [ph,0,2*%pi],
    [gnuplot_preamble, "set polar; set zeroaxis; set size ratio 1"]    )$

Representació en 3D

remvalue(all)$

wxplot3d(x^3 - x*y + y^3, [x,-4,4], [y,-3,3], [z,-60,60],
 [grid,40,40],
[xlabel," llargaria "],[ylabel,"amplaria"],
[zlabel,"F"])$

## input/output

### Xifres significatives

ES  pot controlar el nombre de xifres SIGNIFICATIVES del output amb la variable fpprintprec.
El valor per defecte de fpprintprec és fpprintprec:0 , que produeix un output amb 16 decimals

Cal adonar-se que no controla directament el nombre de decimals, sinó el de xifres significatives

remvalue(all)$

sqrt(2)*100, numer;

fpprintprec:4$  
sqrt(2), numer;
sqrt(2)*100, numer;

fpprintprec:0$  /* restableix el valor per defecte */
sqrt(2)*100, numer;

La variable fpprec controla la precisió interna amb que es realitzen els càlculs.
bfloat(expr) dóna l'expressió expr en "big double precision".

fpprec: 50;
bfloat(%pi);
fpprec: 70;
bfloat(%pi);

La manera de "display" gràfic (el que es té per defecte) trunca les sèries de 
dígits
si es desitgen valors de fpprec molt grans.

fpprec: 100$   /* el valor per defecte es 16 */
100!;
bfloat(%pi);
fpprec: 16$

Si es desitja veure tots els dígits, s'usa "set_display('ascii)$" 
          (menú Maxima > Cambiar pantalla 2D > ascii) 
Es torna la finestra wx a la manera gràfica estàndard amb "set_diplay('*xml)$" 
           (menu Maxima > Canviar pantalla 2D > xml)

set_display('ascii)$
fpprec: 100;
100!;
bfloat(%pi);
set_display('xml)$
fpprec: 16$

set_display('ascii)$

fpprec: 100;
bfloat(%pi);

### Fitxers externs de dades

Es poden generar i llegir dades en format CSV ("comma separated values") de fitxers externs

remvalue(all)$

pts1: [[1,1.3],[3,3.5],[5,6.7],[7,8.1],[9,10.7],[13,14.1],[15,16.9]];

pts2:[[3,2.5],[4, 2.8],[6.5,3.12],[10, 3.5],[14, 3.75]];

datosX: makelist(pts1[i][1],i,1,length(pts1));

datosY: makelist(pts1[i][2],i,1,length(pts1));

file_search("nom_de_fitxer"): Retorna "false" si no existeix. "true" si existeix
"nom_de_fitxer" és una adreça completa ("un path"). 
     En linux o Mac serà del tipus "/home/usuari/documents/.../mifichero.cvs" 
     ATENCIÓ:
En PC també s'usen "/", en comptes de "\" : "C:/docsMaxima/*docsDatos/*mifichero.cvs"
              Molt freqüentment, els fitxers amb extensió csv, s'obrin per defecte amb Excel. Si es
              vol obrir-los com text, cal fer-ho des de dins d'un editor de text (TextEdit, Bloc de notas,...)

file_search("/Users/alumno/Documents/datosMX/puntos1.csv");

write_data(Dades, nom_de_fitxer, separador)
    Dades pot ser una llista , una matriu, un "array" declarat....
    nom_de_fitxer : "un path" complet. 
(És necessari que existeixen tots els directoris del "path")
    Separadors que reconeix write_data: comma (,), pipe (|), semicolon (;), space, tab

write_data(pts1,"/Users/alumno/Documents/AIQ/punts1.csv",comma);

Si existeix la carpeta "/Users/..../AIQ", s'ha creat dins d'ella un fitxer text punts1.csv amb contingut:

1,1.3
3,3.5
5,6.7
7,8.1
9,10.7
13,14.1
15,16.9

El fitxer també podria haver sigut escrit o preparat amb una altra aplicació.
Per a llegir el contingut del fitxer.

M1: read_matrix("/Users/alumno/Documents/AIQ/punts1.csv")$

L1: read_list("/Users/alumno/Documents/AIQ/punts1.csv")$

LN1: read_nested_list("/Users/alumno/Documents/AIQ/punts1.csv")$

M1;

L1;

LN1;

## APÈNDIX. Lletres greques i altres símbols

L'ordre correspon al de l'alfabet grec. 

[%alpha,%beta,%gamma,%delta,%epsilon];
[%zeta,%eta,%theta];
[%iota,%kappa,%lambda,%mu,%nu];
[%xi,%omicron,%pi,%rho,%sigma,%tau];
[%upsilon,%phi,%chi,%psi,%omega];

[%Alpha,%Beta,%Gamma,%Delta,%Epsilon];
[%Zeta,%Eta,%Theta];
[%Iota,%Kappa,%Lambda,%Mu,%Nu];
[%Xi,%Omicron,%Pi,%Rho,%Sigma,%Tau];
[%Upsilon,%Phi,%Chi,%Psi,%Omega];

Pot usar-se "\" com a caràcter escape. lambda minúscula es comporta de manera 
diferent perquè 
és un nom protegit.

[\alpha,\beta,\gamma,\delta,\epsilon];
[\zeta,\eta,\theta];
[\iota,\kappa,\lambda,\mu,\nu];
[\xi,\omicron,\pi,\rho,\sigma,\tau];
[\upsilon,\phi,\chi,\psi,\omega];

[\Alpha,\Beta,\Gamma,\Delta,\Epsilon];
[\Zeta,\Eta,\Theta];
[\Iota,\Kappa,\Lambda,\Mu,\Nu];
[\Xi,\Omicron,\Pi,\Rho,\Sigma,\Tau];
[\Upsilon,\Phi,\Chi,\Psi,\Omega];

L'ús del símbol de "escape" \ permet usar altres notacions tradicionals.

log10(x):=log(x)/log(10)$
pH(x):= log10(x)$

fpprintprec: 4$

\[H\+\]: Kw/(\[OH\-\])$
pH(\[H\+\]);
%, logexpand=super;
expand(%), numer;

remvalue(all)$

eq_quim: K = (\[C\]^c * \[D\]^d)/(\[A\]^a * \[B\]^b);
solve(eq_quim, \[B\]);
solve(eq_quim, a);