Násobení matic a automatické přetypování

stud

Násobení matic a automatické přetypování
« kdy: 17. 09. 2015, 13:34:25 »
Mám třídy pro obecnou matici a čtvercovou matici. Násobení dvou obecných matic někdy dá čtvercovou matici. Lze v nějakém OO jazyce zajistit, abych v takovém případě dostal instanci čtvercové matice (aby šly použít metody dávající smysl jen pro čtvercovou matici)?


k

Re:Násobení matic a automatické přetypování
« Odpověď #1 kdy: 17. 09. 2015, 13:58:47 »
To přece šlo vždycky, z násobení dostanete obecný prapředek Object a zeptáte se přes nějaké instanceof, zda máte jednu nebo druhou instanci a podle toho přetypujete a pokračujete dál.

zboj

  • *****
  • 1 507
    • Zobrazit profil
    • E-mail
Re:Násobení matic a automatické přetypování
« Odpověď #2 kdy: 17. 09. 2015, 14:01:28 »
To přece šlo vždycky, z násobení dostanete obecný prapředek Object a zeptáte se přes nějaké instanceof, zda máte jednu nebo druhou instanci a podle toho přetypujete a pokračujete dál.

Ono jde asi o to, jak to udělat bez instanceof a přetypování.

Radek Miček

Re:Násobení matic a automatické přetypování
« Odpověď #3 kdy: 17. 09. 2015, 14:03:47 »
Citace
Lze v nějakém OO jazyce zajistit, abych v takovém případě dostal instanci čtvercové matice (aby šly použít metody dávající smysl jen pro čtvercovou matici)?

Lze to třeba v C# - stačí zakódovat rozměry matice do jejího typu:

Kód: [Vybrat]
    using Two = S<S<Z>>;
    using Three = S<S<S<Z>>>;

    // Prirozena cisla.
    public class Nat { }
    public class Z : Nat { }
    public class S<N> : Nat where N : Nat { }
    public class Matrix<M, N> where M : Nat where N : Nat
    {
        public Matrix<M, P> Multiply<P>(Matrix<N, P> other)
        {
            throw new NotImplementedException();
        }
    }

    public static class SquareMatrixExtensions
    {
        // Pouze pro ctvercove matice.
        public static int Determinant<N>(this Matrix<N, N> m)
        {
            throw new NotImplementedException();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var a = new Matrix<Two, Three>();
            var b = new Matrix<Three, Two>();
            var x = a.Multiply(b);

            x.Determinant();
            //b.Determinant(); // Neprelozi se.
        }
    }

Nicméně se obávám, že to nebude praktické. Problémy například nastanou, když rozměry matice nebudou známy v době kompilace na úrovni typového systému.

gamer

Re:Násobení matic a automatické přetypování
« Odpověď #4 kdy: 17. 09. 2015, 14:27:45 »
V C++ by se na to dal použít boost variant: http://www.boost.org/doc/libs/1_59_0/doc/html/variant.html
Ale není to moc hezké řešení a myslím si, že to ve skutečnosti nechceš.


zboj

  • *****
  • 1 507
    • Zobrazit profil
    • E-mail
Re:Násobení matic a automatické přetypování
« Odpověď #5 kdy: 17. 09. 2015, 14:40:02 »
To se řeší buď implicitním přetypováním za běhu (v C++, C# to nesmyslně zakazuje), nebo v jazycích umožňujících mít stejnou metodu s různým návratovým typem nějakým vesměs nepěkným trikem. Ve Swiftu by bylo například

Kód: [Vybrat]
func *(m1:Matrix,m2:Matrix)->Matrix
func *(m1:Matrix,m2:Matrix)->SquareMatrix

a když se použije (m1*m2).trace, tak se automaticky vybere druhá implementace, protože nečtvercová matice stopu nemá.

Podobně, ale poněkud elegantněji, lze řešit problém dědičnosti funktorů; například diferenciální operátor bere tenzor a vrací něco jako MultidimensionalArrayWithUpperAndLowerIndices (ať žije čitelnost :) ), nicméně některé vrací zase tenzor. V C# a C++ pak můžu mít dva delegáty/funktory, které od sebe dědí, a pokud použiju například kovariantní nebo absolutní derivaci, lze s výsledkem pracovat jako s tenzorem bez přetypování. Obecně se takové věci ale řeší těžko, protože typový systém je záležitost doby kompilace, kdežto tady se bavíme o době běhu.

JSH

Re:Násobení matic a automatické přetypování
« Odpověď #6 kdy: 17. 09. 2015, 14:41:56 »
Mám třídy pro obecnou matici a čtvercovou matici. Násobení dvou obecných matic někdy dá čtvercovou matici. Lze v nějakém OO jazyce zajistit, abych v takovém případě dostal instanci čtvercové matice (aby šly použít metody dávající smysl jen pro čtvercovou matici)?
Asi bych to nekomplikoval. Násobení vrátí obdélníkovou matici a čtvercová se z ní udělá pomocí funkce co sežere tu obdélníkovou a vykrade jí vnitřnosti (drobně si uprav podle jazyka).

Vracet různé typy jde skoro všude (třeba odvozené ze společné abstraktní matice). Akorát abys tu čtvercovou matici mohl použít, tak ji stejně musíš očekávat, nebo to testovat. A v takovém případě se nějaké rozumné přetypování ztratí.

Inkvizitor

Re:Násobení matic a automatické přetypování
« Odpověď #7 kdy: 17. 09. 2015, 14:53:20 »
A je fakt nutné mít jiný typ (třídu) pro čtvercovou matici? Jinak, podobné věci umí třeba Scala.

JSH

Re:Násobení matic a automatické přetypování
« Odpověď #8 kdy: 17. 09. 2015, 14:55:16 »
To se řeší buď implicitním přetypováním za běhu (v C++, C# to nesmyslně zakazuje) ...
Tak jednoznačně neodsuzoval. Mám pocit, že se častěji chytám do pasti, než že by mi to implicitní přetypování nějak často pomáhalo. I autoři C++ standardu si párkrát naběhli na vidle. Ta debata kam explicit patří a kam ne je celkem výživná.

zboj

  • *****
  • 1 507
    • Zobrazit profil
    • E-mail
Re:Násobení matic a automatické přetypování
« Odpověď #9 kdy: 17. 09. 2015, 14:59:24 »
To se řeší buď implicitním přetypováním za běhu (v C++, C# to nesmyslně zakazuje) ...
Tak jednoznačně neodsuzoval. Mám pocit, že se častěji chytám do pasti, než že by mi to implicitní přetypování nějak často pomáhalo. I autoři C++ standardu si párkrát naběhli na vidle. Ta debata kam explicit patří a kam ne je celkem výživná.
Jistě, ale zde by se právě dost hodilo.

zboj

  • *****
  • 1 507
    • Zobrazit profil
    • E-mail
Re:Násobení matic a automatické přetypování
« Odpověď #10 kdy: 17. 09. 2015, 15:09:02 »
To se řeší buď implicitním přetypováním za běhu (v C++, C# to nesmyslně zakazuje) ...
Tak jednoznačně neodsuzoval. Mám pocit, že se častěji chytám do pasti, než že by mi to implicitní přetypování nějak často pomáhalo. I autoři C++ standardu si párkrát naběhli na vidle. Ta debata kam explicit patří a kam ne je celkem výživná.
BTW C# v tomto případě zakazuje i explicitní casting.

zboj

  • *****
  • 1 507
    • Zobrazit profil
    • E-mail
Re:Násobení matic a automatické přetypování
« Odpověď #11 kdy: 17. 09. 2015, 15:11:08 »
Mám třídy pro obecnou matici a čtvercovou matici. Násobení dvou obecných matic někdy dá čtvercovou matici. Lze v nějakém OO jazyce zajistit, abych v takovém případě dostal instanci čtvercové matice (aby šly použít metody dávající smysl jen pro čtvercovou matici)?
Asi bych to nekomplikoval. Násobení vrátí obdélníkovou matici a čtvercová se z ní udělá pomocí funkce co sežere tu obdélníkovou a vykrade jí vnitřnosti (drobně si uprav podle jazyka).


To by byl ten případ s (implicitním) přetypováním (operator SquareMatrix()), nicméně ani to mi neumožní napsat v C++ něco jako (m1*m2).trace() (na rozdíl od Swiftu).

zboj

  • *****
  • 1 507
    • Zobrazit profil
    • E-mail
Re:Násobení matic a automatické přetypování
« Odpověď #12 kdy: 17. 09. 2015, 15:32:25 »
A je fakt nutné mít jiný typ (třídu) pro čtvercovou matici? Jinak, podobné věci umí třeba Scala.
Je to vhodné, ale nemusí od sebe dědit. Vlastně by to mělo být struct, a tam se dědit ani nedá.

k

Re:Násobení matic a automatické přetypování
« Odpověď #13 kdy: 17. 09. 2015, 15:44:57 »
To přece šlo vždycky, z násobení dostanete obecný prapředek Object a zeptáte se přes nějaké instanceof, zda máte jednu nebo druhou instanci a podle toho přetypujete a pokračujete dál.

Ono jde asi o to, jak to udělat bez instanceof a přetypování.

Instanceof tam bude povinně, z důvodu že se mohou vrátit instance dvou různých nezávislých tříd a předem nevíme co se vrátí. (Teoreticky to v případě násobení matic vědět můžeme, ale tento případ se neuvažuje).

a když se použije (m1*m2).trace, tak se automaticky vybere druhá implementace, protože nečtvercová matice stopu nemá.

(m1*m2).trace nelze použít, protože dopředu nevíte co bude výsledkem operace. Když to nějakým způsobem budete umět odhadnout předem, pak samozřejmě ano.

zboj

  • *****
  • 1 507
    • Zobrazit profil
    • E-mail
Re:Násobení matic a automatické přetypování
« Odpověď #14 kdy: 17. 09. 2015, 15:47:41 »
To přece šlo vždycky, z násobení dostanete obecný prapředek Object a zeptáte se přes nějaké instanceof, zda máte jednu nebo druhou instanci a podle toho přetypujete a pokračujete dál.

Ono jde asi o to, jak to udělat bez instanceof a přetypování.

Instanceof tam bude povinně, z důvodu že se mohou vrátit instance dvou různých nezávislých tříd a předem nevíme co se vrátí. (Teoreticky to v případě násobení matic vědět můžeme, ale tento případ se neuvažuje).

a když se použije (m1*m2).trace, tak se automaticky vybere druhá implementace, protože nečtvercová matice stopu nemá.

(m1*m2).trace nelze použít, protože dopředu nevíte co bude výsledkem operace. Když to nějakým způsobem budete umět odhadnout předem, pak samozřejmě ano.
Lze to použít, kdyby mi to nešlo přeložit, tak to sem nepíšu. Čili jde to i bez instanceof a explicitního přetypování.