forked from IF-LK-2020/entscheidungsbaum
Initial commit
This commit is contained in:
commit
ce5d70b3a8
|
@ -0,0 +1,26 @@
|
||||||
|
# ---> Java
|
||||||
|
# Compiled class file
|
||||||
|
*.class
|
||||||
|
|
||||||
|
# Log file
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# BlueJ files
|
||||||
|
*.ctxt
|
||||||
|
Dokumente*
|
||||||
|
|
||||||
|
# Mobile Tools for Java (J2ME)
|
||||||
|
.mtj.tmp/
|
||||||
|
|
||||||
|
# Package Files #
|
||||||
|
*.jar
|
||||||
|
*.war
|
||||||
|
*.nar
|
||||||
|
*.ear
|
||||||
|
*.zip
|
||||||
|
*.tar.gz
|
||||||
|
*.rar
|
||||||
|
|
||||||
|
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||||
|
hs_err_pid*
|
||||||
|
|
|
@ -0,0 +1,210 @@
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Materialien zu den zentralen NRW-Abiturpruefungen im Fach Informatik ab 2018
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* Generische Klasse BinaryTree<ContentType>
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* Mithilfe der generischen Klasse BinaryTree koennen beliebig viele
|
||||||
|
* Inhaltsobjekte vom Typ ContentType in einem Binaerbaum verwaltet werden. Ein
|
||||||
|
* Objekt der Klasse stellt entweder einen leeren Baum dar oder verwaltet ein
|
||||||
|
* Inhaltsobjekt sowie einen linken und einen rechten Teilbaum, die ebenfalls
|
||||||
|
* Objekte der generischen Klasse BinaryTree sind.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author Qualitaets- und UnterstuetzungsAgentur - Landesinstitut fuer Schule
|
||||||
|
* @version Generisch_03 2014-03-01
|
||||||
|
*/
|
||||||
|
public class BinaryTree<ContentType> {
|
||||||
|
|
||||||
|
/* --------- Anfang der privaten inneren Klasse -------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Durch diese innere Klasse kann man dafuer sorgen, dass ein leerer Baum
|
||||||
|
* null ist, ein nicht-leerer Baum jedoch immer eine nicht-null-Wurzel sowie
|
||||||
|
* nicht-null-Teilbaeume, ggf. leere Teilbaeume hat.
|
||||||
|
*/
|
||||||
|
private class BTNode<CT> {
|
||||||
|
|
||||||
|
private CT content;
|
||||||
|
private BinaryTree<CT> left, right;
|
||||||
|
|
||||||
|
public BTNode(CT pContent) {
|
||||||
|
// Der Knoten hat einen linken und einen rechten Teilbaum, die
|
||||||
|
// beide von null verschieden sind. Also hat ein Blatt immer zwei
|
||||||
|
// leere Teilbaeume unter sich.
|
||||||
|
this.content = pContent;
|
||||||
|
left = new BinaryTree<CT>();
|
||||||
|
right = new BinaryTree<CT>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------- Ende der privaten inneren Klasse -------------- */
|
||||||
|
|
||||||
|
private BTNode<ContentType> node;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Nach dem Aufruf des Konstruktors existiert ein leerer Binaerbaum.
|
||||||
|
*/
|
||||||
|
public BinaryTree() {
|
||||||
|
this.node = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wenn der Parameter pContent ungleich null ist, existiert nach dem Aufruf
|
||||||
|
* des Konstruktors der Binaerbaum und hat pContent als Inhaltsobjekt und
|
||||||
|
* zwei leere Teilbaeume. Falls der Parameter null ist, wird ein leerer
|
||||||
|
* Binaerbaum erzeugt.
|
||||||
|
*
|
||||||
|
* @param pContent
|
||||||
|
* das Inhaltsobjekt des Wurzelknotens vom Typ ContentType
|
||||||
|
*/
|
||||||
|
public BinaryTree(ContentType pContent) {
|
||||||
|
if (pContent != null) {
|
||||||
|
this.node = new BTNode<ContentType>(pContent);
|
||||||
|
} else {
|
||||||
|
this.node = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wenn der Parameter pContent ungleich null ist, wird ein Binaerbaum mit
|
||||||
|
* pContent als Inhalt und den beiden Teilbaeume pLeftTree und pRightTree
|
||||||
|
* erzeugt. Sind pLeftTree oder pRightTree gleich null, wird der
|
||||||
|
* entsprechende Teilbaum als leerer Binaerbaum eingefuegt. So kann es also
|
||||||
|
* nie passieren, dass linke oder rechte Teilbaeume null sind. Wenn der
|
||||||
|
* Parameter pContent gleich null ist, wird ein leerer Binaerbaum erzeugt.
|
||||||
|
*
|
||||||
|
* @param pContent
|
||||||
|
* das Inhaltsobjekt des Wurzelknotens vom Typ ContentType
|
||||||
|
* @param pLeftTree
|
||||||
|
* der linke Teilbaum vom Typ BinaryTree<ContentType>
|
||||||
|
* @param pRightTree
|
||||||
|
* der rechte Teilbaum vom Typ BinaryTree<ContentType>
|
||||||
|
*/
|
||||||
|
public BinaryTree(ContentType pContent, BinaryTree<ContentType> pLeftTree, BinaryTree<ContentType> pRightTree) {
|
||||||
|
if (pContent != null) {
|
||||||
|
this.node = new BTNode<ContentType>(pContent);
|
||||||
|
if (pLeftTree != null) {
|
||||||
|
this.node.left = pLeftTree;
|
||||||
|
} else {
|
||||||
|
this.node.left = new BinaryTree<ContentType>();
|
||||||
|
}
|
||||||
|
if (pRightTree != null) {
|
||||||
|
this.node.right = pRightTree;
|
||||||
|
} else {
|
||||||
|
this.node.right = new BinaryTree<ContentType>();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Da der Inhalt null ist, wird ein leerer BinarySearchTree erzeugt.
|
||||||
|
this.node = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Diese Anfrage liefert den Wahrheitswert true, wenn der Binaerbaum leer
|
||||||
|
* ist, sonst liefert sie den Wert false.
|
||||||
|
*
|
||||||
|
* @return true, wenn der Binaerbaum leer ist, sonst false
|
||||||
|
*/
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return this.node == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wenn pContent null ist, geschieht nichts. <br />
|
||||||
|
* Ansonsten: Wenn der Binaerbaum leer ist, wird der Parameter pContent als
|
||||||
|
* Inhaltsobjekt sowie ein leerer linker und rechter Teilbaum eingefuegt.
|
||||||
|
* Ist der Binaerbaum nicht leer, wird das Inhaltsobjekt durch pContent
|
||||||
|
* ersetzt. Die Teilbaeume werden nicht geaendert.
|
||||||
|
*
|
||||||
|
* @param pContent
|
||||||
|
* neues Inhaltsobjekt vom Typ ContentType
|
||||||
|
*/
|
||||||
|
public void setContent(ContentType pContent) {
|
||||||
|
if (pContent != null) {
|
||||||
|
if (this.isEmpty()) {
|
||||||
|
node = new BTNode<ContentType>(pContent);
|
||||||
|
this.node.left = new BinaryTree<ContentType>();
|
||||||
|
this.node.right = new BinaryTree<ContentType>();
|
||||||
|
}
|
||||||
|
this.node.content = pContent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Diese Anfrage liefert das Inhaltsobjekt des Binaerbaums. Wenn der
|
||||||
|
* Binaerbaum leer ist, wird null zurueckgegeben.
|
||||||
|
*
|
||||||
|
* @return das Inhaltsobjekt der Wurzel vom Typ ContentType bzw. null, wenn
|
||||||
|
* der Binaerbaum leer ist
|
||||||
|
*/
|
||||||
|
public ContentType getContent() {
|
||||||
|
if (this.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return this.node.content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Falls der Parameter null ist, geschieht nichts. Wenn der Binaerbaum leer
|
||||||
|
* ist, wird pTree nicht angehaengt. Andernfalls erhaelt der Binaerbaum den
|
||||||
|
* uebergebenen BinaryTree als linken Teilbaum.
|
||||||
|
*
|
||||||
|
* @param pTree
|
||||||
|
* neuer linker Teilbaum vom Typ BinaryTree<ContentType>
|
||||||
|
*/
|
||||||
|
public void setLeftTree(BinaryTree<ContentType> pTree) {
|
||||||
|
if (!this.isEmpty() && pTree != null) {
|
||||||
|
this.node.left = pTree;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Falls der Parameter null ist, geschieht nichts. Wenn der Binaerbaum leer
|
||||||
|
* ist, wird pTree nicht angehaengt. Andernfalls erhaelt der Binaerbaum den
|
||||||
|
* uebergebenen BinaryTree als rechten Teilbaum.
|
||||||
|
*
|
||||||
|
* @param pTree
|
||||||
|
* neuer linker Teilbaum vom Typ BinaryTree<ContentType>
|
||||||
|
*/
|
||||||
|
public void setRightTree(BinaryTree<ContentType> pTree) {
|
||||||
|
if (!this.isEmpty() && pTree != null) {
|
||||||
|
this.node.right = pTree;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Diese Anfrage liefert den linken Teilbaum des Binaerbaumes. Wenn der
|
||||||
|
* Binaerbaum leer ist, wird null zurueckgegeben.
|
||||||
|
*
|
||||||
|
* @return linker Teilbaum vom Typ BinaryTree<ContentType> oder null, wenn
|
||||||
|
* der aktuelle Binaerbaum leer ist
|
||||||
|
*/
|
||||||
|
public BinaryTree<ContentType> getLeftTree() {
|
||||||
|
if (!this.isEmpty()) {
|
||||||
|
return this.node.left;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Diese Anfrage liefert den rechten Teilbaum des Binaerbaumes. Wenn der
|
||||||
|
* Binaerbaum (this) leer ist, wird null zurueckgegeben.
|
||||||
|
*
|
||||||
|
* @return rechter Teilbaum vom Typ BinaryTree<ContentType> oder null, wenn
|
||||||
|
* der aktuelle Binaerbaum (this) leer ist
|
||||||
|
*/
|
||||||
|
public BinaryTree<ContentType> getRightTree() {
|
||||||
|
if (!this.isEmpty()) {
|
||||||
|
return this.node.right;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
/**
|
||||||
|
* Blattknoten eines Entscheidungsbaums. Klassifiziert einen Datensatz,
|
||||||
|
* nachdem alle Entscheidungen des Pfades getroffen wurden.
|
||||||
|
*/
|
||||||
|
public class Classification extends DecisionNode {
|
||||||
|
|
||||||
|
// Die Klassifikation als String
|
||||||
|
private String classification;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Erstellt eine Klassifikation
|
||||||
|
*
|
||||||
|
* @param pClassification Name der Klasse (z.B. "Ja" oder "Nein")
|
||||||
|
*/
|
||||||
|
public Classification( String pClassification ) {
|
||||||
|
classification = pClassification;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String decide( Dataset pDataset ) {
|
||||||
|
return classification;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
/**
|
||||||
|
* Ein Datensatz, der vom {@link DecisionTreeBuilder} im Entscheidungsbaum
|
||||||
|
* klassifiziert werden kann.
|
||||||
|
* <p>
|
||||||
|
* Basiert auf einer {@link java.util.HashMap}.
|
||||||
|
*/
|
||||||
|
public class Dataset {
|
||||||
|
|
||||||
|
// Speicher für die Daten
|
||||||
|
private java.util.HashMap<String, String> data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Erzeugt einen leeren Datensatz
|
||||||
|
*/
|
||||||
|
public Dataset() {
|
||||||
|
data = new java.util.HashMap<String, String>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gibt den Wert für ein Attribut in diesem Datensatz zurück oder
|
||||||
|
* <code>null</code>, wenn das Attribut im Datensatz nicht existiert.
|
||||||
|
*
|
||||||
|
* @param pAttribute Name des Attributs.
|
||||||
|
* @return Wert im Datensatz oder <code>null</code>.
|
||||||
|
*/
|
||||||
|
public String get( String pAttribute ) {
|
||||||
|
return data.getOrDefault(pAttribute, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setzt den Wert eines Attributs in diesem Datensatz.
|
||||||
|
*
|
||||||
|
* @param pAttribute Name des Attributs.
|
||||||
|
* @param pValue Neuer Wert des Attributs.
|
||||||
|
*/
|
||||||
|
public void set( String pAttribute, String pValue ) {
|
||||||
|
data.put(pAttribute, pValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
/**
|
||||||
|
* Innerer Knoten eines Entscheidungsbaums. Entscheidet basierend auf
|
||||||
|
* dem Wert eines Attributs eines {@link Dataset Datensatzes}, ob im linken oder
|
||||||
|
* rechten Teilbaum weitergesucht werden muss.
|
||||||
|
* <p>
|
||||||
|
* Da es sich um <em>binäre Entscheidungen</em> handelt wird immer nur der Wert
|
||||||
|
* für den linken Teilbaum angegeben und für alle anderen Werte der rechte
|
||||||
|
* Teilbaum gewählt.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public class Decision extends DecisionNode {
|
||||||
|
|
||||||
|
// Name des Attributs
|
||||||
|
private String attribute;
|
||||||
|
|
||||||
|
// Wert, bei dem links weitergesucht werden soll
|
||||||
|
private String valueLeft;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Erstellt eine binäre Entscheidung.
|
||||||
|
*
|
||||||
|
* @param pAttribute Name des Attributs.
|
||||||
|
* @param pValueLeft Wert, wann im linken Teilbaum weitergesucht werden muss.
|
||||||
|
*/
|
||||||
|
public Decision( String pAttribute, String pValueLeft ) {
|
||||||
|
attribute = pAttribute;
|
||||||
|
valueLeft = pValueLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String decide( Dataset pDataset ) {
|
||||||
|
if( pDataset.get(attribute).equals(valueLeft) ) {
|
||||||
|
return "left";
|
||||||
|
} else {
|
||||||
|
return "right";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
/**
|
||||||
|
* Ein Knoten im Entscheidungsbaum. Knoten sind entweder {@link Decision Entscheidungen}
|
||||||
|
* (innere Knoten) oder {@link Classification Klassifikationen} (Blattknoten).
|
||||||
|
*/
|
||||||
|
public abstract class DecisionNode {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Führt den Test der Entscheidung durch. Die Methode
|
||||||
|
* bekommt den Datensatz als Parameter und gibt einen
|
||||||
|
* von drei Strings zurück:
|
||||||
|
* <ol>
|
||||||
|
* <li>"left": Folge dem linken Teilbaum</li>
|
||||||
|
* <li>"right": Folge dem rechten Teilbaum</li>
|
||||||
|
* <li>Die finale Klassifikation, wenn dies ein Blatt des Baumes ist (z.B. "yes" oder "no")</li>
|
||||||
|
* </ol>
|
||||||
|
*/
|
||||||
|
public abstract String decide( Dataset pDataset );
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,159 @@
|
||||||
|
/**
|
||||||
|
* Enthält einen Entscheidungsbaum und kann {@link Dataset Datensätze} damit
|
||||||
|
* klassifizieren.
|
||||||
|
*/
|
||||||
|
public class DecisionTreeBuilder {
|
||||||
|
|
||||||
|
// Wurzel des Entscheidungsbaums
|
||||||
|
private BinaryTree<DecisionNode> decisionTree;
|
||||||
|
|
||||||
|
public DecisionTreeBuilder() {
|
||||||
|
// Vorbereiten der Klassifikationen (Blätter)
|
||||||
|
BinaryTree<DecisionNode> classYes = new BinaryTree<>(
|
||||||
|
new Classification("ja")
|
||||||
|
);
|
||||||
|
BinaryTree<DecisionNode> classNo = new BinaryTree<>(
|
||||||
|
new Classification("nein")
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/*aufg*
|
||||||
|
// TODO: Hier den Entscheidungsbaum aufbauen.
|
||||||
|
//
|
||||||
|
// Der Baum wird von den Blättern nach "oben" zur Wurzel aufgebaut.
|
||||||
|
// z.B.
|
||||||
|
// BinaryTree<DecisionNode> wind = new BinaryTree<>(
|
||||||
|
// new Decision("wind", "stark"), // Entscheide Merkmal "wind", gehe links bei "stark"
|
||||||
|
// classNo, // Linker Teilbaum
|
||||||
|
// classYes // rechter Teilbaum
|
||||||
|
// );
|
||||||
|
// usw...
|
||||||
|
*aufg*/
|
||||||
|
//ml*
|
||||||
|
BinaryTree<DecisionNode> wind = new BinaryTree<>(
|
||||||
|
new Decision("wind", "stark"),
|
||||||
|
classNo,
|
||||||
|
classYes
|
||||||
|
);
|
||||||
|
BinaryTree<DecisionNode> vorhersage = new BinaryTree<>(
|
||||||
|
new Decision("vorhersage", "sonnig"),
|
||||||
|
wind,
|
||||||
|
classYes
|
||||||
|
);
|
||||||
|
BinaryTree<DecisionNode> feuchtigkeit = new BinaryTree<>(
|
||||||
|
new Decision("feuchtigkeit", "hoch"),
|
||||||
|
classNo,
|
||||||
|
classYes
|
||||||
|
);
|
||||||
|
//*ml
|
||||||
|
// Die Wurzel zuletzt
|
||||||
|
decisionTree = new BinaryTree<>(
|
||||||
|
new Decision("vorhersage", "regnerisch"),
|
||||||
|
feuchtigkeit,
|
||||||
|
vorhersage
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schickt die {@link #getTestdata() Testdaten} durch den Entscheidungsbaum
|
||||||
|
* und gibt die Entscheidungen auf der Kommandozeile aus.
|
||||||
|
*
|
||||||
|
* @see #testDataset(Dataset)
|
||||||
|
*/
|
||||||
|
public void testTestdata() {
|
||||||
|
Dataset[] testdata = getTestdata();
|
||||||
|
for( int i = 0; i < testdata.length; i++ ) {
|
||||||
|
Dataset d = testdata[i];
|
||||||
|
String result = testDataset(d);
|
||||||
|
System.out.printf("(%s, %s, %s, %s) = %s",
|
||||||
|
d.get("vorhersage"), d.get("temperatur"),
|
||||||
|
d.get("feuchtigkeit"), d.get("wind"),
|
||||||
|
result);
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schickt einen Datensatz durch den Entscheidungsbaum und gibt die
|
||||||
|
* Klasse als String zurück.
|
||||||
|
*
|
||||||
|
* @param pDataset Der zu testende Datensatz.
|
||||||
|
* @return Die Klasse, der der Datensatz zugeordnet wurde.
|
||||||
|
*/
|
||||||
|
public String testDataset( Dataset pDataset ) {
|
||||||
|
BinaryTree<DecisionNode> node = decisionTree;
|
||||||
|
|
||||||
|
String result = "";
|
||||||
|
while( result.equals("") || result.equals("left")
|
||||||
|
|| result.equals("right") ) {
|
||||||
|
/*aufg* 1
|
||||||
|
// TODO: Impementiere den Durchlauf durch den Entschiedungsbaum,
|
||||||
|
// indem bei jedem inneren Knoten die Entscheidung getroffen wird,
|
||||||
|
// ob links oder rechts weitergemacht wird.
|
||||||
|
*aufg*/
|
||||||
|
/*aufg* 2
|
||||||
|
// TODO: Impementiere den Durchlauf durch den Entschiedungsbaum,
|
||||||
|
// indem bei jedem inneren Knoten die Entscheidung getroffen wird,
|
||||||
|
// ob links oder rechts weitergemacht wird.
|
||||||
|
|
||||||
|
DecisionNode e = null;
|
||||||
|
result = "???";
|
||||||
|
|
||||||
|
if( result.equals("left") ) {
|
||||||
|
// ...
|
||||||
|
} else if( result.equals("right") ) {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
*aufg*/
|
||||||
|
//ml*
|
||||||
|
DecisionNode e = node.getContent();
|
||||||
|
result = e.decide(pDataset);
|
||||||
|
|
||||||
|
if( result.equals("left") ) {
|
||||||
|
// Im linken Teilbaum weiter
|
||||||
|
node = node.getLeftTree();
|
||||||
|
} else if( result.equals("right") ) {
|
||||||
|
// Im rechten Teilbaum weiter
|
||||||
|
node = node.getRightTree();
|
||||||
|
}
|
||||||
|
//*ml
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Erstellt ein Array mit Test-Datensätzen für den Entscheidungsbaum.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Dataset[] getTestdata() {
|
||||||
|
String[][] testdata = {
|
||||||
|
{"sonnig", "heiß", "hoch", "schwach"},
|
||||||
|
{"sonnig", "heiß", "hoch", "stark"},
|
||||||
|
{"bewölkt", "heiß", "hoch", "schwach"},
|
||||||
|
{"regnerisch", "mild", "hoch", "schwach"},
|
||||||
|
{"regnerisch", "kalt", "normal", "schwach"},
|
||||||
|
{"regnerisch", "kalt", "normal", "stark"},
|
||||||
|
{"bewölkt", "mild", "hoch", "stark"},
|
||||||
|
{"sonnig", "mild", "hoch", "schwach"},
|
||||||
|
{"sonnig", "kalt", "normal", "schwach"},
|
||||||
|
{"regnerisch", "mild", "normal", "schwach"},
|
||||||
|
{"sonnig", "mild", "normal", "stark"},
|
||||||
|
{"bewölkt", "heiß", "normal", "schwach"},
|
||||||
|
{"bewölkt", "kalt", "normal", "stark"},
|
||||||
|
{"regnerisch", "mild", "hoch", "stark"}
|
||||||
|
};
|
||||||
|
|
||||||
|
Dataset[] data = new Dataset[testdata.length];
|
||||||
|
for( int i = 0; i < testdata.length; i++ ) {
|
||||||
|
data[i] = new Dataset();
|
||||||
|
data[i].set("vorhersage", testdata[i][0]);
|
||||||
|
data[i].set("temperatur", testdata[i][1]);
|
||||||
|
data[i].set("feuchtigkeit", testdata[i][2]);
|
||||||
|
data[i].set("wind", testdata[i][3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class DecisionTreeTest {
|
||||||
|
|
||||||
|
private static final String[][] known_data = {
|
||||||
|
{"sonnig", "heiß", "hoch", "schwach", "ja"},
|
||||||
|
{"sonnig", "heiß", "hoch", "stark", "nein"},
|
||||||
|
{"bewölkt", "heiß", "hoch", "schwach", "ja"},
|
||||||
|
{"regnerisch", "mild", "hoch", "schwach", "nein"},
|
||||||
|
{"regnerisch", "kalt", "normal", "schwach", "ja"},
|
||||||
|
{"regnerisch", "kalt", "normal", "stark", "ja"},
|
||||||
|
{"bewölkt", "mild", "hoch", "stark", "ja"},
|
||||||
|
{"sonnig", "mild", "hoch", "schwach", "ja"},
|
||||||
|
{"sonnig", "kalt", "normal", "schwach", "ja"},
|
||||||
|
{"regnerisch", "mild", "normal", "schwach", "ja"},
|
||||||
|
{"sonnig", "mild", "normal", "stark", "nein"},
|
||||||
|
{"bewölkt", "heiß", "normal", "schwach", "ja"},
|
||||||
|
{"bewölkt", "kalt", "normal", "stark", "ja"},
|
||||||
|
{"regnerisch", "mild", "hoch", "stark", "nein"}
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final String[][] unknown_data = {
|
||||||
|
{"regnerisch", "heiß", "hoch", "schwach", "nein"},
|
||||||
|
{"sonnig", "kalt", "hoch", "stark", "nein"}
|
||||||
|
};
|
||||||
|
|
||||||
|
private DecisionTreeBuilder tree;
|
||||||
|
|
||||||
|
private Dataset[] known_datasets, unknown_datasets;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
known_datasets = new Dataset[known_data.length];
|
||||||
|
for( int i = 0; i < known_data.length; i++ ) {
|
||||||
|
known_datasets[i] = new Dataset();
|
||||||
|
known_datasets[i].set("vorhersage", known_data[i][0]);
|
||||||
|
known_datasets[i].set("temperatur", known_data[i][1]);
|
||||||
|
known_datasets[i].set("feuchtigkeit", known_data[i][2]);
|
||||||
|
known_datasets[i].set("wind", known_data[i][3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
unknown_datasets = new Dataset[unknown_data.length];
|
||||||
|
for( int i = 0; i < unknown_data.length; i++ ) {
|
||||||
|
unknown_datasets[i] = new Dataset();
|
||||||
|
unknown_datasets[i].set("vorhersage", unknown_data[i][0]);
|
||||||
|
unknown_datasets[i].set("temperatur", unknown_data[i][1]);
|
||||||
|
unknown_datasets[i].set("feuchtigkeit", unknown_data[i][2]);
|
||||||
|
unknown_datasets[i].set("wind", unknown_data[i][3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
tree = new DecisionTreeBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testKnownData() {
|
||||||
|
for( int i = 0; i < known_datasets.length; i++ ) {
|
||||||
|
String result = tree.testDataset(known_datasets[i]);
|
||||||
|
assertEquals(known_data[i][4], result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUnknownData() {
|
||||||
|
for( int i = 0; i < unknown_datasets.length; i++ ) {
|
||||||
|
String result = tree.testDataset(unknown_datasets[i]);
|
||||||
|
assertEquals(unknown_data[i][4], result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
Dies ist die README-Datei des Projekts. Hier sollten Sie Ihr Projekt
|
||||||
|
beschreiben.
|
||||||
|
Erzählen Sie dem Leser (jemand, der nichts über dieses Projekt weiss),
|
||||||
|
alles, was er/sie wissen muss. Üblicherweise sollte der Kommentar
|
||||||
|
zumindest die folgenden Angaben umfassen:
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
|
||||||
|
PROJEKTBEZEICHNUNG:
|
||||||
|
PROJEKTZWECK:
|
||||||
|
VERSION oder DATUM:
|
||||||
|
WIE IST DAS PROJEKT ZU STARTEN:
|
||||||
|
AUTOR(EN):
|
||||||
|
BENUTZERHINWEISE:
|
|
@ -0,0 +1,91 @@
|
||||||
|
#BlueJ package file
|
||||||
|
dependency1.from=DecisionNode
|
||||||
|
dependency1.to=Dataset
|
||||||
|
dependency1.type=UsesDependency
|
||||||
|
dependency2.from=Classification
|
||||||
|
dependency2.to=Dataset
|
||||||
|
dependency2.type=UsesDependency
|
||||||
|
dependency3.from=Decision
|
||||||
|
dependency3.to=Dataset
|
||||||
|
dependency3.type=UsesDependency
|
||||||
|
dependency4.from=DecisionTreeBuilder
|
||||||
|
dependency4.to=BinaryTree
|
||||||
|
dependency4.type=UsesDependency
|
||||||
|
dependency5.from=DecisionTreeBuilder
|
||||||
|
dependency5.to=DecisionNode
|
||||||
|
dependency5.type=UsesDependency
|
||||||
|
dependency6.from=DecisionTreeBuilder
|
||||||
|
dependency6.to=Classification
|
||||||
|
dependency6.type=UsesDependency
|
||||||
|
dependency7.from=DecisionTreeBuilder
|
||||||
|
dependency7.to=Decision
|
||||||
|
dependency7.type=UsesDependency
|
||||||
|
dependency8.from=DecisionTreeBuilder
|
||||||
|
dependency8.to=Dataset
|
||||||
|
dependency8.type=UsesDependency
|
||||||
|
editor.fx.0.height=722
|
||||||
|
editor.fx.0.width=800
|
||||||
|
editor.fx.0.x=388
|
||||||
|
editor.fx.0.y=50
|
||||||
|
objectbench.height=66
|
||||||
|
objectbench.width=1201
|
||||||
|
package.divider.horizontal=0.6
|
||||||
|
package.divider.vertical=0.8983286908077994
|
||||||
|
package.editor.height=622
|
||||||
|
package.editor.width=1078
|
||||||
|
package.editor.x=39
|
||||||
|
package.editor.y=24
|
||||||
|
package.frame.height=776
|
||||||
|
package.frame.width=1241
|
||||||
|
package.numDependencies=8
|
||||||
|
package.numTargets=6
|
||||||
|
package.showExtends=true
|
||||||
|
package.showUses=true
|
||||||
|
project.charset=UTF-8
|
||||||
|
readme.height=58
|
||||||
|
readme.name=@README
|
||||||
|
readme.width=47
|
||||||
|
readme.x=10
|
||||||
|
readme.y=10
|
||||||
|
target1.height=40
|
||||||
|
target1.name=Classification
|
||||||
|
target1.showInterface=false
|
||||||
|
target1.type=ClassTarget
|
||||||
|
target1.width=210
|
||||||
|
target1.x=40
|
||||||
|
target1.y=460
|
||||||
|
target2.height=50
|
||||||
|
target2.name=Decision
|
||||||
|
target2.showInterface=false
|
||||||
|
target2.type=ClassTarget
|
||||||
|
target2.width=190
|
||||||
|
target2.x=300
|
||||||
|
target2.y=460
|
||||||
|
target3.height=120
|
||||||
|
target3.name=BinaryTree
|
||||||
|
target3.showInterface=false
|
||||||
|
target3.type=ClassTarget
|
||||||
|
target3.width=440
|
||||||
|
target3.x=890
|
||||||
|
target3.y=250
|
||||||
|
target4.height=40
|
||||||
|
target4.name=Dataset
|
||||||
|
target4.showInterface=false
|
||||||
|
target4.type=ClassTarget
|
||||||
|
target4.width=270
|
||||||
|
target4.x=430
|
||||||
|
target4.y=30
|
||||||
|
target5.height=50
|
||||||
|
target5.name=DecisionNode
|
||||||
|
target5.showInterface=false
|
||||||
|
target5.type=AbstractTarget
|
||||||
|
target5.width=110
|
||||||
|
target5.x=210
|
||||||
|
target5.y=290
|
||||||
|
target6.height=60
|
||||||
|
target6.name=DecisionTreeBuilder
|
||||||
|
target6.showInterface=false
|
||||||
|
target6.type=ClassTarget
|
||||||
|
target6.width=270
|
||||||
|
target6.x=580
|
||||||
|
target6.y=230
|
Loading…
Reference in New Issue