Simplen Algorithmus optimieren

Status
Nicht offen für weitere Antworten.

0001001

Bekanntes Mitglied
Hi,

ich habe folgenden Algorithmus, der das Tanimoto Ähnlichkeitsmaß berechnet:
Java:
    private double calculateTanimoto(List<String> valuesA, List<String> valuesB) {
    	// create set union of all values
    	Set<String> set = new HashSet<String>();
    	set.addAll(valuesA);
    	set.addAll(valuesB);

    	// calc tanimoto parameters
  	
    	double nA = 0;
    	double nB = 0;
    	double nAB = 0;
    	
    	for(String s: set){
    		if(valuesA.contains(s)){
    			nA++;
    		}
    		if(valuesB.contains(s)){
    			nB++;
    		}
    		if(valuesA.contains(s) && valuesB.contains(s)){
    			nAB++;
    		}
    	}    	
    	
    	// calc tanimoto    	
    	return ((nAB/(nA+nB-nAB)));
    }

Problem sind IMHO die contains() Aufrufe. D.h. es wird für jeden Wert in der Gesamtliste (set) geprüft, ob der Wert in der ListeA (valuesA) oder der ListeB (valuesB) oder in beiden Listen vorkommt.

Ich vermute, dass die Suche mit contains sehr langsam ist. Könnte man das effizienter umsetzen?

Hier mein erster Verbesserungsvorschlag:
Java:
private double calculateTanimoto(List<String> valuesA, List<String> valuesB) {
    	// create set union of all values
    	Set<String> set = new HashSet<String>();
    	set.addAll(valuesA);
    	set.addAll(valuesB);
    	
    	Set<String> setA = new HashSet<String>(); // set is faster than hashmap
    	setA.addAll(valuesA);
    	Set<String> setB = new HashSet<String>();
    	setB.addAll(valuesB);
    	
    	// calc tanimoto parameters
    	int i=0;    	
    	double nA = 0;
    	double nB = 0;
    	double nAB = 0;
    	
    	
    	for(String s: set){
    		boolean inA = false;
    		boolean inB = false;
    		if(setA.contains(s)){
    			nA++;
    			inA = true;
    		}
    		if(setB.contains(s)){
    			nB++;
    			inB = true;
    		}
    		if(inA && inB){
    			nAB++;
    		}
    		i++;
    	}
    	
    	
    	// calc tanimoto    	
    	return ((nAB/(nA+nB-nAB)));
    }

Könnte man das noch weiter optimieren?
 
M

maki

Gast
nimm einen Profiler, alles andere ist geraten und führt nur durch Zufall zum Erfolg.
 
S

SlaterB

Gast
setA und setB sind schon ziemlich gut,
aber wozu danach noch nA/ nb zählen? dürfte doch genau setA.size() usw. sein,
für die Schnittmenge gibts sicher vorgegebene Methoden setA.retain(setB) oder so, und dann wieder size(),
Set<String> set ist dann überflüssig


Zählvariablen allgemein schon gar nicht als double

-----

aber mit Set ist alles geschafft, danach kann es eigentlich gar nicht mehr langsam sein,
wenn der ganze Arbeitsspeicher in wenigen sec durchgezählt werden könnte, braucht man da nicht viel mehr machen
 

Marco13

Top Contributor
Code:
    private static double calculateTanimotoB(List<String> valuesA, List<String> valuesB)
    {
        Set<String> union = new HashSet<String>(valuesA);
        union.addAll(valuesB);
        Set<String> intersection = new HashSet<String>(valuesA);
        intersection.retainAll(new HashSet<String>(valuesB));
        return (double)intersection.size() / union.size();
    }
 

Marco13

Top Contributor
Vielleicht noch der passende Microbenchmark dazu
Java:
import java.util.*;


class Tanimoto
{
    private static Random random = new Random(0);

    public static void main(String args[])
    {
        //verify();
        benchmark();
    }

    private static String createRandomString(int len)
    {
        StringBuilder sb = new StringBuilder();
        for (int i=0; i<len; i++)
        {
            sb.append('A'+(char)(random.nextFloat()*('Z'-'A')));
        }
        return sb.toString();
    }

    private static void verify()
    {
        int n = 3000;
        int len = 2;
        List<String> a = new ArrayList<String>();
        List<String> b = new ArrayList<String>();

        for (int i=0; i<n; i++)
        {
            a.add(createRandomString(len));
            b.add(createRandomString(len));
        }

        testA(n, len, 1, a, b);
        testB(n, len, 1, a, b);
    }

    private static void benchmark()
    {
        int len = 3;
        for (int n=1000; n<=2000; n+=250)
        {
            List<String> a = new ArrayList<String>();
            List<String> b = new ArrayList<String>();

            for (int i=0; i<n; i++)
            {
                a.add(createRandomString(len));
                b.add(createRandomString(len));
            }

            for (int runs=5; runs<=25; runs+=5)
            {
                testA(n, len, runs, a, b);
                testB(n, len, runs, a, b);
            }
        }
    }


    private static void testA(int n, int len, int runs, List<String> a, List<String> b)
    {
        double result = 0;
        long before = System.nanoTime();
        for (int r=0; r<runs; r++)
        {
            result += calculateTanimoto(a, b);
        }
        long after = System.nanoTime();
        double ms = (after-before) / 1000000.0;
        System.out.println("testA n="+n+" len="+len+" runs="+runs+" result "+result+" ms: "+ms);
    }


    private static double calculateTanimoto(List<String> valuesA, List<String> valuesB)
    {
        // create set union of all values
        Set<String> set = new HashSet<String>();
        set.addAll(valuesA);
        set.addAll(valuesB);

        // calc tanimoto parameters

        double nA = 0;
        double nB = 0;
        double nAB = 0;

        for(String s: set)
        {
            if(valuesA.contains(s))
            {
                nA++;
            }
            if(valuesB.contains(s))
            {
                nB++;
            }
            if(valuesA.contains(s) && valuesB.contains(s))
            {
                nAB++;
            }
        }

        // calc tanimoto
        return ((nAB/(nA+nB-nAB)));
    }






    private static void testB(int n, int len, int runs, List<String> a, List<String> b)
    {
        double result = 0;
        long before = System.nanoTime();
        for (int r=0; r<runs; r++)
        {
            result += calculateTanimotoB(a, b);
        }
        long after = System.nanoTime();
        double ms = (after-before) / 1000000.0;
        System.out.println("testB n="+n+" len="+len+" runs="+runs+" result "+result+" ms: "+ms);
    }


    private static double calculateTanimotoB(List<String> valuesA, List<String> valuesB)
    {
        Set<String> union = new HashSet<String>(valuesA);
        union.addAll(valuesB);
        Set<String> intersection = new HashSet<String>(valuesA);
        intersection.retainAll(new HashSet<String>(valuesB));
        return (double)intersection.size() / union.size();
    }


}


Die Ausgaben gehen so in die Richtung von
Code:
testA n=1250 len=3 runs=25 result 1.0276936391172657 ms: 4191.643598
testB n=1250 len=3 runs=25 result 1.0276936391172657 ms: 10.984808

nimm einen Profiler, alles andere ist geraten und führt nur durch Zufall zum Erfolg.

Nachdenken und das Problem analysieren hilft aber auch manchmal ;)


EDIT: Ach, das bezog sich noch auf die "unoptimierte" version - bei der Optimierten ist's nicht meht sooo deutlich
Code:
testA n=25000 len=3 runs=25 result 16.538897406839542 ms: 321.682439
testB n=25000 len=3 runs=25 result 16.538897406839542 ms: 269.092776
Aber zumindest einfacher, übersichtlicher, und zumindest noch einen Tick schneller....
 
Zuletzt bearbeitet:
S

SlaterB

Gast
Java:
    private static double calculateTanimotoC(List<String> valuesA, List<String> valuesB)
    {
        Set<String> setA = new HashSet<String>(valuesA);
        Set<String> setB = new HashSet<String>(valuesB);
        int a = setA.size();
        int b = setB.size();

        setA.retainAll(setB);
        double inter = setA.size();
        return inter / (a + b - inter);
    }

Code:
testB n=3000 len=2 runs=1 result 0.9888 ms: 20.532498
testC n=3000 len=2 runs=1 result 0.9888 ms: 2.372927
testB n=1000 len=3 runs=5 result 0.16782099094299413 ms: 12.829563
testC n=1000 len=3 runs=5 result 0.16782099094299413 ms: 2.282692
testB n=1000 len=3 runs=10 result 0.3356419818859883 ms: 11.040789
testC n=1000 len=3 runs=10 result 0.3356419818859883 ms: 4.52767
testB n=1000 len=3 runs=15 result 0.5034629728289826 ms: 15.864866
testC n=1000 len=3 runs=15 result 0.5034629728289826 ms: 8.104661
testB n=1000 len=3 runs=20 result 0.6712839637719765 ms: 20.201171
testC n=1000 len=3 runs=20 result 0.6712839637719765 ms: 10.646605
testB n=1000 len=3 runs=25 result 0.8391049547149705 ms: 24.886403
testC n=1000 len=3 runs=25 result 0.8391049547149705 ms: 13.072332
;)
 
S

SlaterB

Gast
und weil ja jede ms zählt:

Java:
 private static double calculateTanimotoD(List<String> valuesA, List<String> valuesB)
    {
        Set<String> setA = new HashSet<String>(valuesA);
        Set<String> setB = new HashSet<String>(valuesB);
        int a = setA.size();
        int b = setB.size();

        int inter = 0;
        for (String stB : setB)
        {
            if (setA.contains(stB))
            {
                inter++;
            }
        }
        return (double) inter / (a + b - inter);
    }
Code:
testB n=3000 len=2 runs=1 result 0.9888 ms: 9.317664
testC n=3000 len=2 runs=1 result 0.9888 ms: 2.11675
testD n=3000 len=2 runs=1 result 0.9888 ms: 1.767822
testB n=1000 len=3 runs=5 result 0.16782099094299413 ms: 10.514465
testC n=1000 len=3 runs=5 result 0.16782099094299413 ms: 2.235201
testD n=1000 len=3 runs=5 result 0.16782099094299413 ms: 3.781206
testB n=1000 len=3 runs=10 result 0.3356419818859883 ms: 9.703188
testC n=1000 len=3 runs=10 result 0.3356419818859883 ms: 5.191442
testD n=1000 len=3 runs=10 result 0.3356419818859883 ms: 4.336585
testB n=1000 len=3 runs=15 result 0.5034629728289826 ms: 14.794059
testC n=1000 len=3 runs=15 result 0.5034629728289826 ms: 7.285562
testD n=1000 len=3 runs=15 result 0.5034629728289826 ms: 5.799899
testB n=1000 len=3 runs=20 result 0.6712839637719765 ms: 18.52945
testC n=1000 len=3 runs=20 result 0.6712839637719765 ms: 9.555125
testD n=1000 len=3 runs=20 result 0.6712839637719765 ms: 8.67708
testB n=1000 len=3 runs=25 result 0.8391049547149705 ms: 24.19721
testC n=1000 len=3 runs=25 result 0.8391049547149705 ms: 12.983773
testD n=1000 len=3 runs=25 result 0.8391049547149705 ms: 10.62677
 
M

maki

Gast
nimm einen Profiler, alles andere ist geraten und führt nur durch Zufall zum Erfolg.

Nachdenken und das Problem analysieren hilft aber auch manchmal ;)
Aber ob das Ergebnis schneller, langsamer oder genau gleich ist, merkt man erst, wenn man misst, und das habt ihr ja ;)
Optimierungen jedoch ohne Überprüfung enden meist nicht als Optimierungen...
 

Marco13

Top Contributor
Code:
    private static double calculateTanimotoE(List<String> valuesA, List<String> valuesB)
    {
        Set<String> setA = new HashSet<String>(valuesA);
        int inter = 0;
        for (String stB : valuesB)
        {
            if (setA.contains(stB))
            {
                inter++;
            }
        }
        return (double) inter / (setA.size() + valuesB.size() - inter);
    }
-->
Code:
testD n=70000 len=3 runs=70 result 68.3913711432595 ms: 1122.14439
testE n=70000 len=3 runs=70 result 68.3913711432595 ms: 1110.968867

:joke: (Nicht so ernst zu nehmen - die Zeiten pendeln da im Rahmen der Messungenauigkeit umeinander - aber schon "aus Prinzip" sollte man sich das überflüssige new HashSet sparen ;) )
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
Moritz1508 Variablen Erstellung eines simplen Taschenrechners mit +/- - Auswahl Java Basics - Anfänger-Themen 2
Q OOP Object Array im simplen Shopsystem Java Basics - Anfänger-Themen 6
D .wav Sound in einer simplen Applikation abspielen Java Basics - Anfänger-Themen 3
L Fehler im simplen Quellcode! Java Basics - Anfänger-Themen 2
laxla123 Eigenschaften eines Algorithmus (determiniert vs.. deterministisch) Java Basics - Anfänger-Themen 2
C Gewinnspiel erstellen mit Algorithmus Java Basics - Anfänger-Themen 3
C negamax-Algorithmus für Tic-Tac-Toe spielt manchmal falsch Java Basics - Anfänger-Themen 10
H Minimax Algorithmus in Tic Tac Toe Java Basics - Anfänger-Themen 3
M Minimax-Algorithmus für Vier gewinnt Java Basics - Anfänger-Themen 11
ohneInformatik; Trockentest Algorithmus, mathematischen Zusammenhang angeben Java Basics - Anfänger-Themen 3
M Minimax-Algorithmus Java Basics - Anfänger-Themen 17
mervanpolat Binary Search Algorithmus ausführen Java Basics - Anfänger-Themen 1
J Rekursiver Algorithmus Java Basics - Anfänger-Themen 9
M monte carlo Algorithmus für 4 gewinnt Java Basics - Anfänger-Themen 12
izoards Sortier Algorithmus für Bounding Box Elememte Links nach Rechts und von Oben nach Unten Java Basics - Anfänger-Themen 33
S Algorithmus entwicklen, der zu einem gegebenen Datum die Jahreszeit ermittelt Java Basics - Anfänger-Themen 13
rosima26 Merge-Algorithmus Java Basics - Anfänger-Themen 53
C Ein Algorithmus soll schneller werden Java Basics - Anfänger-Themen 24
D Dijkstra Algorithmus Hilfe!! Java Basics - Anfänger-Themen 9
U Den Kuchen aufteilen - aber wie? (Rebalancing-Algorithmus) Java Basics - Anfänger-Themen 14
s_1895 Pseudocode Naiver Algorithmus Java Basics - Anfänger-Themen 17
H String verschlüsseln - eigener Algorithmus Java Basics - Anfänger-Themen 104
T Algorithmus für Index mit min-Wert Java Basics - Anfänger-Themen 2
Düsseldorf2002 Testen meines Algorithmus Java Basics - Anfänger-Themen 1
D Primzahlen Rechner nach Eratostenes von Kyrene Algorithmus Java Basics - Anfänger-Themen 2
KogoroMori21 Frage zum Euklidischen Algorithmus Java Basics - Anfänger-Themen 11
S Algorithmus java searchAll IKey Java Basics - Anfänger-Themen 4
S Algorithmus Datensätze einfügen wenn... Java Basics - Anfänger-Themen 26
KogoroMori21 MergeSort Algorithmus Java Basics - Anfänger-Themen 2
KogoroMori21 Textdatei einlesen im Array (Selection Sort Algorithmus) Java Basics - Anfänger-Themen 3
fendix Compiler-Fehler Algorithmus zur Bestimmung von Primzahlen Java Basics - Anfänger-Themen 7
S Algorithmus (reelle Zahl <65536 von dezimal zu dual) max. 10 Nachkommastellen Java Basics - Anfänger-Themen 4
G Algorithmus Graphen Java Basics - Anfänger-Themen 10
D Input/Output fehlerhafter Algorithmus zum Ersetzen von Array-Werten nach logischem Schema Java Basics - Anfänger-Themen 1
N Selection Algorithmus: Methode wird nicht erkannt (BlueJ) Java Basics - Anfänger-Themen 3
U Meinung zum Dijkstra Algorithmus Java Basics - Anfänger-Themen 6
U Dijkstra Algorithmus Laufzeit Java Basics - Anfänger-Themen 3
L Math.exp also eigenen Algorithmus Java Basics - Anfänger-Themen 2
Kirby.exe Algorithmus entwickeln Java Basics - Anfänger-Themen 37
M Algorithmus Max-Heap? Java Basics - Anfänger-Themen 3
I Labyrinth auf der Basis eines rekursiven Algorithmus Java Basics - Anfänger-Themen 27
CptK Best Practice Algorithmus nach jedem Schritt zum Visualisieren pausieren Java Basics - Anfänger-Themen 3
A Algorithmus effizienter machen Java Basics - Anfänger-Themen 1
V Algorithmus zur fortlaufenden Berechnung des duechscjnt Java Basics - Anfänger-Themen 1
M Dijkstra Algorithmus in Graphen auf mehrere verschiedene Knoten anwenden lassen Java Basics - Anfänger-Themen 11
O Labyrinth Algorithmus Java Basics - Anfänger-Themen 3
G Quicksort Algorithmus Java Basics - Anfänger-Themen 12
S Binäre-Suche Algorithmus Java Basics - Anfänger-Themen 1
D Algorithmus in Pseudocode mit log2(n) Operationen erstellen Java Basics - Anfänger-Themen 3
C Laufzeit eines Sortier-Algorithmus ermitteln Java Basics - Anfänger-Themen 4
H aufgabe java luhn algorithmus Java Basics - Anfänger-Themen 10
A Datenstruktur für Savings Algorithmus und Planung von kleinen Programmierprojekten Java Basics - Anfänger-Themen 1
J Algorithmus für eine Reihe implementieren Java Basics - Anfänger-Themen 2
S Dijkstra Algorithmus funktioniert nicht Java Basics - Anfänger-Themen 4
N Denksportaufgabe durch Algorithmus lösen Java Basics - Anfänger-Themen 2
S Problem mit einem rekursivem FloodFill Algorithmus Java Basics - Anfänger-Themen 62
B Algorithmus Square und Multiply Java Basics - Anfänger-Themen 3
J Algorithmus - Strings auf eigene Reihenfolge miteinander vergleichen Java Basics - Anfänger-Themen 4
D Frage Boyer-Moore Algorithmus Java Basics - Anfänger-Themen 7
M Komplexität Algorithmus Java Basics - Anfänger-Themen 8
H Zeichen im algorithmus Java Basics - Anfänger-Themen 4
B Code Verständnisfragen - FLoyd Warshall Algorithmus Java Basics - Anfänger-Themen 1
B Algorithmus zum entmischen einer Zahlenfolge Java Basics - Anfänger-Themen 15
X Minimax-Algorithmus über alle Kanten möglich? - Kanten darstellen Java Basics - Anfänger-Themen 1
T Algorithmus zur Überprüfung eines binären Suchbaums Java Basics - Anfänger-Themen 2
K Best Practice Algorithmus für Berechnung von Zahlenreihenfolge Java Basics - Anfänger-Themen 12
M Simpler Algorithmus läuft extrem langsam. Java Basics - Anfänger-Themen 3
K Erste Schritte Brute Force Algorithmus Java Basics - Anfänger-Themen 2
L Frage zu BubbleSort Algorithmus Java Basics - Anfänger-Themen 2
B gibt es ein Stundenplan-Algorithmus? Java Basics - Anfänger-Themen 11
O Algorithmus-Problem Java Basics - Anfänger-Themen 5
P Euklidischer Algorithmus Java Basics - Anfänger-Themen 9
L Greates Commong Dividend - euklidischer Algorithmus, modulos not positive Java Basics - Anfänger-Themen 5
J Euklidischer Algorithmus Java Basics - Anfänger-Themen 1
S Quicksort Algorithmus Java Basics - Anfänger-Themen 2
S GraphNode --- Dijkstra Algorithmus : NullPointerException Java Basics - Anfänger-Themen 1
B Rekursive Algorithmus schreiben Java Basics - Anfänger-Themen 8
V Algorithmus in einer Methode ausführen Java Basics - Anfänger-Themen 3
M Implementierung des Knuth-Morris-Pratt-Algorithmus Java Basics - Anfänger-Themen 0
M Dijkstras Algorithmus Java Basics - Anfänger-Themen 5
S Zusammenhang Datenstruktur/Algorithmus Java Basics - Anfänger-Themen 1
M Simulation - Algorithmus Java Basics - Anfänger-Themen 3
F Erste Schritte Hilfe beim Algorithmus finden Java Basics - Anfänger-Themen 8
D Algorithmus für Punkte auf einem Kreis Java Basics - Anfänger-Themen 0
D Algorithmus zu gegebener Laufzeit implementieren Java Basics - Anfänger-Themen 1
B Doppelte Werte aus Array entfernen ohne Import - Algorithmus Java Basics - Anfänger-Themen 5
C Ideen für einen Algorithmus Java Basics - Anfänger-Themen 1
F Best Practice Algorithmus optimieren - Binaeruhr Java Basics - Anfänger-Themen 2
S Euklid Algorithmus zur Berechnung des GGTs Java Basics - Anfänger-Themen 2
L Welcher Algorithmus ist das ? Java Basics - Anfänger-Themen 9
J Rekursiver Horner-Schema-Algorithmus - Verstehe ich ihn richtig? Java Basics - Anfänger-Themen 2
O Java Zufalls-Verteil-Algorithmus Java Basics - Anfänger-Themen 3
P ganz simpler algorithmus Java Basics - Anfänger-Themen 3
C Sortieren ohne Algorithmus Java Basics - Anfänger-Themen 8
J Algorithmus: Grad von floating zu Grad/Minute/Sekunde Java Basics - Anfänger-Themen 3
A Text Verschriebung/Algorithmus(?) Java Basics - Anfänger-Themen 8
R Rekursionsformel für Laufzeit von Algorithmus Java Basics - Anfänger-Themen 3
E Algorithmus für kart. Produkt: als int [] Feld repräsentiert Java Basics - Anfänger-Themen 10
U Peterson Algorithmus Java Basics - Anfänger-Themen 13
algebraiker Collections Bräuchte Hilfe bei dem Algorithmus - LinkedHashMap Java Basics - Anfänger-Themen 2

Ähnliche Java Themen

Neue Themen


Oben