MATLAB

Linguaggio per il calcolo numerico

MATLAB
(MATrix LABoratory) è un linguaggio di programmazione interpretato creato dalla MathWorks (1984Jack Little e Cleve Moler). MATLAB consente manipolazioni di matrici, visualizzazione di funzioni e dati. 

Per il calcolo simbolico utilizza Maple.

Esistono versioni più o meno compatibili fra cui OCTAVE.

OCTAVE

Octave nasce verso il 1988, ad opera di John W. Eaton, come strumento, alternativo al Fortran, per i calcoli del dimensionamento di reattori chimici, basati su un testo universitario di James B. Rawlings e John G. Ekerdt. Il nome ricorda un professore famoso per la sua abiltà nel esegure i calcoli.

Lo sviluppo verso un linguaggio ebbe inizio nella primavera del 1992, con un rilascio beta a gennaio 1993 e la versione 1.0 il 17 febbraio 1994, è largamente compatibile con MATLAB. L’attuale versione, la 2.1, è disponibile in LINUX (Debian e SuSE) e Windows.

I tipi di dato sono naturalmente numeri, compresi i complessi e i quaternioni (numeri con una componente reale e tre complesse) stringhe e booleani. I dati numericisi possono organizzare in vettori, matrici; liste, celle e strutture (record) sono strutture anche eterogenee.

# Great Common Divisor

function ret = GCD(m,n)

  if n > m     ret = GCD(m,n-m);

  elseif m > n ret = GCD(m-n,n);

  else         ret = m;

  endif 

endfunction

Elegante la definizione di funzioni:

function ret-var = name (arg-list)

  body

endfunction

Molte funzioni di Octave sono polimorfiche, ma non è possibile crearne di proprie. Fra le caratteristiche salienti delle funzioni c’è la possibilità di restituire più valori, il supporto della ricorsività, l’accettazione di un numero variabile di argomenti e la capacità di operare sia su scalari che matrici. Non è possibile utilizzare una funzione come parametro di una funzione, tranne che per utilizzi particolari, in cui si indica una funzione, sia del linguaggio che propria, come la funzione map o quad (integrazione):

function y = fnz (x)

  y = x^2;

endfunction

octave:3> quad("fnz",0,5)

ans = 41.667

try istruzioni

catch pulizia

end_try_catch

unwind_protect istruzioni

unwind_protect_cleanup pulizia

end_unwind_protect

 Le strutture di controllo sono complete, compresi il trattamento degli errori: nella seconda forma le istruzioni del blocco unwind_protect_cleanup sono sempre eseguite. Una variante del for permette di accedere a tutti componenti di una struttura.

zeros()

matrice con zero

ones()

matrice con uno

eye()

matrice identità

rand()

numeri casuali

 La dotazione di funzioni per operare su matrici è ampia (vedere a lato un piccolo repertorio), con un efficace generatore di vettori numerici: inizio:fine e inizio:incremento:fine. In genere il richiamo di funzione con un solo valore n restituisce una  matrice quadrata di rango n, per avere un singolo valore occorre indicare funzione(1,1). La sintassi per costruire matrici è pittosto flessibile, i gli elementi di una stessa colonna sono separato da spazi o virgole, le righe da ; o da un ritorno a capo.  L’operatore unario postscritto ' (apostrofo) inverte le matrici.

fi = 0:0.01:10;

ro = 0.5 * fi;

[x,y]=pol2cart(fi,ro);

grid("on");

title("Spiral ro = 0.5fi");

plot(x,y);

Octave possiede funzioni e packages per l’analisi lineare, l’integrazione, la risoluzione di qualche tipo di equazioni differenziali, la statistica, la simulazione, la gestione del suono e naturalmente un insieme di funzioni, che utilizzano il package gnuplot,  per ottenere facilmente grafici, purtroppo salvabili in formato proprietario. Qui a lato le istruzioni per disegnare una spirale trasformando le coordinate polari in cartesiani.

Esistono istruzioni per l’interattività, il debug (input, menu, keyboard, ...), l’introspezione ed il salvataggio e recupero di risultati (save, load), L’input /output è simile al C.

In Octave le funzioni sono definite ovunque, ciò significa che è possibile estrarre radci quadrate di numeri negativi o dividere per 0.

Nell’esempio che segue sono determinati empiricamente i tempi di un semaforo a due vie, per minimizzare le attese. L’algoritmo è vagamente  genetico nel senso che dato un insieme di individui i cui "geni" sono i tempi del ciclo del semaforo, è eseguita una simulazione di arrivi con calcolo del tempo totale di attesa e ad ogni generazione sono sostituiti gli elementi che hanno avuto i tempi di attesa maggiori.

...

Generation  37   Mean Wait time 3544.652

Generation  38   Mean Wait time 3409.597

Generation  39   Mean Wait time 3517.910

Generation  40   Mean Wait time 3560.152

Generation  41   Mean Wait time 3457.081

Generation  42   Mean Wait time 3488.969

Generation  43   Mean Wait time 3438.306

Generation  44   Mean Wait time 3484.457

Generation  45   Mean Wait time 3519.356

Generation  46   Mean Wait time 3504.721

Generation  47   Mean Wait time 3576.267

Generation  48   Mean Wait time 3487.271

Generation  49   Mean Wait time 3562.220

Generation  50   Mean Wait time 3483.727

Proposed Time (seconds) for S0:  52, for S1: 38




#GNU Octave, version 2.1.73 (i686-pc-cygwin).

#Copyright (C) 2006 John W. Eaton.

function Ret = IIF(Bool,R1,R2)     # IFF function (in C is ?)

  Ret = R2;

  if (Bool)Ret = R1; endif

endfunction

function Ord = Order(arr,col) # for sorting rows

   [s, i] = sort (arr (:, col));

   Ord =   arr (i, :);

endfunction

# functon Sema return semaphor value, time of changing

# input are the Clock, the actual semaphore, the time of the last change

#              ande the time for the two direction

function [AS,LC] = Sema(Clk,ActDir,LastChange,TimeS0,TimeS1)

  AS = ActDir;

  LC = LastChange;

  Sx = IIF(ActDir == 0,TimeS0,TimeS1);

  if (Clk > LastChange+Sx)

    AS = mod(ActDir +1,2);

    LC = LastChange + Sx;

  endif

endfunction

SemTime=90;                              # total semaphor time

Amt = 2;                                 # Arrival Mean Time

People = 100;                            # Population

History = zeros(50,1);             # Store for generation mean

Population = zeros(People,3); # Name, time of S0, Wait total

Population(:,1) = (1:1:People)';         # names

Population(:,2) = SemTime*rand(People,1);  # time of S0 semaphor (S1 = SemTime - S0)

for ijk =1:50                            # 50 generations

  Population(:,3) = zeros(People,1);

  for ij = 1:People                      # try all population

    Clock=0;

    AD=0;                                # actual free direction

    LC=0;                                # time of last change

    S0=Population(ij,2);           # time for S0 semaphore

    S1=SemTime-S0;      # time for S1 semaphore

    Stat = zeros(2,3);  # statistical arrival matrix (set to zeroes)

    # 1 = total arrival, 2 = numbers of waiting, 3 = totaL wait time  

    while (Clock < 600) # simulation of ten minutes traffic

        Clock = Clock+rand(1)*Amt*2;

        Direction = IIF(rand(1) > 0.4,0,1);    # S0 60% traffic

        Stat(Direction+1,1) = Stat(Direction+1,1) + 1;

        Signal = sprintf("Clock: %-8.5g  Direction: %1d  ",Clock,Direction);

        [AD,LC] = Sema(Clock,AD,LC,S0,S1);

        if (Direction != AD)

          Stat(Direction+1,3) = Stat(Direction+1,3)+LC+IIF(AD == 0,S0,S1) - Clock;

        endif

    endwhile

    Population(ij,3) = Stat(1,3) + Stat(2,3);

  endfor

  Population = Order(Population,3);

  History(ijk) = mean(Population)(3);

  printf("Generation %3d   Mean Wait time %7.3f\n",ijk,History(ijk));

  # replace the 10 worser mean

  Population(91:100,2) = SemTime*rand(10,1); # time of S0 semaphor (S1 = SemTime-S0)

endfor

plot(History);

S0 = ceil(mean(Population)(2));

S1 = SemTime - S0;

printf("Proposed Time (seconds) for S0: %3d, for S1: %3d\n",S0,S1);