Fragen und Antworten ->"Expertensysteme"

CDW

Moderator
Mitarbeiter
#1
Eingereicht von Ook!
Es geht darum, eine Anwendung zu bauen, die physikalische Fragen beantworten kann. Das Teilgebiet ist frei wählbar (Bewegung, Gravitation, Magnetismus, Relativität, Quantenmechanik oder was euch einfällt). Schön wäre, wenn die Anwendung min. zwei Gebiete abdeckt.
Ein Beispiel für Bewegung wäre:
Ook läuft durchschnittlich 10km/h auf einer Strecke von 5km. Wie lange braucht er für seine Strecke?

Eine Lösungsvariante wäre, dass der Benutzer die drei Daten eingibt:
1. 10km/stunde
2. 5 km
3. ? <Einheit>
Lösung: 0,5 Stunden oder 30 Minuten

Ein weiteres Beispiel für die Angaben:
1. 10km/stunde
2. 30 minuten
3. ? meter
Lösung: 5000 meter
Also: nimm Dir ein Gebiet vor und programmiere eine Anwendung, welche auf diesem Gebiet die Benutzerfragen beantwortet.
Dazu gibt der Benuter natürlich erforderliche Daten ein - und erhält eine Antwort.

Schwierigkeit: beliebig steigbar ;)
Denn: Schwierigkeit1: feste Menüstruktur, Nutzer wählt aus, was er beantwortet haben möchte und das Programm liest erforderliche Daten ein.
Schwierigkteit2: Nutzer gibt Daten ein (unter festen Menüpunkten) und sobald genug Daten eingegeben wurden, werden die Fehlenden ergänzt.
Schwierigkeit3: Nutzer gibt einfach Daten ein wie "5000m" "10km/h" (ohne feste Strukturen mit variablen Messeinheiten)
Schwierigkeit3+: Eingabe in Satzform, Programm erkennt "Absicht" (über Schlüsselworte), Bsp: "Bis zum Bäcker sind es 200m, mein Auto fährt mit 120km/h, wie lange brauche ich?"
 
#2
Erstens kann ich gar nicht verstehen warum zu dieser interessanten Aufgabe niemand etwas gecodet hat, zweitens passen die Anforderungen (Analyse von Zeichenketten und Datenextraktion) ganz gut zu der Thematik, mit der ich mich gerade sowieso beschäftige.
Außerdem wird sich der Punk Entwicklung eines wissenschaftlichen Expertensystems gut in meinem Lebenslauf machen...:wink:

Als ersten Lösungsansatz habe ich eine kleine Java-Anwendung gebaut, die Fragen zur Bewegung & zur elektrischen Leistung beantworten kann. Die Frage kann dabei sowohl ausformuliert eingegeben werden, also z. B.: "Wie schnell fährt ein Auto das 100km in 10h schafft?" oder minimalistisch durch Nennung zweier Werte "100km" und "10h" gestellt werden - die Anwendung würde in beiden Fällen korrekt antworten. Der User muss lediglich darauf achten die Größen in Zahlen anzugeben, die ohne Leerzeichen direkt vor der Einheit stehen. Und der Wert nachdem gefragt wird darf nicht als Abkürzung in der Frage vorkommen.
Also für die Bewegung z.B. 10km oder 10km/h oder 10h
Und für die elektrische Leistung: 10V (Volt) oder 12W (Watt) oder 0.43A (Ampere)
Kommatas sind natürlich als Punkte einzugeben...

Code:
import java.io.*;
import java.util.regex.*;

public class KlugscheisserHaBo 
{//Klasse
    private static void leistung()throws IOException
    {//leistung()
        String frage;
        float P=0, U=0, I=0;
        BufferedReader ein=new BufferedReader(new InputStreamReader(System.in));
        
        System.out.println("Bitte geben Sie Ihre Frage ein:");
        frage=ein.readLine();
        
        //Definition der regulären Ausdrücke zur Mustererkennung
        Pattern leistung=Pattern.compile("([\\d]+)W");
        Pattern spannung=Pattern.compile("([\\d]+)V");
        Pattern strom=Pattern.compile("([\\d]+)A");
        Matcher pMuster=leistung.matcher(frage);
        Matcher uMuster=spannung.matcher(frage);
        Matcher iMuster=strom.matcher(frage);
        
        //Extraktion der Zahlen zur Initalisierung der Variablen
        if(pMuster.find())
        {
            if(pMuster.groupCount()==1)
            {
                P=Float.valueOf(pMuster.group(1));
            }
        }
        if(uMuster.find())
        {
            if(uMuster.groupCount()==1)
            {
                U=Float.valueOf(uMuster.group(1));
            }
        }
        if(iMuster.find())
        {
            if(iMuster.groupCount()==1)
            {
                I=Float.valueOf(iMuster.group(1));
            }
        }
        
        //Berechnen der Antwort
        if(P==0)
        {
            P=Math.round(U*(I/100));
            System.out.println("Die Leistung beträgt: "+P+"Watt\n");
        }
        if(U==0)
        {
            U=Math.round(P/(I/100));
            System.out.println("Die Spannung beträgt: "+U+" Volt\n");
        }
        if(I==0)
        {
            I=Math.round(P/U);
            System.out.println("Die Stromstärke beträgt: "+I+" Ampere\n");
        }
        menue();
    }//leistung()
    private static void bewegung()throws IOException
    {//bewegung()
        String frage;
        float v=0, s=0, t=0;
        BufferedReader ein=new BufferedReader(new InputStreamReader(System.in));
        
        System.out.println("Bitte geben Sie Ihre Frage ein:");
        frage=ein.readLine();
        
        //Definition der regulären Ausdrücke zur Mustererkennung
        Pattern geschwindigkeit=Pattern.compile("([\\d]+)km/h");
        Pattern zeit=Pattern.compile("([\\d]+)h");
        Pattern weg=Pattern.compile("([\\d]+)km(?!/h)");
        Matcher vMuster=geschwindigkeit.matcher(frage);
        Matcher tMuster=zeit.matcher(frage);
        Matcher sMuster=weg.matcher(frage);
        
        //Extraktion der Zahlen zur Initalisierung der Variablen
        if(vMuster.find())
        {
            if(vMuster.groupCount()==1)
            {
                v=Float.valueOf(vMuster.group(1));
            }
        }
        if(tMuster.find())
        {
            if(tMuster.groupCount()==1)
            {
                t=Float.valueOf(tMuster.group(1));
            }
        }
        if(sMuster.find())
        {
            if(sMuster.groupCount()==1)
            {
                s=Float.valueOf(sMuster.group(1));
            }
        }
        
        //Berechnen der Antwort
        if(v==0)
        {
            v=s/t;
            System.out.println("Die Geschwindigkeit beträgt: "+v+" km/h\n");
        }
        if(t==0)
        {
            t=s/v;
            System.out.println("Die Zeitdauer beträgt: "+t+" h\n");
        }
        if(s==0)
        {
            s=v*t;
            System.out.println("Die Strecke beträgt: "+s+" km\n");
        }
        menue();
    }//bewegung()
    private static void menue()throws IOException
    {//menue()
        String auswahl;
        BufferedReader ein=new BufferedReader(new InputStreamReader(System.in));
        
        System.out.println("*** HaBo-Klugscheißer ***");
        System.out.println("1 - Bewegung");
        System.out.println("2 - elektrische Leistung");
        System.out.println("3 - Programm beenden");
        System.out.println("Ihre Wahl?");
        auswahl=ein.readLine();
        
        if(auswahl.equals("1"))
        {
            bewegung();
        }
        else if(auswahl.equals("2"))
        {
            leistung();
        }
        else if(auswahl.equals("3"))
        {
            System.out.println("Programm beendet...");
            System.exit(0);
        }
        else
        {
            System.out.println("Ungültige Eingabe!\n");
            menue();
        }
    }//menue()
    public static void main(String[]args)throws IOException
    {//main()
        menue();
    }//main()
}//Klasse
 
Zuletzt bearbeitet:
#3
Konsolenanwendung in VB.
Da ich von den ganzen anderen Sachen (Magnetismus, Elektrizität, etc.) nicht wirklich viel Ahnung habe (war in Naturwissenschaften leider nie besonders), hab ich als zweite Möglichkeit der Berechnung einen BMI-Rechner eingebaut.
Reihenfolge der Eingaben der Werte ist egal - die Frage kann auch ausformuliert gestellt werden. Einzig die Angabe am Anfang - ob Geschw. oder BMI - ist nötig.
Mehrere Abfragen nacheinander sind möglich.

Code:
Imports System.Console

Module Module1
    Private text As String
    Private text2 As String
    Private kategorie As Integer
    Private nochmal As Char

    Sub Main()
        Do
            WriteLine("Für Bewegungsberechnungen bitte ""std"", ""meter"" oder ""km/h"" nutzen:")
            WriteLine("Für BMI-Berechnungen bitte ""cm"", ""kg"" oder ""bmi"" nutzen:")
            WriteLine("Was möchten Sie berechnen? (1=Geschwindigkeit, 2=BMI)")
            kategorie = CInt(ReadLine())
            WriteLine("Frage eingeben:")
            WriteLine()
            text = ReadLine()


            Select Case Suchen(text, kategorie)
                Case 1
                    text2 = text.Substring(0, text.IndexOf("meter"))
                    Dim meter As Double = CDbl(text2.Substring(text2.LastIndexOf(" ") + 1))
                    text2 = text.Substring(0, text.IndexOf("std"))
                    Dim std As Double = CDbl(text2.Substring(text2.LastIndexOf(" ") + 1))
                    WriteLine(meter & " Meter in " & std & " Stunden entspricht " & (meter / 1000 / std).ToString & "km/h")
                Case 2
                    text2 = text.Substring(0, text.IndexOf("km/h"))
                    Dim kmh As Double = CDbl(text2.Substring(text2.LastIndexOf(" ") + 1))
                    text2 = text.Substring(0, text.IndexOf("std"))
                    Dim std As Double = CDbl(text2.Substring(text2.LastIndexOf(" ") + 1))
                    WriteLine(kmh & "km/h über einen Zeitraum von " & std & " Stunden entspricht einer zurückgelegten Strecke von " & (kmh * std).ToString & " Metern")
                Case 3
                    text2 = text.Substring(0, text.IndexOf("km/h"))
                    Dim kmh As Double = CDbl(text2.Substring(text2.LastIndexOf(" ") + 1))
                    text2 = text.Substring(0, text.IndexOf("meter"))
                    Dim meter As Double = CDbl(text2.Substring(text2.LastIndexOf(" ") + 1))
                    WriteLine("Eine Strecke von " & meter & " Metern wird bei " & kmh & "km/h in " & (meter / 1000 / kmh).ToString & " Stunden (" & (meter / 1000 / kmh * 60).ToString & " Minuten) zurückgelegt")
                Case 4
                    text2 = text.Substring(0, text.IndexOf("cm"))
                    Dim cm As Double = CDbl(text2.Substring(text2.LastIndexOf(" ") + 1))
                    text2 = text.Substring(0, text.IndexOf("kg"))
                    Dim kg As Double = CDbl(text2.Substring(text2.LastIndexOf(" ") + 1))
                    WriteLine("Ihr BMI beträgt: " & (kg / ((cm / 100) ^ 2)).ToString)
                Case 5
                    text2 = text.Substring(0, text.IndexOf("cm"))
                    Dim cm As Double = CDbl(text2.Substring(text2.LastIndexOf(" ") + 1))
                    text2 = text.Substring(0, text.IndexOf("bmi"))
                    Dim bmi As Double = CDbl(text2.Substring(text2.LastIndexOf(" ") + 1))
                    WriteLine("Für einen BMI von " & bmi & " bei " & cm & " cm Körpergröße müssten Sie " & (bmi * ((cm / 100) ^ 2)).ToString & " kg wiegen")
                Case 6
                    text2 = text.Substring(0, text.IndexOf("bmi"))
                    Dim bmi As Double = CDbl(text2.Substring(text2.LastIndexOf(" ") + 1))
                    text2 = text.Substring(0, text.IndexOf("kg"))
                    Dim kg As Double = CDbl(text2.Substring(text2.LastIndexOf(" ") + 1))
                    WriteLine("Für einen BMI von " & bmi & " bei einem Gewicht von " & kg & "kg müssten sie " & ((Math.Sqrt(kg / bmi)) * 100) & "cm groß sein")
            End Select
            WriteLine("Noch eine Berechnung durchführen? (j/n):")
            nochmal = ReadLine()
        Loop While nochmal = "j"

    End Sub

    Private Function Suchen(ByVal text As String, ByVal kategorie As Integer) As Integer
        If kategorie = 1 Then
            If text.IndexOf("km/h") = -1 Then
                Return 1
                Exit Function
            End If
            If text.IndexOf("meter") = -1 Then
                Return 2
                Exit Function
            End If
            If text.IndexOf("std") = -1 Then
                Return 3
                Exit Function
            End If
        Else
            If text.IndexOf("bmi") = -1 Then
                Return 4
                Exit Function
            End If
            If text.IndexOf("kg") = -1 Then
                Return 5
                Exit Function
            End If
            If text.IndexOf("cm") = -1 Then
                Return 6
                Exit Function
            End If
        End If

    End Function

End Module
 
#4
Hey, finde das ist echt ne coole Aufgabe dir du dir da ausgedacht hast;-) Vor allem weil sie so beliebig erweiterbar ist. Da ich im Moment sowieso viel mit Physik zu tun habe, passt mir das eigentlich sehr gut=)
Werde mich in nächster Zeit auch mal an mein "Expertensystem" machen, sehr interessant finde ich die Eingabe als Satz, denn das kann man auch immer weiter verbessern. Mache mich also demnächst mal dran und poste dann erste Lösungen:p

Lg fr33g
 

SchwarzeBeere

Moderator
Mitarbeiter
#6
Nach nunmehr drei Jahren und sieben Monaten wär's aber schon langsam an der Zeit eine Lösung zu posten, meinst du nicht?
Schwierigkeit 1: Feste Zieleinheit ("Was möchten Sie berechnen?") -> Feste Eingabeeinheiten ("Diese Werte werden benötigt") -> Simples Frage/Antwort-System
Schwierigkeit 2: Feste Eingabeeinheiten ("Bitte geben Sie eine beliebige Menge an Daten ein")-> Feste Zieleinheiten ("Sie können folgende Metriken berechnen") -> Erweitertes Frage/Antwort-Spiel
Schwierigkeit 3: Feste Eingabeeinheiten ("Ich möchte mehrere Meter und Beschleunigung eingeben ....") + Feste Zieleinheiten ("... und die Zielgeschwindigkeit und den Abbremsweg bei einer Bremswirkung von 5m/s berechnen") und -> Lösen einer oder mehrerer Gleichungen der Form Kombination(Eingabeeinheiten) = Ausgabeeinheit
Schwierigkeit 3+: Beliebige Eingabeeinheiten ("Ich möchte Meter und Beschleundigung angeben ...") + beliebige Zieleinheiten ("... und eine Formel erhalten, wie weit ich bei einer Schanze mit unbekanntem Winkel fliegen würde") -> Wissenssystem mit NLP ;)
Tipp: Verfeinern könnte man jeden Schwierigkeitgrad noch, indem man die Einheiten nicht vorgibt, sondern einfach nur mit deren Repräsentationen 'm','h',"kg",... rechnet, z.B. "kg" = 1000*'g'

Davon wirst du doch etwas hinbekommen, oder? ;)
 
Zuletzt bearbeitet:
Oben