Suche 'intelligenten' Suchalgorithmus

Für allgemeine Fragen zur Programmierung mit PureBasic.
Little John

Beitrag von Little John »

STARGÅTE hat geschrieben:Das Problem was ich jetzt sehe ist: das man menschliche Verständnis für Ähnlichkeit nicht mit dem Computer-Ähnlich vergleichen kann, es wird wohl nie eine gute Procedure dafür geben ....
Das kann man pauschal nicht unbedingt so sagen. "Computer-Ähnlich" ist ja nicht verbindlich festgelegt. Es kommt halt darauf an, wie ein Programm (verschiedene Grade von) Ähnlichkeit ermittelt. Es ist keineswegs ausgeschlossen, dass jemand dafür einen pfiffigen Algorithmus findet.

Gruß, Little John
DarkDragon
Beiträge: 6291
Registriert: 29.08.2004 08:37
Computerausstattung: Hoffentlich bald keine mehr
Kontaktdaten:

Beitrag von DarkDragon »

gnasen hat geschrieben:stimmt, doch mehr Übereinstimmungen.

Trotzdem müsste der Wert niedriger ausfallen. Es müsste mehr acht auf den Zusammenhang gelegt werden, wie ich schon sagte.

"abcdefg" sollte mit "aertbertcertdertfertgert" also fast nichts mehr zu tun haben (ist jetzt ein übertriebenes Beispiel)
Dann mach es halt quadratisch...

Code: Alles auswählen

AltesResultatInProzent.f = 60.0
NeuesResultatInProzent.f = Pow(AltesResultatInProzent, 2) / 100.0

Debug AltesResultatInProzent
Debug NeuesResultatInProzent
Angenommen es gäbe einen Algorithmus mit imaginärer Laufzeit O(i * n), dann gilt O((i * n)^2) = O(-1 * n^2) d.h. wenn man diesen Algorithmus verschachtelt ist er fertig, bevor er angefangen hat.
Toshy
Beiträge: 713
Registriert: 22.03.2005 00:29
Computerausstattung: Computer und Strom vorhanden
Wohnort: LK Wolfenbüttel

Beitrag von Toshy »

Hi.

Also ich denke Kiffi sucht nicht nach einer Möglichkeit rauszufinden ob sein Suchbegriff einem Text (den Listeneinträgen) ähnlich ist, sondern ob der Suchbegriff oder die "Untermenge des Suchbegriffs" bzw. "alle möglichen kürzeren Teile des SUchbegriffs" darin vorkommen.

Da ich in Kürze was ähnliches Brauche für meine DorfMap habe ich mal grob folgendes gebastelt:

Code: Alles auswählen

;   ;http://www.purebasic.fr/german/viewtopic.php?t=17752

Global NewList TextListe.s()
Structure struct_gefunden
  *pointer
  SuchString.s
EndStructure
Global NewList Gefunden.struct_gefunden()

For i = 1 To 10 ; einfach mal schnell ne Liste erstellen in der gesucht werden kann.
  AddElement(TextListe())
  TextListe() = "123bubuxyz" + ("_") + Str(i)
  AddElement(TextListe())
  TextListe() = "123ubuxyz" + ("_") + Str(i)
  AddElement(TextListe())
  TextListe() = "123bubuxyz" + ("_") + Str(i)
  AddElement(TextListe())
  TextListe() = "123bubxyz" + ("_") + Str(i)
Next i


Procedure Search2(SuchString.s)
  ResetList(TextListe())
  ForEach TextListe()
    Position = FindString(TextListe(), SuchString, 1) 
    If Position > 0
      AddElement(Gefunden())
      Gefunden()\pointer = @TextListe()
      Gefunden()\SuchString = SuchString
      ;Debug Str(Gefunden()\pointer) + ":" + Gefunden()\SuchString
    EndIf
  Next
EndProcedure
Procedure Search(SuchString.s)
  ClearList(Gefunden()) 
  SuchStringCopy.s = SuchString
  For teillaenge = Len(SuchString) To 1 Step -1
    For pos = 1 To (Len(SuchString)-teillaenge)+1
      Search2(Mid(SuchString, pos, teillaenge))
    Next
  Next
EndProcedure
Procedure ClearSearch()
  ;  ResetList(Gefunden())
  SortStructuredList(Gefunden(), #PB_Sort_Ascending , OffsetOf(struct_gefunden\pointer), #PB_Sort_String)
  ForEach Gefunden()
    If Gefunden()\pointer = *OldPointer
     DeleteElement(Gefunden() )
       EndIf
    *OldPointer = Gefunden()\pointer
    Gefunden()\SuchString = ""
  Next
EndProcedure

Search("bubu")
ClearSearch() ; falls nicht interessiert welcher Teilstring zum erfolg führte, so kann man hiermit alle doppelten Einträge löschen. 

ForEach Gefunden()
  ChangeCurrentElement(TextListe(), Gefunden()\pointer)
    Debug Str(Gefunden()\pointer) + " : " + Gefunden()\SuchString + " : " + TextListe()
Next


Delay(10000)
Ist noch nicht so groß getestet, da ich keinen Bock hatte mir hunderte verschiedene Listeneinträge einfallen zu lassen ;-) sollte aber an sich laufen.

Eine Liste beinhaltet die Texte die durchsucht werden sollen, die zweite Liste beinhaltet die Pointer auf die Einträge der ersten Liste in welcher der Suchbegriff (oder Teil davon) vorkommt. Es kann dabei zu Mehrfacheinträgen in der Ergebnissliste kommen, was aber sinnvoll sein kann, wenn man sehen möchte zu welchem Suchbegriff / Suchteil was gefunden wurde (mit Einen Durchlaufe und einer If-Abfrage oder der Sortierungsfunktion kann man die Ausgabe formatieren).
Mit "Clearsearch" kann man die Ergebnissliste schnell aufräumen und es wird jeder Pointer nur noch einmal vorkommen. Man weiß also schnell in welchen Einträgen gefunden wurde.

Die Suche sollte mit jeder Suchwortlänge zurechtkommen. Nur "Leerstrings" könnten Probleme bereiten, da ich da noch keine Sicherheitsabfragen drinn habe.

Ein bissl optiert und angepaßt werden muß also noch.

Ich hoffe es klappt.

Nachtrag:
Für die meißten fälle dürfte das schnell genug sein. erhöht man die Listeneinträge im Beispiel auf 10 000 EInträge so dauert es bei mir ca. 3 Sekunden. Ohne "clearsearch" ne halbe. Das heißt optimieren kann was bringen.
wenn man z.B. ZUERST nach dem Vorkommen der einzelnen Buchstaben schaut (also umgekehrte Suchreihenfolge) und in bestimmten EInträgen diese nicht findet, so kann mana ausschließen das sich längere Suchwörter da drinn befinden und braucht dort nicht mehr zu suchen. Dadurch würde die Suche im Durchschnitt viel schneller gehen. Falls es aussreicht zu wissen ob in einem Eintrag überhaupt ein Suchwortteil vorkommt kann man nach dem ersten Fund ebenfalls diesen Teil aus der Suche rausnehmen (also z.B. in der TExtliste den EIntrag löschen).
Ich denke dem Code läßt sich noch in Bezug auf Tempo um einiges optimieren. Aber das wollte ich nicht machen, denn ich weiß nicht wozu es genau benötigt wird.

Gruß
Toshy
1. Win10
PB6.1
marco2007
Beiträge: 906
Registriert: 26.10.2006 13:19
Kontaktdaten:

Beitrag von marco2007 »

STARGÅTE hat geschrieben:wo wir gerade wieder dabei sind :
was haltet ihr von dieser Procedure :
:allright:
Windows 11 - PB 6.03 x64
_________________________________
c4s
Beiträge: 1235
Registriert: 19.09.2007 22:18

Re: Suche 'intelligenten' Suchalgorithmus

Beitrag von c4s »

Sorry, dass ich diesen alten Thread ausgrabe, aber hierhin passt es immer noch am ehesten: Mir ist soeben aufgefallen, dass STARGÅTEs Code für die beigefügten Beispiele nicht mehr die richtigen Ergebnisse liefert...
Erwünscht hat geschrieben:50,0%
50,0%
71,2%
98,8%
77,8%
48,0%
55,9%
49,6%
Ergebnis mit PB5.11, x86 hat geschrieben:0.25
0.21875
0.3912036716938
0.4938271343708
0.38271605968475
0.33999997377396
0.33136093616486
0.36088153719902
Auch x100 sind es völlig andere Werte. Woran kann das liegen?
"Menschenskinder, das Niveau dieses Forums singt schon wieder!" — GronkhLP ||| "ich hogffe ihr könnt den fehle endecken" — Marvin133 ||| "Ideoten gibts ..." — computerfreak ||| "Jup, danke. Gruss" — funkheld
Kevin
Beiträge: 236
Registriert: 11.06.2007 12:55

Re: Suche 'intelligenten' Suchalgorithmus

Beitrag von Kevin »

c4s hat geschrieben:Sorry, dass ich diesen alten Thread ausgrabe, aber hierhin passt es immer noch am ehesten: Mir ist soeben aufgefallen, dass STARGÅTEs Code für die beigefügten Beispiele nicht mehr die richtigen Ergebnisse liefert...
Erwünscht hat geschrieben:50,0%
50,0%
71,2%
98,8%
77,8%
48,0%
55,9%
49,6%
Ergebnis mit PB5.11, x86 hat geschrieben:0.25
0.21875
0.3912036716938
0.4938271343708
0.38271605968475
0.33999997377396
0.33136093616486
0.36088153719902
Auch x100 sind es völlig andere Werte. Woran kann das liegen?
Hi,

der Code funktioniert nicht im Unicode Modus...
wenn du Zeile 9 änderst geht es wieder:

Code: Alles auswählen

;Chr$ = PeekS(@String(i)+n-1, 1)
Chr$ = PeekS(@String(i)+(n-1)*SizeOf(Character), 1)
mfg
c4s
Beiträge: 1235
Registriert: 19.09.2007 22:18

Re: Suche 'intelligenten' Suchalgorithmus

Beitrag von c4s »

:oops: Danke dir!
"Menschenskinder, das Niveau dieses Forums singt schon wieder!" — GronkhLP ||| "ich hogffe ihr könnt den fehle endecken" — Marvin133 ||| "Ideoten gibts ..." — computerfreak ||| "Jup, danke. Gruss" — funkheld
Antworten