Quel est votre truc de programmation MATLAB / Octave préféré?

Je pense que tout le monde conviendra que le langage MATLAB n’est pas joli ou particulièrement cohérent. Mais tant pis! Nous devons toujours l’utiliser pour faire avancer les choses.

Quelles sont vos astuces préférées pour faciliter les choses? Ayons une par réponse pour que les gens puissent les voter s’ils sont d’accord. Essayez également d’illustrer votre réponse par un exemple.

Utilisation du profileur intégré pour voir où se trouvent les parties essentielles de mon code:

profile on % some lines of code profile off profile viewer 

ou simplement utiliser le tic et le toc intégrés pour obtenir des timings rapides:

 tic; % some lines of code toc; 

Extraction directe des éléments d’une masortingce satisfaisant une condition particulière, à l’aide de tableaux logiques:

 x = rand(1,50) .* 100; xpart = x( x > 20 & x < 35); 

Maintenant, xpart ne contient que les éléments de x qui se trouvent dans la plage spécifiée.

Fournissez un access rapide à la documentation des autres fonctions en ajoutant une ligne “VOIR AUSSI” aux commentaires d’aide. Tout d’abord, vous devez inclure le nom de la fonction dans tous les calques en tant que première ligne de commentaire. Faites vos en-têtes de commentaire habituels, puis mettez SEE ALSO avec une liste séparée par des virgules d’autres fonctions connexes.

 function y = transmog(x) %TRANSMOG Transmogrifies a masortingx X using reverse orthogonal eigenvectors % % Usage: % y = transmog(x) % % SEE ALSO % UNTRANSMOG, TRANSMOG2 

Lorsque vous tapez “help transmog” sur la ligne de commande, vous verrez tous les commentaires dans cet en-tête de commentaire, avec des hyperliens vers les en-têtes de commentaire pour les autres fonctions répertoriées.

Transformez une masortingce en un vecteur en utilisant un seul deux-points.

 x = rand(4,4); x(:) 

Boucles de vectorisation . Il y a de nombreuses façons de procéder, et il est amusant de rechercher des boucles dans votre code et de voir comment elles peuvent être vectorisées. La performance est incroyablement plus rapide avec les opérations vectorielles!

Fonctions anonymes, pour quelques raisons:

  1. pour effectuer une fonction rapide pour des utilisations uniques, comme 3x ^ 2 + 2x + 7. (voir la liste ci-dessous) Ceci est utile pour des fonctions comme quad et fminbnd qui prennent des fonctions comme arguments. C’est également pratique dans les scripts (fichiers .m qui ne commencent pas par un en-tête de fonction), car contrairement aux fonctions vraies, vous ne pouvez pas inclure de sous-fonctions.
  2. pour les fermetures – bien que les fonctions anonymes soient un peu limitantes car il ne semble pas y avoir de moyen d’affecter des états à une mutation.

.

 % quick functions f = @(x) 3*x.^2 + 2*x + 7; t = (0:0.001:1); plot(t,f(t),t,f(2*t),t,f(3*t)); % closures (linfunc below is a function that returns a function, % and the outer functions arguments are held for the lifetime % of the returned function. linfunc = @(m,b) @(x) m*x+b; C2F = linfunc(9/5, 32); F2C = linfunc(5/9, -32*5/9); 

Bsxfun , arrayfun , cellfun et structfun de Matlab sont très intéressants et enregistrent souvent une boucle.

 M = rand(1000, 1000); v = rand(1000, 1); c = bsxfun(@plus, M, v); 

Ce code, par exemple, ajoute le vecteur colonne-v à chaque colonne de la masortingce M.

Cependant, dans les parties critiques de votre application, vous devriez comparer ces fonctions à celles de sortingvial for-loop, car les boucles sont souvent plus rapides.

Mode LaTeX pour les formules dans les graphiques : Dans l’une des versions récentes (R2006?), Vous ajoutez les arguments supplémentaires ,'Interpreter','latex' à la fin d’un appel de fonction et il utilisera le rendu LaTeX. Voici un exemple:

 t=(0:0.001:1); plot(t,sin(2*pi*[t ; t+0.25])); xlabel('t'); ylabel('$\hat{y}_k=sin 2\pi (t+{k \over 4})$','Interpreter','latex'); legend({'$\hat{y}_0$','$\hat{y}_1$'},'Interpreter','latex'); 

Pas sûr quand ils l’ont ajouté, mais cela fonctionne avec R2006b dans les fonctions text (), title (), xlabel (), ylabel (), zlabel (), et même legend (). Assurez-vous simplement que la syntaxe que vous utilisez n’est pas ambiguë (donc, avec legend (), vous devez spécifier les chaînes comme un tableau de cellules).

Utiliser xlim et ylim pour dessiner des lignes verticales et horizontales. Exemples:

  1. Tracez une ligne horizontale à y = 10:

    line(xlim, [10 10])

  2. Tracez une ligne verticale à x = 5:

    line([5 5], ylim)

Voici un exemple rapide:

Je trouve la syntaxe de liste séparée par des virgules très utile pour créer des appels de fonctions:

 % Build a list of args, like so: args = {'a', 1, 'b', 2}; % Then expand this into arguments: output = func(args{:}) 

Voici un tas de fonctions non évidentes qui sont utiles de temps en temps:

  • mfilename (renvoie le nom du script MATLAB en cours d’exécution)
  • dbstack (vous donne access aux noms et numéros de ligne de la stack de fonctions matlab)
  • keyboard (arrête l’exécution et cède le contrôle à l’invite de débogage; c’est pourquoi il y a un K dans l’invite de débogage K>>
  • dbstop error (vous place automatiquement en mode débogage arrêté à la ligne qui déclenche une erreur)

J’aime bien utiliser les poignées de fonction pour de nombreuses raisons. D’une part, ils sont la chose la plus proche que j’ai trouvée dans MATLAB pour les pointeurs, de sorte que vous pouvez créer un comportement de type référence pour les objects. Il y a aussi quelques petites choses que vous pouvez faire avec eux. Par exemple, remplacer une instruction switch:

 switch number, case 1, outargs = fcn1(inargs); case 2, outargs = fcn2(inargs); ... end % %can be turned into % fcnArray = {@fcn1, @fcn2, ...}; outargs = fcnArray{number}(inargs); 

Je pense juste que de petites choses comme ça sont cool.

Utiliser nargin pour définir les valeurs par défaut des arguments facultatifs et utiliser nargout pour définir des arguments de sortie facultatifs. Exemple rapide

 function hLine=myplot(x,y,plotColor,markerType) % set defaults for optional paramters if nargin<4, markerType='none'; end if nargin<3, plotColor='k'; end hL = plot(x,y,'linetype','-', ... 'color',plotColor, ... 'marker',markerType, ... 'markerFaceColor',plotColor,'markerEdgeColor',plotColor); % return handle of plot object if required if nargout>0, hLine = hL; end 

Invocation de code Java de Matlab

Cellfun et arrayfun pour automatiser les boucles.

Oh, et inverser un tableau

 v = 1:10; v_reverse = v(length(v):-1:1); 

arguments conditionnels dans la partie gauche d’une tâche:

 t = (0:0.005:10)'; x = sin(2*pi*t); x(x>0.5 & t<5) = 0.5; % This limits all values of x to a maximum of 0.5, where t<5 plot(t,x); 

Connaissez les propriétés de votre axe ! Il y a toutes sortes de choses que vous pouvez définir pour modifier les propriétés de tracé par défaut pour faire ce que vous voulez:

 set(gca,'fontsize',8,'linestyleorder','-','linewidth',0.3,'xtick',1:2:9); 

(par exemple, définit la taille de la police sur 8pt, les styles de ligne de toutes les nouvelles lignes sont tous solides et leur largeur de 0,3pt, et les points xtick sur [1 3 5 7 9])

Les propriétés des lignes et des figures sont également utiles, mais je me retrouve à utiliser le plus souvent les propriétés des axes.

Être ssortingct avec la spécification des dimensions lors de l’utilisation de fonctions d’agrégation telles que min, max, mean, diff, sum, any, all, …

Par exemple la ligne:

 reldiff = diff(a) ./ a(1:end-1) 

pourrait bien fonctionner pour calculer les différences relatives d’éléments dans un vecteur, mais si le vecteur dégénère en un seul élément, le calcul échoue:

 >> a=rand(1,7); >> diff(a) ./ a(1:end-1) ans = -0.5822 -0.9935 224.2015 0.2708 -0.3328 0.0458 >> a=1; >> diff(a) ./ a(1:end-1) ??? Error using ==> rdivide Masortingx dimensions must agree. 

Si vous spécifiez les dimensions correctes pour vos fonctions, cette ligne renvoie une masortingce 1 par 0 vide, ce qui est correct:

 >> diff(a, [], 2) ./ a(1, 1:end-1) ans = Empty masortingx: 1-by-0 >> 

Il en va de même pour une fonction min qui calcule généralement les minimums sur les colonnes d’une masortingce, jusqu’à ce que la masortingce ne soit constituée que d’une ligne. – Ensuite, il retournera le minimum sur la ligne, sauf indication contraire du paramètre de dimension, et cassera probablement votre application.

Je peux presque vous garantir que par conséquent, définir les dimensions de ces fonctions d’agrégation vous permettra d’économiser beaucoup de travail de débogage par la suite.

Au moins, cela aurait été le cas pour moi. 🙂

L’opérateur du côlon pour la manipulation des tableaux.

@ ScottieT812 en mentionne un: aplatir un tableau, mais il y a toutes les autres variantes de sélection des bits d’un tableau:

 x=rand(10,10); flattened=x(:); Acolumn=x(:,10); Arow=x(10,:); y=rand(100); firstSix=y(1:6); lastSix=y(end-5:end); alternate=y(1:2:end); 

Pour pouvoir tester rapidement une fonction, j’utilise nargin comme ceci:

 function result = multiply(a, b) if nargin == 0 %no inputs provided, run using defaults for a and b clc; disp('RUNNING IN TEST MODE') a = 1; b = 2; end result = a*b; 

Plus tard, j’ajoute un script de test unitaire pour tester la fonction pour différentes conditions de saisie.

Utiliser ismember () pour fusionner les données organisées par identificateurs de texte. Utile lorsque vous parsingz des périodes différentes lorsque les entrées, dans mon cas les symboles de la société, vont et viennent.

 %Merge B into A based on Text identifiers UniverseA = {'A','B','C','D'}; UniverseB = {'A','C','D'}; DataA = [20 40 60 80]; DataB = [30 50 70]; MergeData = NaN(length(UniverseA),2); MergeData(:,1) = DataA; [tf, loc] = ismember(UniverseA, UniverseB); MergeData(tf,2) = DataB(loc(tf)); MergeData = 20 30 40 NaN 60 50 80 70 

Demander «pourquoi» (utile pour me faire sortir d’une trance de débogage Matlab à trois heures …)

Exécuter un modèle Simulink directement à partir d’un script (plutôt qu’interactif) à l’aide de la commande sim . Vous pouvez faire des choses comme prendre des parameters à partir d’une variable d’espace de travail et exécuter plusieurs fois sim dans une boucle pour simuler quelque chose tout en faisant varier le paramètre pour voir comment le comportement change. Beaucoup plus facile que d’essayer de le faire de manière interactive, et cela vous donne beaucoup plus de flexibilité que les blocs “oscilloscope” Simulink lors de la visualisation des résultats. (bien que vous ne puissiez pas l’utiliser pour voir ce qui se passe en temps réel pendant l’exécution de la simulation)

SrcWorkspace options DstWorkspace et SrcWorkspace de la commande simset . Celles-ci contrôlent où les blocs “To Workspace” et “From Workspace” obtiennent et placent leurs résultats. Dstworkspace défaut l’espace de travail actuel (par exemple, si vous appelez sim depuis une fonction, les blocs “To Workspace” apparaîtront comme des variables accessibles depuis cette même fonction) mais SrcWorkspace défaut l’espace de travail de base sim vous souhaiterez définir SrcWorkspace sur current afin de SrcWorkspace d’une interface propre pour fournir / récupérer les parameters et les sorties des entrées de simulation. Par exemple:

 function Y=run_my_sim(t,input1,params) % runs "my_sim.mdl" % with a From Workspace block referencing I1 as an input signal % and parameters referenced as fields of the "params" structure % and output resortingeved from a To Workspace block with name O1. opt = simset('SrcWorkspace','current','DstWorkspace','current'); I1 = struct('time',t,'signals',struct('values',input1,'dimensions',1)); Y = struct; Yt = sim('my_sim',t,opt); Y.output1 = O1.signals.values; 

Tracés de contour avec [c,h]=contour et clabel(c,h,'fontsize',fontsize) . J’utilise généralement le paramètre fontsize pour réduire la taille de la police afin que les nombres ne se rencontrent pas. Ceci est idéal pour visualiser la valeur des fonctions 2D sans avoir à manipuler des graphiques 3D.

Vectorisation:

 function iNeedle = findClosest(hay,needle) %FINDCLOSEST find the indicies of the closest elements in an array. % Given two vectors [A,B], findClosest will find the indicies of the values % in vector A closest to the values in vector B. [hay iOrgHay] = sort(hay(:)'); %#ok must have row vector % Use histogram to find indices of elements in hay closest to elements in % needle. The bins are centered on values in hay, with the edges on the % midpoint between elements. [iNeedle iNeedle] = histc(needle,[-inf hay+[diff(hay)/2 inf]]); %#ok % Reversing the sorting. iNeedle = iOrgHay(iNeedle); 

Utilisation de variables persistent (statiques) lors de l’exécution d’un algorithme en ligne. Il peut accélérer le code dans des domaines tels que l’apprentissage automatique bayésien où le modèle est formé de manière itérative pour les nouveaux échantillons. Par exemple, pour calculer les probabilités de loglik indépendantes, je calcule tout d’abord le loglikelihood et le mets à jour en additionnant cette loglikelihood précédemment calculée et la loglikelihood supplémentaire.

Au lieu de poser un problème d’apprentissage automatique plus spécialisé, permettez-moi de donner un code général de calcul en ligne que j’ai pris ici :

 function av = runningAverage(x) % The number of values entered so far - declared persistent. persistent n; % The sum of values entered so far - declared persistent. persistent sumOfX; if x == 'reset' % Initialise the persistent variables. n = 0; sumOfX = 0; av = 0; else % A data value has been added. n = n + 1; sumOfX = sumOfX + x; av = sumOfX / n; % Update the running average. end 

Ensuite, les appels donneront les résultats suivants

 runningAverage('reset') ans = 0 >> runningAverage(5) ans = 5 >> runningAverage(10) ans = 7.5000 >> runningAverage(3) ans = 6 >> runningAverage('reset') ans = 0 >> runningAverage(8) ans = 8 

Je suis surpris que les gens aient mentionné l’approche de la masortingce logique pour indexer un tableau, personne n’a mentionné la commande find.

par exemple si x est un tableau NxMxO

x (x> 20) fonctionne en générant un tableau logique NxMxO et en l’utilisant pour indexer x (ce qui peut être mauvais si vous avez de grands tableaux et recherchez un petit sous-ensemble)

x (find (x> 20)) fonctionne en générant une liste (c.-à-d. 1xwhatever) d’indices de x satisfaisant x> 20, et en indexant x par celui-ci. “trouver” devrait être utilisé plus qu’il ne l’est, selon mon expérience.

Plus ce que j’appellerais des “trucs”

vous pouvez développer / append des tableaux et des tableaux de cellules si vous ne connaissez pas la taille dont vous avez besoin, en utilisant end + 1 (fonctionne également avec des dimensions supérieures, à condition que les dimensions de la tranche correspondent). doit initialiser x à autre chose que [] dans ce cas). Pas bon pour les chiffres, mais pour les petites listes dynamics de choses (ou les tableaux de cellules), par exemple les fichiers d’parsing.

par exemple

 >> x = [1,2,3]
 x = 1 2 3
 >> x (fin + 1) = 4
 x = 1 2 3 4

Une autre idée que beaucoup de gens ne savent pas, c’est que pour les travaux sur n’importe quel tableau dim 1, pour continuer l’exemple

 >> pour n = x; disp (n); fin
      1
      2
      3
      4

Ce qui signifie que si vous n’avez besoin que des membres de x, vous n’avez pas besoin de les indexer.

Cela fonctionne également avec les tableaux de cellules, mais c’est un peu ennuyeux car, en les parcourant, l’élément est toujours enveloppé dans une cellule:

 >> pour el = {1,2,3,4}; disp (el); fin
     [1]
     [2]
     [3]
     [4]

Donc, pour obtenir les éléments, vous devez les indexer

 >> pour el = {1,2,3,4}; disp (el {1}); fin
      1
      2
      3
      4

Je ne me souviens pas s’il y a une meilleure façon de contourner cela.

-Vous pouvez créer un raccourci Matlab vers un fichier d’initialisation appelé startup.m. Ici, je définis la mise en forme, la précision de la sortie et les parameters de tracé pour ma session Matlab (par exemple, j’utilise un axe / une taille de police plus grands pour que .fig apparaisse clairement lorsque je les mets en présentations). article de blog d’un des développeurs à ce sujet http://blogs.mathworks.com/loren/2009/03/03/whats-in-your-startupm/ .

-Vous pouvez charger un fichier ASCII numérique complet en utilisant la fonction “load”. Ce n’est pas particulièrement rapide, mais fait rapidement le travail de prototypage (ne devrait-il pas s’agir de la devise de Matlab?)

-Comme mentionné, l’opérateur du côlon et la vectorisation sont des sauveteurs. Boucles à vis.

x = repmat ([1:10], 3,1); % disent que x est un exemple de tableau de données

l = x> = 3; % l est un vecteur logique (1s / 0s) pour mettre en évidence les éléments du tableau qui satisferaient une certaine condition.

N = sum (sum (l));% N est le nombre d’éléments qui répondent à cette condition donnée.

Bravo – scripting heureux!