PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Befehl zur Erstellung einer großen Diagonalmatrix



AureusPhoenix
23-11-2011, 12:53
Hi Leute,
ich bin am überlegen mir einen Befehl zu schreiben, der das Erzeugen großer Diagonalmatrizen vereinfacht. Im Prinzip so, wie der diag-Befehl von Matlab. Ich hab aber leider noch keine richtige Idee, wie man da am besten ran gehen sollte. Insbesondere, dass das Ganze für beliebig große Matrizen funktionieren soll bereitet mir Kopfschmerzen. Einen Befehl für eine 3x3 oder 4x4 ist ja kein Problem.

Zum Füllen der Matrix hatte ich überlegt, ob man zwei geschachtelte for-Schleifen nehmen könnte. Aber selbst da ist das Problem, wie man Latex beibiegt, wieviele Schleifendurchläufe er braucht. Und wie sagt man ihm welche Einträge auf der Diagonalen stehen sollen.

Ich wollte hier hauptsächlich nach Ideen und Teillösungen fragen. Also auch falls ihr keine vollständige Lösung parat habt, wäre ich euch für eure Hilfe sehr dankbar!


PS: Für die Eingabesyntax hatte ich überlegt, das sowas cool wäre (falls das möglich ist): \diag{1&2&3} --> 3x3-Matrix mit 1,2,3 auf der Diagonalen.

rais
23-11-2011, 21:34
Moin moin,


Zum Füllen der Matrix hatte ich überlegt, ob man zwei geschachtelte for-Schleifen nehmen könnte. Aber selbst da ist das Problem, wie man Latex beibiegt, wieviele Schleifendurchläufe er braucht. Und wie sagt man ihm welche Einträge auf der Diagonalen stehen sollen.

wenn ich das richtig verstehe, bräuchtest Du `nur' noch herauszufinden, in welcher Zeile (bei einer Diagonalmatrix gleicht das der Spalte, von oben links gesehen) Du Dich befindest?


\documentclass{article}
\newcounter{diagonalmatrixline}
\newcounter{diagonalmatrixlines}
\makeatletter
\newcommand*\diagonalmatrix@item{}
\newcommand*\diagonalmatrixtest[1]{%
\setcounter{diagonalmatrixline}{0}%
\setcounter{diagonalmatrixlines}{0}%
\@for\diagonalmatrix@item:=#1 \do{%
\stepcounter{diagonalmatrixlines}%
}%
\@for\diagonalmatrix@item:=#1 \do{%
\stepcounter{diagonalmatrixline}%
Eintrag \thediagonalmatrixline/\thediagonalmatrixlines\ \ensuremath{(\diagonalmatrix@item)}\par
}%
}
\makeatother
\begin{document}
\diagonalmatrixtest{\alpha,\beta,\gamma}
\bigskip
\diagonalmatrixtest{a,b,{c,d},e,f}
\end{document}

zeigt einen möglichen Ansatz: in der ersten \@for-Schleife wird lediglich ermittelt, wie viele Zeilen bzw. Spalten vorgegeben sind.
In der zweiten \@for-Schleife folgt dann die Auswertung -- an der natürlich noch gebastelt werden muß.;) -- sie demonstriert hier lediglich, wie Du an die Info kommen könntest, in welcher Zeile (bzw. Spalte) von wieviel Zeilen (bzw. Spalten) man gerade ist.

Nun bräuchtest Du theoretisch nur noch in jeder Diagonalmatrix-Zeile n-1 Nullen vor den eigentlichen Eintrag (hier \diagonalmatrix@item) und m-n Nullen hintendran zu stellen (wobei hier n für `diagonalmatrixline' und m für `diagonalmatrixlines' steht)

MfG

AureusPhoenix
23-11-2011, 21:56
Das ist ja mal echt ein genialer Code!
Vielen Dank. Sobald ich ihn fertig ausgebaut habe, werde ich ihn hier posten. Kann aber noch ein paar Tage dauern. Ich weis noch nicht wieviel Zeit ich zwischendurch finde.

Grüße

AureusPhoenix
24-11-2011, 20:36
Hi, ich hab da mal noch ne kleine Frage.
Ich bin schon fast mit dem Code fertig. Ist auch richtig cool geworden. Im Moment häng ich nur noch an einem kleinen Schönheitsfehler. Das heißt, es ginge auch ohne diesen Befehl, aber mit ihm wäre der Quelltext viel besser lesbar.

Und zwar hab ich mir nen Befehl geschrieben, der mir die Länge einer Liste bestimmt.


\documentclass{article}
\usepackage[ngerman]{babel}
\usepackage[]{xifthen}
\usepackage{amsmath}

\makeatletter

\newcounter{Num}
\newcommand*{\@listitem}{}
\newcommand*{\sizeoflist}[1]{%
\setcounter{Num}{0}%
\@for\@listitem:=#1\do{\stepcounter{Num}}%
\theNum%
}

\makeatother

\begin{document}
\sizeoflist{a,b,c,d} % --> 4
\end{document}


Wenn ich jetzt aber folgendes versuche, dann funktioniert das nicht.


\newcounter{rows}
\setcounter{rows}{\sizeoflist{a,b,c,d}}


Mir ist im Grunde auch schon klar warum. Für TeX ist die Zahl die er ausgibt ein Zeichen und kein numerischer Wert. Gibt es da irgend eine Möglichkeit ihm zu verklickern, dass das eine Zahl ist?


Nochmals Danke!
Grüße

rais
24-11-2011, 22:16
Moin moin,


Wenn ich jetzt aber folgendes versuche, dann funktioniert das nicht.


\newcounter{rows}
\setcounter{rows}{\sizeoflist{a,b,c,d}}


Mir ist im Grunde auch schon klar warum. Für TeX ist die Zahl die er ausgibt ein Zeichen und kein numerischer Wert. Gibt es da irgend eine Möglichkeit ihm zu verklickern, dass das eine Zahl ist?

ich würde die Ausgabe \theNum aus \sizeoflist entfernen und das in etwa so aufrufen


\newcounter{rows}
\sizeoflist{a,b,c,d} % 4 --> Num
\setcounter{rows}{\value{Num}}%<-- rows=Num

Beim Hantieren mit Zählern ist es Imho eh besser, mit \value (oder eine Ebene tiefer mit \c@...) zu arbeiten, als sich darauf zu verlassen, daß \the<Zähler> einen auswertbaren Wert liefert (der darf ja gerne mal \Roman oder \alph oder gar eine Kombination aus mehreren Zählern (vgl. \thesubsection etc.) statt eines numerischen Wertes liefern).

MfG

AureusPhoenix
25-11-2011, 12:39
So, meine Befehle sind jetzt soweit fertig. Ich stell sie hier einfach mal rein, für den Fall, das nochmal jemand sowas machen will.

Eine kleine Frage hätte ich zwar noch, aber die Stell ich am besten erst ganz unten.
Hier der Code, den ich geschrieben habe:




\usepackage[]{xifthen}
\usepackage{amsmath}
\usepackage{forloop}

\makeatletter

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%% Counter Initilization %%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\newcounter{Num}
\newcounter{Row}
\newcounter{Col}
\newcounter{Rows}
\newcounter{Help}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%% List Management %%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%\makelist[stepwidth]{from}{to}
\newcommand{\makelist}[3][1]{\forLoop[#1]{#2}{#3}{Num}{\theNum, }}

%\getfromlist[index, default=1]{list}
\newcommand*{\@listitem}{}
\newcommand*{\getfromlist}[2][1]{%
\setcounter{Num}{0} %
\@for\@listitem:=#2\do{%
\stepcounter{Num}%
\ifthenelse{\equal{\theNum}{#1}}{\@listitem}{}%
}%
}

%\sizeoflist[optional counter]{list}
\newcommand{\sizeoflist}{\@ifstar\@sizeoflistStar\ @sizeoflistNoStar}

\newcommand*{\@sizeoflistNoStar}[2][Num]{%
\setcounter{Num}{0}%
\@for\@listitem:=#2\do{\stepcounter{Num}}%
\theNum\setcounter{#1}{\value{Num}}%
}

\newcommand*{\@sizeoflistStar}[2][Num]{%
\setcounter{Num}{0}%
\@for\@listitem:=#2\do{\stepcounter{Num}}%
\setcounter{#1}{\value{Num}}%
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%% Identity Matrix %%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%\ones(*)[background]{size}
\newcommand{\ones}{\@ifstar\@onesStar\@onesNoStar}

% Command without Star
\newcommand*{\@onesNoStar}[2][0]{%
\setcounter{Row}{0}%
\setcounter{Col}{0}%
\setcounter{Rows}{#2}%
\stepcounter{Rows}%
%
\ensuremath{%
\begin{matrix}%
\forloop{Row}{1}{\theRow < \theRows}{%
\forloop{Col}{1}{\theCol < \theRows}{%
\ifthenelse{\equal{\theRow}{\theCol}}{1}{#1}%
\ifthenelse{\equal{\theCol}{\theRows}}{}{&}%
}\\}%
\end{matrix}}%
}

% Command with Star
\newcommand*{\@onesStar}[2][0]{%
\setcounter{Row}{0}%
\setcounter{Col}{0}%
\setcounter{Rows}{#2}%
\setcounter{Help}{\theRows}%
\stepcounter{Rows}%
%
\ensuremath{%
\begin{matrix}%
\forloop[-1]{Row}{\theHelp}{\theRow > 0}{%
\forloop{Col}{1}{\theCol < \theRows}{%
\ifthenelse{\equal{\theRow}{\theCol}}{1}{#1}%
\ifthenelse{\equal{\theCol}{\theRows}}{}{&}%
}\\}%
\end{matrix}}%
}



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%% Arbitrary Diagonal Matrix %%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


%\diag(*)[matrix background]{list}
\newcommand{\diag}{\@ifstar\@diagStar\@diagNoStar}

\newcommand*{\@diagNoStar}[2][0]{%
\setcounter{Row}{0}%
\setcounter{Col}{0}%
\sizeoflist*[Rows]{#2}%
\stepcounter{Rows}%
%
\ensuremath{%
\begin{matrix}
\forloop{Row}{1}{\theRow < \theRows}{%
\forloop{Col}{1}{\theCol < \theRows}{%
\ifthenelse{\equal{\theRow}{\theCol}}{\getfromlist[\theRow]{#2}}{#1}%
\ifthenelse{\equal{\theCol}{\theRows}}{}{&}%
}\\}%
\end{matrix}}%
}

\newcommand*{\@diagStar}[2][0]{%
\setcounter{Row}{0}%
\setcounter{Col}{0}%
\sizeoflist*[Rows]{#2}%
\setcounter{Help}{\theRows}%
\stepcounter{Rows}%
%
\ensuremath{%
\begin{matrix}%
\forloop[-1]{Row}{\theHelp}{\theRow > 0}{%
\forloop{Col}{1}{\theCol < \theRows}{%
\ifthenelse{\equal{\theRow}{\theCol}}{\getfromlist[\theRow]{#2}}{#1}%
\ifthenelse{\equal{\theCol}{\theRows}}{}{&}%
}\\}%
\end{matrix}}%
}

\makeatother


Im Anhang befindet sich eine Beispieldatei, die zeigt, was damit so alles möglich ist.


Jetzt noch schnell zu meiner Frage. Im Code gibt es den Befehl \makelist (auch in der pdf zu sehen). Der Befehl setzt zwar am Ende noch ein Komma, das sollte aber nicht das Problem sein. Ich habe mit dem Befehl nun folgendes versucht:



\getfromlist[3]{\makelist[1]{1}{10}}


Das klappt nicht. Ich vermute, das TeX wieder den Ausgabestring von \makelist nicht für eine liste hält, wie ich sie ihm eingeben würde. Lässt sich da was machen? Damit käme man um die längliche Defintion des \ones Befehl rundrum, weil man ihn auf \diag zurückführen könnte.

Nochmal Danke!
Grüße

rais
27-11-2011, 11:13
Moin moin,

Im Code gibt es den Befehl \makelist (auch in der pdf zu sehen). Der Befehl setzt zwar am Ende noch ein Komma, das sollte aber nicht das Problem sein. Ich habe mit dem Befehl nun folgendes versucht:



\getfromlist[3]{\makelist[1]{1}{10}}


Das klappt nicht. Ich vermute, das TeX wieder den Ausgabestring von \makelist nicht für eine liste hält, wie ich sie ihm eingeben würde.
der in Deinem \makelist verwendete \forLoop nutzt intern \ifthenelse aus dem ifthen-Paket, da gibt es afair Probleme, wenn man an das expandierte Ergebnis kommen will (vllt irre ich mich auch).
Mit einem kleinen Umweg geht's:


\newcommand*\meineliste{}%
\newcommand*\Makelist[3][1]{%
\forLoop[#1]{#2}{#3}{Num}{\edef\meineliste{\meineliste\ifnum\v alue{Num}>1,\fi\theNum}}%
}

und dann im Text


\Makelist[2]{1}{10}%
(\meineliste)
\getfromlist[3]{\meineliste}

MfG

AureusPhoenix
28-11-2011, 15:57
Danke!
Die Sache mit den expandierten Befehlen usw. ist mir allerdings schon lange ein Rätsel. Du kennst nicht zufällig ein Buch oder eine Webseite wo der ganze Kram (insbesondere dieses \expandafter usw.) gut beschrieben steht?

Grüße

rais
29-11-2011, 01:00
Nunja, gerade bei Expansion hat auch meiner einer noch diverse Lücken :(
Ich find das TeXbyTopic recht gut -- und ist immer griffbereit (texdoc TeXbyTopic).
Du kannst ja mal stöbern, was bei Dir alles unter doc/plain bzw. doc/generic schlummert;-)

MfG