Optymizacja zlozonego loop'a.

Optymizacja zlozonego loop'a.
S2
  • Rejestracja:około 4 lata
  • Ostatnio:około 4 lata
  • Postów:65
0

Panowie, kodze sobie ostatnio po godzinach w Javie, pewien projekt i w jednej z metod urodzil mi sie zapierajacy dech w piersiacrh koszmarek. W php biorac pod uwage mozliwosc dynamicznego deklarowania zmiennych, zrobienie w kodzie ponizej nie stanowiloby problemu, no ale to Java.

Jakies sugestie jak mozna by to "spakowac" tak zeby az tak nie "walilo po oczach"?

Kopiuj
    public void run()
    {
        this.settingsDataStorage.setSprocess("train");

        initStaticLoopers();

        List<List<Integer>> alIterations = settingsDataStorage.getAlOptimizationIterations();

        this.networkResultsCollector.init();

        int s00number = alIterations.get(0).size();
        for (int s00 = 0; s00 < s00number; s00++) {
            int i00 = 0; int i00number = alIterations.get(0).get(s00);
            while(alLoopers.get(0).setSettings(0, s00, i00, i00number) < i00number){

                i00++;

                initDynamicLoopers();

                alIterations = settingsDataStorage.getAlOptimizationIterations();

                int s01number = alIterations.get(1).size();
                for (int s01 = 0; s01 < s01number; s01++) {
                    int i01 = 0; int i01number = alIterations.get(1).get(s01);
                    while(alLoopers.get(1).setSettings(1, s01, i01, i01number) < i01number){

                        i01++;

                        int s02number = alIterations.get(2).size();
                        for (int s02 = 0; s02 < s02number; s02++) {
                            int i02 = 0; int i02number = alIterations.get(2).get(s02);
                            while(alLoopers.get(2).setSettings(2, s02, i02, i02number) < i02number){

                                i02++;

                                int s03number = alIterations.get(3).size();
                                for (int s03 = 0; s03 < s03number; s03++) {
                                    int i03 = 0; int i03number = alIterations.get(3).get(s03);
                                    while(alLoopers.get(3).setSettings(3, s03, i03, i03number) < i03number){

                                        i03++;

                                        this.networkDataStorage.initResultsCollections();

                                        int s04number = alIterations.get(4).size();
                                        for (int s04 = 0; s04 < s04number; s04++) {
                                            int i04 = 0; int i04number = alIterations.get(4).get(s04);
                                            while(alLoopers.get(4).setSettings(4, s04, i04, i04number) < i04number){

                                                i04++;

                                                int s05number = alIterations.get(5).size();
                                                for (int s05 = 0; s05 < s05number; s05++) {
                                                    int i05 = 0; int i05number = alIterations.get(5).get(s05);
                                                    while(alLoopers.get(5).setSettings(5, s05, i05, i05number) < i05number){

                                                        i05++;

                                                        int s06number = alIterations.get(6).size();
                                                        for (int s06 = 0; s06 < s06number; s06++) {
                                                            int i06 = 0; int i06number = alIterations.get(6).get(s06);
                                                            while(alLoopers.get(6).setSettings(6, s06, i06, i06number) < i06number){

                                                                i06++;

                                                                int s07number = alIterations.get(7).size();
                                                                for (int s07 = 0; s07 < s07number; s07++) {
                                                                    int i07 = 0; int i07number = alIterations.get(7).get(s07);
                                                                    while(alLoopers.get(7).setSettings(7, s07, i07, i07number) < i07number){

                                                                        i07++;

                                                                        int s08number = alIterations.get(8).size();
                                                                        for (int s08 = 0; s08 < s08number; s08++) {
                                                                            int i08 = 0; int i08number = alIterations.get(8).get(s08);
                                                                            while(alLoopers.get(8).setSettings(8, s08, i08, i08number) < i08number){

                                                                                i08++;

                                                                                int s09number = alIterations.get(9).size();
                                                                                for (int s09 = 0; s09 < s09number; s09++) {
                                                                                    int i09 = 0; int i09number = alIterations.get(9).get(s09);
                                                                                    while(alLoopers.get(9).setSettings(9, s09, i09, i09number) < i09number){

                                                                                        i09++;

                                                                                        int s10number = alIterations.get(10).size();
                                                                                        for (int s10 = 0; s10 < s10number; s10++) {
                                                                                            int i10 = 0; int i10number = alIterations.get(10).get(s10);
                                                                                            while(alLoopers.get(10).setSettings(10, s10, i10, i10number) < i10number){

                                                                                                i10++;

                                                                                                int s11number = alIterations.get(11).size();
                                                                                                for (int s11 = 0; s11 < s11number; s11++) {
                                                                                                    int i11 = 0; int i11number = alIterations.get(11).get(s11);
                                                                                                    while(alLoopers.get(11).setSettings(11, s11, i11, i11number) < i11number){

                                                                                                        i11++;

                                                                                                        int s12number = alIterations.get(12).size();
                                                                                                        for (int s12 = 0; s12 < s12number; s12++) {
                                                                                                            int i12 = 0; int i12number = alIterations.get(12).get(s12);
                                                                                                            while(alLoopers.get(12).setSettings(12, s12, i12, i12number) < i12number){

                                                                                                                i12++;

                                                                                                                trainNetwork(i12);
                                                                                                            }
                                                                                                        }
                                                                                                    }
                                                                                                }
                                                                                            }
                                                                                        }
                                                                                    }
                                                                                }
                                                                            }
                                                                        }
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }

                                        networkResultsCollector.writeResultsToFile();
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        networkResultsCollector.writeResultsCompactedToFile();
    }
LI
LongInteger
Ja bym się nie tyle martwił wyglądem, co czasem działania. Tak na oko mamy O(n^13).
lion137
  • Rejestracja:około 8 lat
  • Ostatnio:około godziny
  • Postów:4919
1

Zapodałeś mocny trójkąt forów :)


Charles_Ray
  • Rejestracja:około 17 lat
  • Ostatnio:około 11 godzin
  • Postów:1875
6

Tu problemem nie jest Java, tylko brak umiejętności programowania. W php wyglądałoby równie tragicznie i nie dałoby się tego tknąć. Nikt nie będzie za Ciebie tego refaktorowal, tym bardziej, że brak totalnych podstaw, np. nazwy zmiennych.

Przeczytaj Clean Code, to będzie dla Ciebie boost w karierze.


”Engineering is easy. People are hard.” Bill Coughran
stivens
  • Rejestracja:ponad 8 lat
  • Ostatnio:6 minut
1

Arrow anti-pattern

A poza tym to np. zamiast pisac List<List<Integer>> mozesz jak czlowiek napisac var allIterations =.


λλλ
edytowany 2x, ostatnio: stivens
Zobacz pozostałe 14 komentarzy
jarekr000000
Bo w kotlinie są extension funkcions. Za to nie ma typeclass (chyba najważniejsze zastosowanie implicit) i niestety jest to duże ograniczenie - polimorfizm objektowy to bieda z nędzą niestety. Straszenie implicitami jest modne, ale tak naprawdę - najgorsze nawet implicity nie są tak zrypane i groźne jak używanie Springa. W pewnym sensie implicity wykorzystuje się do tego samego co Spring- wrzucenia aspektów infrastruktury do kodu, z tym, że jak zrypiesz coś w implicitach to Ci się kod nie skompiluje, a nie poleci bez security i transakcji na produkcję.
stivens
@jarekr000000: mi sie raz w jakiejs libce do rysowania wykresow wykladal kod mowiac, ze jest problem z argumentem przekazywanym jako implicit. Ale tak na prawde wystarczylo ze taki normalny argument uzupelnilem (bylo jakies default value) i zaczelo dzialac. Co sie tam odwalilo to do dzisiaj nie wiem. Ale w sumie nie kopalem.
stivens
Niemniej, wciaz kod sie po prostu nie kompilowal dopoki nie naprawilem, wiec tak - to lepsze od Springa :)
somekind
var to rak - nie spodziewałem się przeczytać czegoś takiego, 2021 zaskakuje nawet bardziej niż poprzedni rok. Z drugiej strony, może to jest po prostu zbyt nowy ficzer, stąd ten opór.
LukeJL
Skąd opór przed inferencją typów? Wydaje mi się, że to jest jakiś sweet spot, gdzie masz statyczne typowanie i jego zalety, a nie musisz zwykle pisać tych typów, tylko kompilator to sam analizuje. Bawię się ostatnio w Rust i to fajnie tam działa. Ba, nawet w TypeScript zauważyłem, że to jest (kiedyś chyba nie było, albo po prostu ludzie nie wiedzieli, że jest, bo i tak pisali wszędzie adnotacje typów, co zaciemniało kod).
Shalom
  • Rejestracja:około 21 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
2

jak mozna by to "spakowac"

Ciężko powiedzieć bo kod jest zupełnie nieczytelny i nie wiadomo co chciałeś tam osiągnąć i co to w ogóle robi. Jakieś zmienne s01, s02, i01, i02 WTF? Na szybko patrząc to można by te wszystkie copy-paste zwinąć w jedną funkcje rekurencyjną chociażby, ale jestem pewien że da się nawet prościej bo te alIterations.get(10).size() sugerują ze zamiast copypaste można by tam mieć zwykłą pętle...
Ale niestety zeby to poprawić to trzeba najpierw jasno opisać co ten kod miał za zadanie robić.


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
edytowany 2x, ostatnio: Shalom
NS
  • Rejestracja:ponad 7 lat
  • Ostatnio:dzień
  • Postów:455
2

Orzesz w morde. Ma chłop rozmach :D

Silv
Moderator Wiki
  • Rejestracja:ponad 10 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Warszawa
0

OK, ja się na Javie nie znam, ale jak już przedmówcy zauważyli, kluczową kwestią jest, żebyś podał, co ten kod ma robić. Opisz np. w punktach. Zawrzyj wszystkie szczegóły – zarówno, co robi cała funkcja, jak i co robią poszczególne pętle, fragmenty itd.


edytowany 1x, ostatnio: Silv
jarekr000000
  • Rejestracja:ponad 8 lat
  • Ostatnio:dzień
  • Lokalizacja:U krasnoludów - pod górą
  • Postów:4707
6

W zasadzie sprawa jest prosta.
Funkcja przyjmuje nic, zwraca void. Czyli nie robi nic.
Upraszczamy do takiej postaci:

Kopiuj
public void run() {
}

I gotowe.

Bardziej doświadczeni programiści java, wiedzą jednak, że pewnie chodziło o coś w tym stylu:

Kopiuj
public void run() {
    throw new NullPointerException("I tak by się to tak skończyło, nie ma się co męczyć");
}

jeden i pół terabajta powinno wystarczyć każdemu
NamingException
no chyba, że pracujesz u mnie wtedy, spodziewaj się z 3 uboków na każdej metodzie zmieniających argumenty, które zapodałeś
superdurszlak
  • Rejestracja:prawie 7 lat
  • Ostatnio:3 dni
  • Lokalizacja:Kraków
  • Postów:2000
1

Nie umiem odszyfrować, co ten for w forze w forze w ... w forze przedstawia, za co odpowiadają poszczególne poziomy zagnieżdżenia (01 i tym podobne też nic nie mówią) ani ogólnie co to ma robić. Nie mam również pojęcia, co ma do tego dynamiczne typowanie / "dynamiczna deklaracja zmiennych" :(

Jeśli bardzo chcesz zamaskować fakt, że masz milion poziomów zagnieżdżenia i dodatkowo da się jakoś logicznie uzasadnić, że poziom zagnieżdżenia N różni się czymś (poza zmienną, po której iterujesz) od poziomu N-1, na pewno możesz pochować poziomy zagnieżdżenia po pomocniczych metodach... Ale w ten sposób radzisz sobie z trupem wylatującym z szafy przez poćwiartowanie go i poupychanie w szufladach.

A tak poza tym, chyba dążysz do porządnego refaktoringu, a nie optymalizacji :)

A jeśli dobrze mi się zdaje, co widzę, jest spora szansa że te pętle są zagnieżdżone zupełnie bez sensu. Masz 12 elementów czegoś, więc potrzebujesz 12 poziomów zagnieżdżenia - co, gdyby było ich 100? Co, gdyby każdy iterowany zbiór / tablica / kolekcja ze 100 miały tylko po 2 elementy? miałbyś 2^100 iteracji, czyli z grubsza 1 000 000 000 000 000 000 000 000 000 000, a w praktyce jeszcze trochę więcej. Nie jesteś w stanie przepisać tego kodu tak, by miał 1 - no góra 2 pętle zamiast N=12 wymiarów?


NamingException
  • Rejestracja:około 4 lata
  • Ostatnio:około 4 lata
  • Postów:110
1

Opowiedz co to robi.

S2
  • Rejestracja:około 4 lata
  • Ostatnio:około 4 lata
  • Postów:65
0

@Shalom:
W skrocie jest to "silnik" dla sieci neuronowej. Normalnie wszystkie parametry sieci podajesz statycznie i odpalasz algorytm i czekasz na wynik. Natomiast w przypadku tego kodu, zarowno architektura sieci, jak i wszystkie niezbedne parametry, lacznie z formatowaniem danych, zakresami danych itp itd do obrobki moga byc przygotowywane dynamicznie. Zatem masz tzw looper'y, ktorych kolejnosc ustawiane w settingu ktore przygotowuja (dynamicznie lub statycznie w zaleznosci od looper'a) konkretne wartosc ustawien tzn, zakresu danych, elementow architektury sieci itp itd, po to by w "oku cyklonu" tego koszmarka odpalic siec metoda:

Kopiuj
trainNetwork(i12);

Aplikacja jest konsolowa wiec run niekoniecznie musi mi cokolwiek zwracac, poza tym wyniki zapisywane sa do pliku, a biezacy status wyswietla w konsoli. To tak z grubsza, jesli caly czas zbyt pobieznie to chetnie dopowiem.

NamingException
Zatem masz tzw looper'y, ktorych kolejnosc ustawiane w settingu ktore przygotowuja (dynamicznie lub statycznie w zaleznosci od looper'a) konkretne wartosc ustawien
superdurszlak
  • Rejestracja:prawie 7 lat
  • Ostatnio:3 dni
  • Lokalizacja:Kraków
  • Postów:2000
0
spartan24 napisał(a):

@Shalom:

W skrocie jest to "silnik" dla sieci neuronowej. Normalnie wszystkie parametry sieci podajesz statycznie i odpalasz algorytm i czekasz na wynik. Natomiast w przypadku tego kodu, zarowno architektura sieci, jak i wszystkie niezbedne parametry, lacznie z formatowaniem danych, zakresami danych itp itd do obrobki moga byc przygotowywane dynamicznie. Zatem masz tzw looper'y, ktorych kolejnosc ustawiane w settingu ktore przygotowuja (dynamicznie lub statycznie w zaleznosci od looper'a) konkretne wartosc ustawien tzn, zakresu danych, elementow architektury sieci itp itd, po to by w "oku cyklonu" tego koszmarka odpalic siec metoda:

ale po co to ma 12 poziomów zagnieżdżenia pętli? Jakie znowu loopery? o.O Po czym tak naprawdę iterujesz, co zawierają te poszczególne cośtam(0), cośtam(1)?

Masz sobie sieć neuronową. Sieć ma warstwy, neurony, połączenia między neuronami. Dostaje dane na wejściu, przetwarza je i wypluwa coś na wyjściu.

Parametry (wagi połączeń) jesteś w stanie przedstawić jako macierze połączeń między poszczególnymi warstwami. Czyli masz tyle tych macierzy, ile warstw (nie licząc wejściowej). Czyli masz kilka, może kilkanaście macierzy reprezentujących stan / konfigurację jednej sieci neuronowej.

Teraz jeszcze potrzebujesz zbiór danych, który podzielisz na zbiory uczące, sprawdzające czy jak tam je zwał (zapomniało mi się).

Gdzie tu potrzebujesz aż 12 poziomów zagnieżdżenia?


Shalom
  • Rejestracja:około 21 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
1

Ok ok czyli robisz kupę nieczytelnego kodu żeby na koniec zawołać trainNetwork(i12); które absolutnie nic nie mówi i pracuje na jakichś globalach? To jest na poważnie? Niestety ale mój werdykt jest taki ze nie da się tego poprawić tylko trzeba go zaorać do gołej ziemi i przepisać od nowa. Tym razem z głową i bez globali. Ad uczelnia sieci o dowolnej strukturze i parametrach to https://github.com/Pharisaeus/Neural nie jest to może kanon piękna, pisane 100 lat temu na studiach, ale myśle że nadal jest wielokrotnie bardziej czytelne i train network wygląda tak: https://github.com/Pharisaeus/Neural/blob/master/NeuralNetwork/pl/edu/agh/neural/learning/backpropagation/BackpropagationLearning.py#L13 ;]


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
S2
  • Rejestracja:około 4 lata
  • Ostatnio:około 4 lata
  • Postów:65
0

@Shalom: Nie na globalach. To jest jedynie jedna z metod pewnej klasy. W moim pytaniu istota nie jest architektura calej aplikacji ale sposob poradzenia sobie z tak zagniezdzonymi loop'ami w specyfice jezyka jakim jest Java.

Jeszcze raz. Mamy szereg czynnikow ktore maja wplyw na dzialanie sieci: ilosc wartsw, ilosc inputow, ilosc outpuow, rodzaje funkcji aktywacji, sposob inicjacji wag, zakresy danych pobierane do treningu, werifykacji i testu. Kazdy z tych elementow normalnie podawany jest statycznie, tzn np ilosc warstw 3, ilosc inputow 5, ilosc output'ow 1 itp itd.
Podawania tych wszystkich wartosc recznie i odpalanie sieci, ponowne podawanie i odpalanie jest delikatnie mowiac malo efektywne.
Mozna zajac sie tym dynamicznie tzn np w przypadku architektury sieci ustawic kolejne zmiany architektury zaczynajac od 3 potem 4,5,6 konczac np 10 warstwach. Generowaniem tych konkretnych wartosci zamuja sie looper'y, zatem przykladowo ilosc warstw moze rosnac np liniowo, lub byc modyfikowana biorac pod uwage aktualny wynik nauczania. Tak ja wspominalem wczesniej zbierane jest to wszystko do kupy i odpalane w oku cyklonu.

edytowany 1x, ostatnio: spartan24
stivens
  • Rejestracja:ponad 8 lat
  • Ostatnio:6 minut
0

W moim pytaniu istota nie jest architektura calej aplikacji ale sposob poradzenia sobie z tak zagniezdzonymi loop'ami w specyfice jezyka jakim jest Java

Ale ze co ma do tego Java?

Jesli uwazasz, ze w PHP nie trzeba deklarowac zmiennych to sprobuj sobie uzyc niezadeklarowanej zmiennej :)


λλλ
edytowany 1x, ostatnio: stivens
Zobacz pozostały 1 komentarz
Shalom
To pokaż ten kod w PHP.
S2
@Shalom: jest jakas szansa, ze w koncu ktos zacznie mowic na temat?
stivens
@spartan24: to jest bardzo na temat
stivens
Albo wytlumacz chociaz PRECYZYJNIE z jakiego powodu z dwoch petli zrobilo Ci sie 300 XD
Shalom
@spartan24: zara ci coś wyczaruje
Silv
Moderator Wiki
  • Rejestracja:ponad 10 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Warszawa
0

@spartan24: Dzięki za ten opis, który już zamieściłeś. Jednak ponawiam swoją sugestię: opisz ze szczegółami, co robią poszczególne pętle i inne fragmenty kodu, które można wyodrębnić logicznie. Np. w punktach. Punktów może być dowolna ilość o dowolnym poziomie zagnieżdżenia. Chodzi mi o to, żeby reprezentacja algorytmu reprezentowanego przez tę funkcję była inna niż kod w Javie. (Nie znam się na sieciach neuronowych, więc przepraszam, jeśli ta sugestia nie jest trafna).


edytowany 1x, ostatnio: Silv
superdurszlak
  • Rejestracja:prawie 7 lat
  • Ostatnio:3 dni
  • Lokalizacja:Kraków
  • Postów:2000
1
spartan24 napisał(a):

@Shalom: Nie na globalach. To jest jedynie jedna z metod pewnej klasy. W moim pytaniu istota nie jest architektura calej aplikacji ale sposob poradzenia sobie z tak zagniezdzonymi loop'ami w specyfice jezyka jakim jest Java.

Jeszcze raz. Mamy szereg czynnikow ktore maja wplyw na dzialanie sieci: ilosc wartsw, ilosc inputow, ilosc outpuow, rodzaje funkcji aktywacji, sposob inicjacji wag, zakresy danych pobierane do treningu, werifykacji i testu. Kazdy z tych elementow normalnie podawany jest statycznie, tzn np ilosc warstw 3, ilosc inputow 5, ilosc output'ow 1 itp itd.
Podawania tych wszystkich wartosc recznie i odpalanie sieci, ponowne podawanie i odpalanie jest delikatnie mowiac malo efektywne.

Ok, zdajesz sobie sprawę że nawet wyuczenie sieci dla jednego zestawu tych parametrów może chwilę zająć? Co dopiero gdy spróbujesz przebić się przez wszystkie kombinacje np.

  • 4 różne liczby warstw sieci
  • 3 różne liczby neuronów w każdej z podwarstw (tylko tu możesz mieć 3^N możliwości!)
  • najlepiej to jeszcze K różnych algorytmów uczenia sieci
  • 5 różnych funkcji aktywacji

Chyba nie muszę wymieniać dalej? ;)

Mozna zajac sie tym dynamicznie tzn np w przypadku architektury sieci ustawic kolejne zmiany architektury zaczynajac od 3 potem 4,5,6 konczac np 10 warstwach. Generowaniem tych konkretnych wartosci zamuja sie looper'y, zatem przykladowo ilosc warstw moze rosnac np liniowo, lub byc modyfikowana biorac pod uwage aktualny wynik nauczania. Tak ja wspominalem wczesniej zbierane jest to wszystko do kupy i odpalane w oku cyklonu.

czyli te Twoje loopery to te kosmiczne 12 pętli w pętlach w pętlach? To nie zadziała.

to ze w php zrobienie czegos takiego to raptem 2 petle, zagniezdzone jedna w drugiej, a w Javie nie mam pojecia jak to zrobic, dlatego pytam.

Dalej nie wiemy co tak naprawdę chcesz zrobić. Dla mnie terminologia loopery i oko cyklonu to jakieś dziwne wymysły, które nic mi nie mówią - nigdy nie spotkałem się z podobną terminologią, może poza filmami katastroficznymi pokroju Sharknado.

Jak dla mnie to możesz chcieć sprawdzić te N^12 kombinacji jakichś ustawień, a możesz siłować się z iterowaniem po entry-secie mapy, której używałeś w PHP i nazwałeś to dynamicznym deklarowaniem zmiennych, a w Javie nie znalazłeś odpowiednika. A może chodzi o coś innego. Nie wiem, bo używasz niezrozumiałego słownictwa, którego najprawdopodobniej nikt poza Tobą nie używa.

@Shalom: jest jakas szansa, ze w koncu ktos zacznie mowic na temat?

Wyobraź sobie, że przyszedłem do Ciebie, bo mam problem z upieczeniem tortu. Zamiast mówić o świeczkach, mówię o płonących pochodniach albo źródełkach światła, jak pytasz dlaczego chcę kupić 5 piekarników to tłumaczę, że tort z cukierni miał 4 warstwy przełożone kremem, ale jak ktoś chciał to mógł mieć 5 albo 3. A potem zaczynam się wpieniać, że mówisz nie na temat :)


edytowany 1x, ostatnio: superdurszlak
S2
  • Rejestracja:około 4 lata
  • Ostatnio:około 4 lata
  • Postów:65
0

@superdurszlak: wszystko smiga bez zarzutu, oczywiscie ograniczenia wynikaja z mozliwosci sprzetu i zakresu zarowno podawanych danych jak i generowanych kombinacji ustawien.
Zatem nie mam problemu z dzialaniem kodu, a jedynie koszmarnymi loop'ami.
Poza tym po kiego te wszystkie wycieczki do PHP, tu jest mowa o Javie i o mozliwosci optymizacji tego kodu. Reasumujac nie masz pojecia jak sobie z tym poradzic i na tym poprzestanmy. Jesli sprawia ci przyjemnosc podnoszenie mi cisnienia jestem na kilku watkach na flame'ie tam sie mozemy rozmowic, tutaj nawet nie bede reagowal bo nie po to tu jestem.

S2
  • Rejestracja:około 4 lata
  • Ostatnio:około 4 lata
  • Postów:65
0

@everybody: nie odpowiadam na suche teksty.
Poczekam jeszcze na @Shalom'a jesli nie da rady nic zrobic, temat beda uwazal za zamkniety.

stivens
  • Rejestracja:ponad 8 lat
  • Ostatnio:6 minut
0

Poza tym po kiego te wszystkie wycieczki do PHP, tu jest mowa o Javie i o mozliwosci optymizacji tego kodu. Reasumujac nie masz pojecia jak sobie z tym poradzic i na tym poprzestanmy. Jesli sprawia ci przyjemnosc podnoszenie mi cisnienia jestem na kilku watkach na flame'ie tam sie mozemy rozmowic, tutaj nawet nie bede reagowal bo nie po to tu jestem.

Uwazasz ze problem jest w Javie. Zatem staramy sie wspolnie go znalezc. Poki co to nie powiedziales jeszcze ZADNYCH konkretow. Tylko jakies ogolniki pokroju w specyfice jezyka jakim jest Java.

Zauwaz ze jesli zidentyfikujemy Twoj problem to byc moze sie okaze Ty po prostu czegos nie rozumiesz i wyjasnienie Ci tego bedzie rozwiazaniem problemu.

Zatem jak bys to zrobil w PHP i dlaczego tak nie mozesz w Javie?

Bo roznica pokroju $i = 5 vs int i = 5 to nie jest powod do robienia 300 petli.


λλλ
edytowany 2x, ostatnio: stivens
Shalom
  • Rejestracja:około 21 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
0

W moim pytaniu istota nie jest architektura calej aplikacji ale sposob poradzenia sobie z tak zagniezdzonymi loop'ami w specyfice jezyka jakim jest Java.

Ja bym zaczął od jakiegoś takiego cudaka:

Kopiuj
import java.util.Collections;
import java.util.List;
import java.util.function.BiFunction;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

// bloatware, to można chwilowo zignorować

class NetworkConfiguration {
    private final int inputs;
    private final int outputs;
    private final int layers;
    private final String label;

    NetworkConfiguration(int inputs, int outputs, int layers, String label) {
        this.inputs = inputs;
        this.outputs = outputs;
        this.layers = layers;
        this.label = label;
    }

    @Override
    public String toString() {
        return "NetworkConfiguration{" +
                "inputs=" + inputs +
                ", outputs=" + outputs +
                ", layers=" + layers +
                ", label='" + label + '\'' +
                '}';
    }

    public static Builder builder() {
        return new Builder();
    }

    static class Builder {
        private int inputs;
        private int outputs;
        private int layers;
        private String label;

        public Builder withInputs(Integer inputs) {
            this.inputs = inputs;
            return this;
        }

        public Builder withOutputs(Integer outputs) {
            this.outputs = outputs;
            return this;
        }

        public Builder withLayers(Integer layers) {
            this.layers = layers;
            return this;
        }

        public Builder withLabel(String label) {
            this.label = label;
            return this;
        }

        public Builder copy() {
            return builder()
                    .withInputs(inputs)
                    .withOutputs(outputs)
                    .withLayers(layers)
                    .withLabel(label);
        }

        public NetworkConfiguration build() {
            return new NetworkConfiguration(inputs, outputs, layers, label);
        }
    }
}

public class Looper {

// to jest ważne!
    public <T> List<NetworkConfiguration.Builder> generate(List<NetworkConfiguration.Builder> templates,
                                                           List<T> values,
                                                           BiFunction<NetworkConfiguration.Builder, T, NetworkConfiguration.Builder> setter) {
        return templates
                .stream()
                .flatMap(template -> values
                        .stream()
                        .map(value -> setter.apply(template.copy(), value))
                )
                .collect(Collectors.toList());
    }

    public static void main(String[] args) {
// tak można tego używać
        Looper looper = new Looper();
        NetworkConfiguration.Builder starter = NetworkConfiguration.builder();
        List<Integer> inputs = IntStream.range(0, 10).boxed().collect(Collectors.toList());
        List<NetworkConfiguration.Builder> withInputs= looper.generate(Collections.singletonList(starter), inputs, NetworkConfiguration.Builder::withInputs);
        List<Integer> outputs = IntStream.range(10, 20).boxed().collect(Collectors.toList());
        List<NetworkConfiguration.Builder> withOutputsAndInputs = looper.generate(withInputs, outputs, NetworkConfiguration.Builder::withOutputs);

        withOutputsAndInputs.forEach(x -> System.out.println(x.build()));
    }
}

Masz jedną magiczną funkcje która generuje konfiguracje sieci na podstawie listy konfiguracji wypełniając jeden z podanych parametrów wartościami.
Można by tam pewnie xakep-style wywalic te collecty i lecieć wszystko gołymi streamami ale nie chce mi się teraz mysleć.

I teraz te twoje 70 zagnieżdżonych pętli załatwia takie:

Kopiuj
List<Integer> outputs = IntStream.range(10, 20).boxed().collect(Collectors.toList());
looper.generate(withInputs, outputs, NetworkConfiguration.Builder::withOutputs)

edit: mały fix

Kopiuj
    public <T> Stream<NetworkConfiguration.Builder> generate(Stream<NetworkConfiguration.Builder> templates,
                                                             List<T> values,
                                                             BiFunction<NetworkConfiguration.Builder, T, NetworkConfiguration.Builder> setter) {
        return templates
                .flatMap(template -> values
                        .stream()
                        .map(value -> setter.apply(template.copy(), value))
                );
    }

    public static void main(String[] args) {
        Looper looper = new Looper();
        NetworkConfiguration.Builder starter = NetworkConfiguration.builder();
        List<Integer> inputs = IntStream.range(0, 10).boxed().collect(Collectors.toList());
        Stream<NetworkConfiguration.Builder> withInputs = looper.generate(Stream.of(starter), inputs, NetworkConfiguration.Builder::withInputs);
        List<Integer> outputs = IntStream.range(10, 20).boxed().collect(Collectors.toList());
        Stream<NetworkConfiguration.Builder> withOutputsAndInputs = looper.generate(withInputs, outputs, NetworkConfiguration.Builder::withOutputs);
        List<String> labels = Arrays.asList("ala", "ma", "kota");
        Stream<NetworkConfiguration.Builder> withOutputsAndInputsAndLabels = looper.generate(withOutputsAndInputs, labels, NetworkConfiguration.Builder::withLabel);

        withOutputsAndInputsAndLabels.forEach(x -> System.out.println(x.build()));
    }

Teraz już na streamach bez zbędnych collectów. I w wersji na hackera:

Kopiuj
        Looper looper = new Looper();
        List<Integer> inputs = IntStream.range(0, 10).boxed().collect(Collectors.toList());
        List<Integer> outputs = IntStream.range(10, 20).boxed().collect(Collectors.toList());
        List<String> labels = Arrays.asList("ala", "ma", "kota");

        Stream<NetworkConfiguration> configurations = looper.generate(
                looper.generate(
                        looper.generate(
                                Stream.of(NetworkConfiguration.builder()), inputs, NetworkConfiguration.Builder::withInputs
                        ),
                        outputs, NetworkConfiguration.Builder::withOutputs
                ),
                labels, NetworkConfiguration.Builder::withLabel
        ).map(NetworkConfiguration.Builder::build);

"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
edytowany 6x, ostatnio: Shalom
superdurszlak
  • Rejestracja:prawie 7 lat
  • Ostatnio:3 dni
  • Lokalizacja:Kraków
  • Postów:2000
1

Reasumujac nie masz pojecia jak sobie z tym poradzic

Owszem, przez analogię do przykładu z tortem - nadal nie wiem po co potrzebujesz aż pięciu piekarników, by upiec swój tort przekładany kremem. Nadal nie wyjaśniłeś, po co potrzebujesz aż 5 piekarników i nadal pieklisz się, że głąby z 4programmers nie rozumieją i nie chcą pomóc.

Jak chcesz to tak zostawić, spoko - pisz sobie choćby i 200 zagnieżdżonych pętli, na zdrowie. Tylko nie miej pretensji, że nikt nie chce Ci pomóc, skoro nie chcesz przedstawić problemu w zrozumiały sposób.

I nie, loopery, oka cyklonu i zmienne zmienna1, zmienna2, zmienna3 nie objaśniają problemu.


edytowany 1x, ostatnio: superdurszlak
S2
  • Rejestracja:około 4 lata
  • Ostatnio:około 4 lata
  • Postów:65
0

@Shalom: bardzo Ci dziekuje, przeanalizuje sobie kod, ktory zapodales.
Ile sie nalezy? Daj jakies namiary na paypala to Ci chociaz na dobre piwo przesle :D.
Mowie powaznie.

edytowany 2x, ostatnio: spartan24
Shalom
Zrobiłem jeszcze maly fix, zobacz wersję 2.0 bez niepotrzebnych collectów zeby nie smiecić pamięci.
LukeJL
  • Rejestracja:około 11 lat
  • Ostatnio:minuta
  • Postów:8420
0

Panowie, kodze sobie ostatnio po godzinach w Javie, pewien projekt i w jednej z metod urodzil mi sie zapierajacy dech w piersiacrh koszmarek.

Ten kod wygląda, jakbyś tak naprawdę chciał napisać rekurencję, ale jakbyś się bał tego zrobić.


edytowany 1x, ostatnio: LukeJL
PanamaJoe
  • Rejestracja:ponad 4 lata
  • Ostatnio:około 3 lata
  • Postów:310
0
spartan24 napisał(a):

Panowie, kodze sobie ostatnio po godzinach w Javie, pewien projekt i w jednej z metod urodzil mi sie zapierajacy dech w piersiacrh koszmarek. W php biorac pod uwage mozliwosc dynamicznego deklarowania zmiennych, zrobienie w kodzie ponizej nie stanowiloby problemu, no ale to Java.

Jakies sugestie jak mozna by to "spakowac" tak zeby az tak nie "walilo po oczach"?

Kopiuj
    public void run()

            PYRAMID OF DOOM

    }

OMG co to jest? Wygląda jak Final Boss Of Refactoring.

A tak na poważnie - masz tam sagment kodu powtarzający się na kolejnych zagnieżdżeniach - jeśli jest jakiś pattern wg którego zmieniają się parametry, to może zrób z tego f-cje rekurencyjną z odpowiednimi warunkami jej kontynuacji / stopu / ew. jej uruchamianej wersji?

P.S.
Ten potwór zepsuł nawet forum, jak kliknąłem wstecz w przegladarce to mi się jakiś megajson wyświetlił :D
screenshot-20210308232011.png


A poza tym sądzę, że bootcampy należy zniszczyć.
edytowany 1x, ostatnio: PanamaJoe
vpiotr
  • Rejestracja:ponad 13 lat
  • Ostatnio:prawie 3 lata
3

Po pierwsze gratuluję OP wkręcenia @Shalom'a.

Po drugie, jeśli chodziło o test które fragmenty będą najbardziej wk...ce dla przyszłych inżynierów wsparcia, to ja głosuję na:

  • kreatywne literówki ("getAlOptimizationIteration", "alIterations", "setSprocess")
  • set z get ("setSettings")
  • stosowanie anonimowych zmiennych ("s07number")

Sugerowałbym zmianę nazwy metody "trainNetwork" bo jest trochę zbyt oczywista.

Zobacz pozostały 1 komentarz
EP
Dzięki @Shalom, zastanawiałem się jak można to ugryźć
vpiotr
Takie kody najlepiej się rozwija przy pomocy Shift+kursor+Del. Zwłaszcza 9 kolejnych powtórzeń.
PanamaJoe
@vpiotr: ty się nie śmiej, bo ja z postów Shalom'a uczę się stream api. Zniechęcisz go i bedę musiał po SO grzebać.
vpiotr
@PanamaJoe: nie czuję się na siłach żeby go skutecznie zniechęcić. Może @somekind mógłby gdyby nie to, że wszyscy już się uodpornili na jego hejt Dżawy.
somekind
To nie odporność, to hipokryzja.
ledi12
  • Rejestracja:ponad 5 lat
  • Ostatnio:około miesiąc
  • Lokalizacja:Wrocław
0

Nigdy nie wypowiadałem się w Javie ( Nie kodze, bo nie umiem i nie lubię :( ), ale ta ilość zagnieżdżeń mnie mocno zaintrygowała - Nigdy takowej nie widziałem. Mimo wszystko to szacunek dla autora, że miał cierpliwość w "rysowaniu" takiego trójkąta :D


Robię http response status cody w martwych ciągach
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)