Sunday, March 29, 2009

GUI tree

/*
* Attribute.java
* Copyright (C) 1999 Pierre Geurts
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

import java.io.*;

abstract class Attribute{
/* the name of the attributes */
String name;
/* the database of the attributes */
Database db;
/* attribute index in the database */
int index;
/* the lastbestscore of this attribute */
double lastbestscore;

public Object Value(Obj o) {
return o.attributesvalues.elementAt(index);
}
abstract void SetAttValue(Obj o,Object s);
public String toString() {
return name;
}
abstract String describe();
abstract String describeBestTest();
abstract int ReadAttValue(Obj o,StreamTokenizer stt);
// compute the best score we can obtain with this attribute
abstract double bestscore(ObjectSet os, SymbAtt goal);
// effectively compute the partition resulting from this best score
abstract Partition bestpartition(ObjectSet os, SymbAtt goal);
}
----------------------

/*
* BuildDt.java
* Copyright (C) 1999 Pierre Geurts
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

import java.util.*;
import java.net.*;

/**
* examples:
* java buildDt database/omib.db security 700
* java buildDt database/iris.db class 100
* java buildDt database/color.db color 1500
*/
public class BuildDt {
public static void main(String args[]){
if (args.length<3) {
System.out.println("usage : database goal learning_set_size [entthres stopthres]");
return;
}
/* creation of a database */
Database db = new Database();

System.out.println("Database loading:");
try {
db.loadDb(new URL(args[0]));
} catch (Exception e) {
System.out.println("database file not found");
return;
}
if (db.objects.size==0) {
System.out.println("no object");
return;
}
ObjectSet ls=db.objects.selectRandom(Integer.parseInt(args[2]));
ObjectSet ts=db.objects.selectNotIn(ls);

// select the goal attribute
Attribute goal=db.findAttribute(args[1]);
if (goal==null) {
System.out.println("goal attribute not found");
return;
}

// select all candidate attributes
Vector ca=db.getCandidateAttributes(args[1]);
if (ca.size()==0) {
System.out.println("no candidate attributes");
return;
}

double entthres=0.0;
double stopthres=2.0;
if (args.length>=4) {
entthres=(new Double(args[3])).doubleValue();
}
if (args.length>=5) {
stopthres=(new Double(args[4])).doubleValue();
}
DecisionTree dt=new DecisionTree(db, ls, ca, (SymbAtt)goal,entthres,stopthres);
dt.buildDt();
dt.printDt();
System.out.println("ls errors : " + 100.0*dt.testDt(ls) + "%");
System.out.println("ts errors : " + 100.0*dt.testDt(ts) + "%");
}
}




---------------------------

/*
* 1.1 version.
*/

import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;

/*
* This displays a framed area. When the user clicks within
* the area, this program displays a dot and a string indicating
* the coordinates where the click occurred.
*/

public class CoordinatesDemo extends Applet {
FramedArea framedArea;
Label label;

public void init() {
GridBagLayout gridBag = new GridBagLayout();
GridBagConstraints c = new GridBagConstraints();

setLayout(gridBag);

framedArea = new FramedArea(this);
c.fill = GridBagConstraints.BOTH;
c.weighty = 1.0;
c.gridwidth = GridBagConstraints.REMAINDER; //end row
gridBag.setConstraints(framedArea, c);
add(framedArea);

label = new Label("Click within the framed area.");
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1.0;
c.weighty = 0.0;
gridBag.setConstraints(label, c);
add(label);
}

public void updateLabel(Point point) {
label.setText("Click occurred at coordinate ("
+ point.x + ", " + point.y + ").");
}
}

/* This class exists solely to put a frame around the coordinate area. */
class FramedArea extends Panel {
public FramedArea(CoordinatesDemo controller) {
super();

//Set layout to one that makes its contents as big as possible.
setLayout(new GridLayout(1,0));

add(new CoordinateArea(controller));
}

public Insets getInsets() {
return new Insets(4,4,5,5);
}

public void paint(Graphics g) {
Dimension d = getSize();
Color bg = getBackground();

g.setColor(bg);
g.draw3DRect(0, 0, d.width - 1, d.height - 1, true);
g.draw3DRect(3, 3, d.width - 7, d.height - 7, false);
}
}

class CoordinateArea extends Canvas {
Point point = null;
CoordinatesDemo controller;

public CoordinateArea(CoordinatesDemo controller) {
super();
this.controller = controller;

addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
int x = e.getX();
int y = e.getY();
if (point == null) {
point = new Point(x, y);
} else {
point.x = x;
point.y = y;
}
repaint();
}
});
}

public void paint(Graphics g) {
//If user has chosen a point, paint a tiny rectangle on top.
if (point != null) {
controller.updateLabel(point);
g.fillRect(point.x - 1, point.y - 1, 2, 2);
}
}
}
-----------------------------------------

/*
* Database.java
* Copyright (C) 1999 Pierre Geurts
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

import java.util.*;
import java.io.*;
import java.net.*;

public class Database{
/* the name of the database */
String name;
/* the filename from which the database has been loaded */
String filename;
/* the set of objects */
ObjectSet objects=new ObjectSet();
/* the vector of atttributes */
Vector attributes=new Vector();

/* method to add an object */
public int addObjToDb(Obj o) {
objects.addElement(o);
return objects.size-1;
}

/* method to add an attribute */
public int addAttToDb(Attribute att){
attributes.addElement(att);
return attributes.size()-1;
}

/* a short description of the database */
public String toString(){
StringBuffer s=new StringBuffer();
s.append(name);
s.append(" o(");
s.append(objects.size);
s.append(") a(");
s.append(attributes.size());
s.append(")");
return s.toString();
}

/* to "pretty" print the content of the database */
public void printDb() {
System.out.println(toString());
System.out.print("Object ");
for (int i=0;
ii++) {
System.out.print(((Attribute)attributes.
elementAt(i)).
toString() + " ");
}

System.out.println("");
for (int i=0; i Obj o=(Obj)objects.elementAt(i);
System.out.print(o.toString() + " ");
for (int j=0; j System.out.print(o.attributesvalues.elementAt(j).toString());
System.out.print(" ");
}
System.out.println("");
}
}

/* utilities */
private static void skipBlankLines(StreamTokenizer stt) throws IOException {
while (stt.ttype==stt.TT_EOL)
stt.nextToken();
}

/* loading of a database from a file */
/* return 1 if there is an error, 0 otherwise */
public int loadDb (URL u) {
boolean objectname=false;
int objectnameindex=0;
filename=u.toString();
try {
// URL u=new URL(fn);
URLConnection urlConnection=u.openConnection();
urlConnection.connect();

InputStream in=urlConnection.getInputStream();
BufferedReader r=new BufferedReader(new InputStreamReader(in));
StreamTokenizer stt=new StreamTokenizer(r);
/* some streamtokenizer inititialisations*/
stt.lowerCaseMode(false);
stt.parseNumbers();
stt.eolIsSignificant(true);
stt.commentChar(';');
stt.wordChars('$','$');
stt.wordChars('_','_');
/* file reading */
stt.nextToken();
skipBlankLines(stt);

/**************************
* read the database name *
**************************/
if (stt.ttype==stt.TT_WORD)
name=stt.sval;
else {
System.out.println("the database name must be a symbol");
return 1;
}
stt.nextToken();
skipBlankLines(stt);

/*******************************
* read attributes declaration *
*******************************/
int nreadvalue=0;
int natt=0;
while (stt.ttype!=stt.TT_EOL) {
String attname;
String atttype;
if (stt.ttype!=stt.TT_WORD) {
System.out.println("error in attribute declaration");
return 1;
}
attname=stt.sval;
stt.nextToken();
if (stt.ttype!=stt.TT_WORD) {
System.out.println("error in attribute declaration");
return 1;
}
atttype=stt.sval;
if (atttype.equals("name") || atttype.equals("NAME")) {
if (!objectname) {
objectname=true;
objectnameindex=nreadvalue;
} else {
System.out.println("error in attribute declaration");
return 1;
}
} else {
if (atttype.equals("symbolic") || atttype.equals("SYMBOLIC"))
new SymbAtt(attname,this);
else if (atttype.equals("numerical") || atttype.equals("NUMERICAL"))
new NumAtt(attname,this);
else {
System.out.println("not recognised attribute type");
return 1;
}
natt++;
}
nreadvalue++;
stt.nextToken();
}
System.out.println("" + natt + " attributes have been read");
System.out.println(attributes.toString());

/**************************
* read objects definitions *
**************************/

int exactnatt=natt;
int nobject=1;
while(stt.ttype!=stt.TT_EOF) {
skipBlankLines(stt);
/* number of readed values*/
nreadvalue=0;
/* number of readed attributes (as nreadvalue but
without the object name) */
natt=0;
Obj o;
if (objectname)
o=new Obj("",this);
else
o=new Obj("O" + nobject,this);
nobject++;

/* read attributes values */
while(stt.ttype!=stt.TT_EOL && stt.ttype!=stt.TT_EOF) {
if (objectname==true &&
objectnameindex==nreadvalue &&
nreadvalue==objectnameindex) {
if (stt.ttype==stt.TT_WORD) {
o.name=stt.sval;
nreadvalue++;
} else {
System.out.println("Object name must be a string");
return 1;
}
} else {
if (((Attribute)attributes.elementAt(natt)).ReadAttValue(o,stt)
==1) {
System.out.println("objet " + nobject + " value " + nreadvalue);
return 1;
}
natt++;
nreadvalue++;
}
stt.nextToken();
}
if (natt System.out.println("Attribute values are missing");
return 1;
}
skipBlankLines(stt);
}
System.out.println("" + (nobject-1) + " objects have been read");
// System.out.println(objects.toString());
in.close();
}
catch (Exception e){
System.err.println(e);
}
return 0;
}

/* a method to find an attribute by its name */
public Attribute findAttribute(String name) {
int as=attributes.size();
for (int i=0; i Attribute a=(Attribute)attributes.elementAt(i);
if (name.equals(a.name))
return a;
}
return null;
}

/* a method to find all attributes except one */
public Vector getCandidateAttributes(String goal) {
int as=attributes.size();
Attribute a;
Vector result=new Vector();
for (int i=0; i a=(Attribute)attributes.elementAt(i);
if (!goal.equals(a.name)) {
result.addElement(a);
}
}
return result;
}

/* a method to find a object by its name */
public Obj findObject(String name) {
int os=objects.size;
for (int i=0; i Obj o=(Obj)objects.elementAt(i);
if (name.equals(o.name))
return o;
}
return null;
}
}
----------------------------

/*
* DbReader.java
* Copyright (C) 1999 Pierre Geurts
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

import java.io.*;

public class DbReader {
private static void skipBlankLines(StreamTokenizer stt) throws IOException {
while (stt.ttype==stt.TT_EOL)
stt.nextToken();
}
/* return 1 if there is an error, 0 otherwise */
public static int loadDb (Database db, String filename) {
boolean objectname=false;
int objectnameindex=0;
try {
File f=new File(filename);
Reader in=new FileReader(f);
StreamTokenizer stt=new StreamTokenizer(in);
/* some streamtokenizer initialisations*/
stt.lowerCaseMode(true);
stt.parseNumbers();
stt.eolIsSignificant(true);
stt.commentChar(';');
/* file reading */
stt.nextToken();
skipBlankLines(stt);

/*******************************
* read attributes declaration *
*******************************/
int nreadvalue=0;
int natt=0;
while (stt.ttype!=stt.TT_EOL) {
String attname;
String atttype;
if (stt.ttype!=stt.TT_WORD) {
System.out.println("error in attribute declaration");
return 1;
}
attname=stt.sval;
stt.nextToken();
if (stt.ttype!=stt.TT_WORD) {
System.out.println("error in attribute declaration");
return 1;
}
atttype=stt.sval;
if (attname.equals("object")) {
if (!objectname) {
objectname=true;
objectnameindex=nreadvalue;
} else {
System.out.println("error in attribute declaration");
return 1;
}
} else {
if (atttype.equals("symbolic"))
new SymbAtt(attname,db);
else if (atttype.equals("numerical"))
new NumAtt(attname,db);
else {
System.out.println("not recognised attribute type");
return 1;
}
natt++;
}
nreadvalue++;
stt.nextToken();
}
System.out.println("" + natt + " attributes have been read");
System.out.println(db.attributes.toString());

/**************************
* read objects definitions *
**************************/

int exactnatt=natt;
int nobject=1;
while(stt.ttype!=stt.TT_EOF) {
skipBlankLines(stt);
/* number of readed values*/
nreadvalue=0;
/* number of readed attributes (as nreadvalue but
without the object name) */
natt=0;
Obj o;
if (objectname)
o=new Obj("",db);
else
o=new Obj("O" + nobject,db);
nobject++;

/* read attributes values */
while(stt.ttype!=stt.TT_EOL && stt.ttype!=stt.TT_EOF) {
if (objectname==true &&
objectnameindex==nreadvalue &&
nreadvalue==objectnameindex) {
if (stt.ttype==stt.TT_WORD) {
o.name=stt.sval;
nreadvalue++;
} else {
System.out.println("Object name must be a string");
return 1;
}
} else {
if (((Attribute)db.attributes.elementAt(natt)).ReadAttValue(o,stt)
==1) {
return 1;
}
natt++;
nreadvalue++;
}
stt.nextToken();
}
if (natt System.out.println("Attribute values are missing");
return 1;
}
skipBlankLines(stt);
}
System.out.println("" + nobject + " objects have been read");
System.out.println(db.objects.toString());
in.close();
}
catch (IOException e){
System.err.println(e);
}
return 0;
}
}

----------------------------------

/*
* DecisionTree.java
* Copyright (C) 1999 Pierre Geurts
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

import java.util.*;

public class DecisionTree {
/* problem definition */
Database db;
ObjectSet LearningSet;
Vector CandAttributes;
SymbAtt goal;

/* parameter */
double EntropyThres=0;
double ScoreThres=0;

/* root node */
DtNode root;

/* stack of open node */
Stack openNodes=new Stack();

/* Ordered attributes list for the current node */
Vector CurrentNodeAtt;

/**
* create a trivial tree with the default parameters values
*/
DecisionTree(Database d, ObjectSet ls, Vector CandAtt, SymbAtt g) {
db=d;
LearningSet=ls;
CandAttributes=CandAtt;
goal=g;
DtNode.nbnodes=0;
root=new DtNode(LearningSet, g);
root.graphnode=new WNode("open", null, null, null, null, 0, 0, 0, root);
root.graphnode.selected=true;
// openNodes.push(root);
}

/**
* create a trivial tree with the user's parameter values
*/
DecisionTree(Database d, ObjectSet ls, Vector CandAtt, SymbAtt g,
double et, double st) {
EntropyThres=et;
ScoreThres=st;
db=d;
LearningSet=ls;
CandAttributes=CandAtt;
goal=g;
DtNode.nbnodes=0;
root=new DtNode(LearningSet, g);
root.graphnode=new WNode("open", null, null, null, null, 0, 0, 0, root);
root.graphnode.selected=true;
// openNodes.push(root);
}

/**
* build completely the decision tree
*/
public void buildDt() {
// we search this tree for all the remaining open nodes
getOpenNodes();
// then we build the tree
while(!openNodes.empty()) {
expandTopNode();
}
}

/**
* expand the node on the top of stack always with the best choice
*/
public void expandTopNode() {
DtNode topnode=(DtNode)openNodes.pop();
scanNode(topnode);
Vector result=topnode.split(CurrentNodeAtt,0,goal);
//-- we put the successors on the top of the stack (in reverse order)
if (result!=null) {
for (int i=result.size()-1; i>=0; i--) {
openNodes.push(result.elementAt(i));
}
}
}

/**
* scan the attributes for the top node
*/
public Vector scanNode(DtNode topnode) {
CurrentNodeAtt=topnode.scanAttributes(CandAttributes, goal, EntropyThres, ScoreThres);
/* build a vector of textual description of candidate tests */
Vector result=new Vector();
for (int i=0; i result.addElement(((Attribute)CurrentNodeAtt.elementAt(i)).describeBestTest());
result.addElement(CurrentNodeAtt.lastElement());
return result;
}

/**
* split the top node according to the choice in the CurrentNodeAtt
* Vector
*/
public DtNode splitNode(DtNode topnode, int choice) {
Vector result=topnode.split(CurrentNodeAtt,choice,goal);
if (result!=null) {
// we return the first successor
return (DtNode)result.elementAt(0);
} else {
// otherwise, we return the leftmost open node
return getLeftMostOpenNode();
}
}

/**
* get all the open nodes of the tree (needed because the user can
* now open the node by himself)
*/
public void getOpenNodes() {
openNodes.removeAllElements();
root.getOpenNodes(openNodes);
}

/**
* look for the leftmost open node in the tree
* (this is used after splitting to find the next node to split)
*/

public DtNode getLeftMostOpenNode() {
return root.getLeftMostOpenNode();
}

/**
* get a description of the current open node
*/
public String getNodeDescription(DtNode node) {
return node.getNodeDescription(goal);
}

/**
* propagate this object across the tree and get the associated class
*/
public String Propagate(Obj o) {
return root.getClass(o);
}

/**
* test the dt on an objectset
*/
public double testDt(ObjectSet ts) {
String treeclass, trueclass;
int nberrors=0;
for (int i=0; i treeclass=Propagate(ts.elementAt(i));
trueclass=(String)goal.Value(ts.elementAt(i));
if (!trueclass.equals(treeclass))
nberrors++;
}
System.out.println("nb of errors : " + nberrors + " out of " + ts.size);
return 1.0*nberrors/ts.size;
}

/**
* test the tree using cross-validation
* argument - the number of subsets into which
* the data base must be divided
*/
public double testDtCrossvalidation(int tssize) {
DecisionTree dt;
int n=LearningSet.size/tssize;
Vector tsvector=new Vector();
ObjectSet remainingobjects=LearningSet;
System.out.println("");
System.out.println("Cross validation : " + n + ", LS : "
+ (LearningSet.size-tssize) + " , TS: " +
tssize);
System.out.println("");

// we construct the set of test sets
for (int i=0; i ObjectSet os=remainingobjects.selectRandom(tssize);
tsvector.addElement(os);
remainingobjects=remainingobjects.selectNotIn(os);
}

// we construct the trees
double result=0;
for (int i=0; i System.out.println("");
System.out.println("Tree number " + (i+1));
System.out.println("");
ObjectSet ts=(ObjectSet)tsvector.elementAt(i);
dt=new DecisionTree(db, LearningSet.selectNotIn(ts),
CandAttributes, goal,
EntropyThres, ScoreThres);
dt.buildDt();
result+=dt.testDt(ts);
}

// we return the average
return result/n;
}

public void printDt() {
System.out.println(root.printNode(0));
}
}
----------------------------

/*
* DecisionTreeApplet.java
* Copyright (C) 1999 Pierre Geurts
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.net.*;
import java.io.*;

/**
* Displays the tree building process
*/
public class DecisionTreeApplet extends Applet
implements ActionListener,ItemListener, Runnable
{
/* Following are workarounds for font size calculations, as Netscape
* reports unappealing font height/ascents on varying platforms. */
static final int FIXED_FONT_HEIGHT = 10;
static final int FIXED_FONT_ASCENT = 3;

boolean running;
Thread t;
WNode root;
WalTreeCanvas tc;
SimpleNodeDrawer snd;
DetailedNodeDrawer dnd;

/* decision tree data */
Database db;
DecisionTree CurrentDt;
DtNode CurrentDtn;
ObjectSet ls;
ObjectSet ts;

Button btn_scan; // scan the attribute
Button btn_split; // split one node (if it is still possible)
Button btn_build; // build the tree
Button btn_refresh; // refresh the graph (actually not useful)
Label lbl_zoom=new Label("Zoom", Label.RIGHT);
Button btn_zoominc;
Button btn_zoomdec;
Choice AttChoice; // selection list for the best attribute
String messagechoice="Click 'Scan Attributes' to see the choices";

TextField tf_opennode=new TextField(); // description of the current node

// input parameters
Panel top=new Panel();
Label lbl_database=new Label("Database url : ", Label.RIGHT);
TextField tf_database= new TextField(65); // to enter the file name
Button btn_loaddb=new Button("Load Database");
// to restart with a new database
Label lbl_goal=new Label("Goal Attribute : ", Label.RIGHT); // goal attribute
Choice GoalAttributeChoice; // a choice list for the goal attribute (only the symbolic)
// (at the same time, it displays all the attribute)
Label lbl_candatt=new Label("Candidate attributes : ");
java.awt.List lst_candatt; // a selection list for the candidate attributes

// learning set selection
Label lbl_learningset=new Label("Learning set :", Label.RIGHT);
Label lbl_lssize=new Label("size :", Label.RIGHT);
TextField tf_lssize=new TextField(5);
Label lbl_lsmode=new Label("Selection mode:", Label.RIGHT);
Choice SelectionChoiceLs;

// tree parameters
Label lbl_entthres=new Label("Entropy Threshold : ", Label.RIGHT);
TextField tf_entthres=new TextField(4);
Label lbl_scorethres=new Label("Inf X LS size Threshold : ", Label.RIGHT);
TextField tf_scorethres= new TextField(4);
double default_scorethres=0.0;
double default_entthres=0.0;

// start tree button
Button btn_starttree=new Button("New Tree");

// test parameters
Label lbl_testset=new Label("Test set :", Label.RIGHT);
Label lbl_tssize=new Label("size :", Label.RIGHT);
TextField tf_tssize=new TextField(5);
Label lbl_tsmode=new Label("Selection mode:", Label.RIGHT);
Choice SelectionChoiceTs;
TextField tf_testresult=new TextField(20);
Button btn_testtree;
Button btn_crossvalidation;

// panels
Panel t_p0=new Panel(new GridLayout(3,1,0,0));
Panel t_loaddb=new Panel(new FlowLayout(FlowLayout.CENTER,5,0));
Panel t_p1=new Panel(new FlowLayout(FlowLayout.CENTER,5,0));
Panel t_p2=new Panel(new FlowLayout(FlowLayout.CENTER,5,0));
Panel t_p3=new Panel(new FlowLayout(FlowLayout.CENTER,5,0));
Panel t_p4=new Panel(new FlowLayout(FlowLayout.CENTER,5,0));
Panel t_p5=new Panel(new BorderLayout());

Panel b_p1=new Panel(new FlowLayout(FlowLayout.CENTER,5,0));
Panel b_p2=new Panel(new FlowLayout(FlowLayout.CENTER,5,0));
Panel b_p3=new Panel(new FlowLayout(FlowLayout.CENTER,5,0));
Panel b_p4=new Panel(new FlowLayout(FlowLayout.CENTER,5,0));
Panel bottom=new Panel();
ScrollPane sp=new ScrollPane();
CheckboxGroup treedrawer=new CheckboxGroup();
Checkbox chk_simple=new Checkbox("Simple",treedrawer,true);
Checkbox chk_detailed=new Checkbox("Detailed",treedrawer,false);

/**
* Initialize the applet.
*/
public void init ()
{
super.init();
String str;

setLayout(new BorderLayout());

t_loaddb.add(lbl_database);
t_loaddb.add(tf_database);
t_loaddb.add(btn_loaddb);
t_p1.add(lbl_goal);
t_p1.add(GoalAttributeChoice=new Choice());
t_p2.add(lbl_entthres);
t_p2.add(tf_entthres);
t_p3.add(lbl_scorethres);
t_p3.add(tf_scorethres);
t_p4.add(lbl_learningset);
t_p4.add(lbl_lssize);
t_p4.add(tf_lssize);
t_p4.add(lbl_lsmode);
t_p4.add(SelectionChoiceLs=new Choice());
t_p4.add(btn_starttree);
SelectionChoiceLs.add("Random");
SelectionChoiceLs.add("First");
SelectionChoiceLs.add("Last");
t_p5.add(lbl_candatt,"North");
t_p5.add(lst_candatt=new java.awt.List(5,true),"Center");
t_p0.add(t_p1) ; t_p0.add(t_p2) ; t_p0.add(t_p3);
top.setLayout(new BorderLayout());
top.add(t_loaddb, "North");
top.add(t_p0, "West");
top.add(t_p5,"Center");
top.add(t_p4,"South");

// center : the tree canvas
sp.add(tc=new WalTreeCanvas());

// bottom : control of the building process
bottom.setLayout(new GridLayout(4,1,0,0));
b_p1.add(tf_opennode=new TextField(100));
tf_opennode.setEditable(false);
bottom.add(b_p1);
b_p3.add(AttChoice=new Choice());
bottom.add(b_p3);
b_p2.add(btn_scan=new Button("Scan attributes"));
b_p2.add(btn_split=new Button("Split"));
b_p2.add(btn_build=new Button("Build"));
b_p2.add(chk_simple);
b_p2.add(chk_detailed);
b_p2.add(btn_refresh=new Button("Refresh"));
b_p2.add(lbl_zoom);
b_p2.add(btn_zoominc=new Button("+"));
b_p2.add(btn_zoomdec=new Button("-"));
bottom.add(b_p2);

b_p4.add(lbl_testset);
b_p4.add(lbl_tssize);
b_p4.add(tf_tssize);
b_p4.add(lbl_tsmode);
b_p4.add(SelectionChoiceTs=new Choice());
SelectionChoiceTs.add("Not in ls");
SelectionChoiceTs.add("Random");
SelectionChoiceTs.add("First");
SelectionChoiceTs.add("Last");
SelectionChoiceTs.add("Learning set");
b_p4.add(btn_testtree=new Button("Test tree"));
b_p4.add(btn_crossvalidation=new Button("Cross Validation"));
b_p4.add(tf_testresult);
tf_testresult.setEditable(false);
bottom.add(b_p4);

add(top, "North");
add(bottom, "South");
add(sp, "Center");

snd=new SimpleNodeDrawer(tc);
dnd=new DetailedNodeDrawer(tc);
tc.nd=snd;

tc.setParentDistance(30);

// load the database
if (getParameter("DBFILE")!=null) {
URL u;
try {
u=new URL(getDocumentBase(), getParameter("DBFILE"));
initDb(u);
} catch (MalformedURLException e) {
System.out.println("-- database file not found");
showStatus("Bad url");
}

}

// different actions binding
// buttons
btn_split.addActionListener(this);
btn_refresh.addActionListener(this);
btn_scan.addActionListener(this);
btn_starttree.addActionListener(this);
btn_testtree.addActionListener(this);
btn_crossvalidation.addActionListener(this);
btn_build.addActionListener(this);
btn_loaddb.addActionListener(this);
btn_zoominc.addActionListener(this);
btn_zoomdec.addActionListener(this);
// check button
chk_simple.addItemListener(this);
chk_detailed.addItemListener(this);
// selection list
SelectionChoiceTs.addItemListener(this);
// mouse
MyMouseListener ml=new MyMouseListener();
tc.addMouseListener(ml);
}

public void loadDb() {
URL u;
try {
u=new URL(tf_database.getText());
initDb(u);
tc.setTree(root);
tc.repaint();
} catch (MalformedURLException e) {
System.out.println("-- database file not found");
showStatus("Bad url");
}
}

public void initDb(URL u) {
db = new Database();
System.out.println("Database loading:");
showStatus("Loading database");

if (db.loadDb(u)==1) {
showStatus("Loading failed : bad file format");
return;
}

tf_database.setText(u.toString());

if (db.objects.size==0) {
System.out.println("no object");
}

//-- fill candidate attribute selection list
lst_candatt.removeAll();
GoalAttributeChoice.removeAll();

int last_symb=0;
for (int i=0; i Attribute att=(Attribute)db.attributes.elementAt(i);
lst_candatt.add(att.describe());
lst_candatt.select(i);
if (att instanceof SymbAtt) {
GoalAttributeChoice.add(att.toString());
last_symb=i;
}
}
GoalAttributeChoice.select(GoalAttributeChoice.getItemCount()-1);
lst_candatt.deselect(last_symb);

//-- initialise score and entropy threshold
tf_entthres.setText("" + default_entthres);
tf_scorethres.setText("" + default_scorethres);

//-- initialise ls size and type
tf_lssize.setText("" + (int)(2*db.objects.size/3));
SelectionChoiceLs.select(0);
tf_tssize.setText("" + (int)(db.objects.size/3));
SelectionChoiceTs.select(0);
AttChoice.add(messagechoice);
AttChoice.select(0);

//-- initialise the tree
root=null;

//-- garbage collecting after this (to remove the previous database)
System.gc();

showStatus("done");
setComment("");
}

public void NewTree() {
//-- learning set selection
int lssize=GetLsSize();
int lsmode=GetLsMode();
if (lsmode==0)
ls=db.objects.selectRandom(lssize);
else if (lsmode==1)
ls=db.objects.selectFirst(lssize);
else if (lsmode==2)
ls=db.objects.selectLast(lssize);

//-- we build a trivial tree
CurrentDt=new DecisionTree(db, ls, GetCandAtt(), GetGoalAttribute(),
GetEntThres(), GetScoreThres());
CurrentDtn=CurrentDt.root;
root=CurrentDt.root.graphnode;

//-- we initialise the graphical interface
setComment(CurrentDt.getNodeDescription(CurrentDtn));
AttChoice.removeAll();
AttChoice.add(messagechoice);
AttChoice.select(0);
refreshcurrenttree();
}

/**
* some functions to get the parameters value
*/
public Vector GetCandAtt() {
int[] index=lst_candatt.getSelectedIndexes();
if (index.length==0)
return new Vector();
Vector result=new Vector();
for (int i=0; i result.addElement(db.attributes.elementAt(index[i]));
}
return result;
}

public SymbAtt GetGoalAttribute() {
return (SymbAtt)db.findAttribute(GoalAttributeChoice.getSelectedItem());
}

public double GetEntThres() {
return (new Double(tf_entthres.getText())).doubleValue();
}

public double GetScoreThres() {
return (new Double(tf_scorethres.getText())).doubleValue();
}

public int GetLsSize() {
if (tf_lssize.getText()=="")
return 0;
else
return Integer.parseInt(tf_lssize.getText());
}

public int GetLsMode() {
return SelectionChoiceLs.getSelectedIndex();
}

public int GetTsSize() {
if (tf_lssize.getText()=="")
return 0;
else
return Integer.parseInt(tf_tssize.getText());
}

public int GetTsMode() {
return SelectionChoiceTs.getSelectedIndex();
}

public void setComment(String t) {
tf_opennode.setText(t);
}

/**
* Start the main applet thread.
*/
public void start ()
{
running = true;
t = new Thread(this);
t.start();
}

/**
* Stop the applet.
*/
public void stop ()
{
running = false;
}

/**
* Main event loop.
*/
public void run () { }

/**
* scan all the attributes at the top node for the best attribute.
* display the result into the choice list.
*/
public void Scanatt() {

if (CurrentDtn==null)
return;

Vector choices=CurrentDt.scanNode(CurrentDtn);
AttChoice.removeAll();
for (int i=0; i AttChoice.add((String)choices.elementAt(i));
}

/**
* Split the current node
*
*/
public void SplitMore() {

if (CurrentDtn==null)
return;

if (CurrentDtn.type!="open") {
// if the node is not open, we open it
CurrentDtn.open();
}

if (AttChoice.getItem(0)==messagechoice) {
//-- the user has not asked for attributes scanning
CurrentDt.scanNode(CurrentDtn);
changeSelectedNode(CurrentDt.splitNode(CurrentDtn,0));
} else {
//-- we take into account the user's choice
changeSelectedNode(CurrentDt.splitNode(CurrentDtn,AttChoice.getSelectedIndex()));
}
refreshcurrenttree();
}

public void changeSelectedNode(DtNode dtn) {
if (CurrentDtn!=null)
CurrentDtn.graphnode.selected=false;
if (AttChoice.getItem(0)!=messagechoice) {
AttChoice.removeAll();
AttChoice.add(messagechoice);
AttChoice.select(0);
}
CurrentDtn=dtn;
if (CurrentDtn!=null) {
CurrentDtn.graphnode.selected=true;
setComment(CurrentDt.getNodeDescription(CurrentDtn));
} else {
setComment("");
}
}

public void buildalltree() {
showStatus("Building the tree...");
CurrentDt.buildDt();
changeSelectedNode(null);
refreshcurrenttree();
CurrentDt.printDt();
showStatus("done");
}

public void testtree() {
//-- learning set selection
showStatus("Testing the tree...");
int tssize=GetTsSize();
int tsmode=GetTsMode();
if (tsmode==0)
ts=db.objects.selectNotIn(ls);
else if (tsmode==1)
ts=db.objects.selectRandom(tssize);
else if (tsmode==2)
ts=db.objects.selectFirst(tssize);
else if (tsmode==3)
ts=db.objects.selectLast(tssize);
else if (tsmode==4)
ts=ls;
String result="" + CurrentDt.testDt(ts)*100;
if (result.length()<5)
tf_testresult.setText("" + result + "%");
else
tf_testresult.setText("" + result.substring(0,5) + "%");
showStatus("done");
}

public void CrossValidation() {
showStatus("Cross validation...please wait");
double result=CurrentDt.testDtCrossvalidation(GetTsSize());
String sr="" + result*100;
if (sr.length()<5)
tf_testresult.setText(sr + "%");
else
tf_testresult.setText(sr.substring(0,5) + "%");
showStatus("done");
}

public void actionPerformed(ActionEvent event) {
String command=event.getActionCommand();

if (command=="Split" && root!=null) {
SplitMore();
} else if (command=="Build" && root!=null) {
buildalltree();
} else if (command=="Scan attributes" && root!=null) {
Scanatt();
} else if (command=="Refresh" && root!=null) {
refreshcurrenttree();
} else if (command=="Test tree" && root!=null) {
testtree();
} else if (command=="New Tree") {
NewTree();
} else if (command=="Load Database") {
loadDb();
} else if (command=="Cross Validation" && root!=null) {
CrossValidation();
} else if (command=="+") {
snd.increaseZoom();
dnd.increaseZoom();
tc.repaint();
} else if (command=="-") {
snd.decreaseZoom();
dnd.decreaseZoom();
tc.repaint();
}
}

public void refreshcurrenttree() {
if (root==null)
return;
tc.nd.computeNodeSize(root);
tc.setTree(root);
tc.repaint();
}

public void itemStateChanged(ItemEvent event) {
String command=(String)event.getItem();

if (command == "Simple") {
tc.nd=snd;
refreshcurrenttree();
} else if (command == "Detailed") {
tc.nd=dnd;
if (root!=null) {
dnd.initWidth(root);
refreshcurrenttree();
}
} else if (command == "Not in ls") {
tf_tssize.setText("" + (db.objects.size - Integer.parseInt(tf_lssize.getText())));
} else if (command == "Learning set") {
tf_tssize.setText(tf_lssize.getText());
}
}

/* gestion de la souris */
class MyMouseListener extends MouseAdapter {
public void mousePressed(MouseEvent e) {
int x=e.getX();
int y=e.getY();
if (root!=null) {
DtNode dtn=root.getPointedNode((int)(x/tc.nd.zoom),(int)(y/tc.nd.zoom));
if (dtn!=null) {
// select this node
changeSelectedNode(dtn);
// retrace the graph (there must exist a better way to do this)
tc.repaint();
}
}
}
}
}
-------------------------

/*
* DetailedNodeDrawer.java
* Copyright (C) 1999 Pierre Geurts
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

import java.awt.*;
import java.util.*;

/**
* a abstract class to allow many representation for
* a node
*/

public class DetailedNodeDrawer extends NodeDrawer {

FontMetrics metrics_small,metrics_big, metrics_current;
Font smallfont, bigfont;
int SMALL_FIXED_FONT_HEIGHT=8;
int BIG_FIXED_FONT_HEIGHT=14;
int current_font_height;
int default_border=10;
Vector colours=new Vector();
int max_width=60;
int max_height=40;
int max_ls_size=1;
double coef;
Canvas cv;

DetailedNodeDrawer(Canvas c) {
cv=c;
bigfont=new Font("Helvetica", Font.PLAIN, BIG_FIXED_FONT_HEIGHT);
c.setFont(bigfont);
metrics_big=c.getFontMetrics(c.getFont());

smallfont=new Font("Helvetica", Font.PLAIN, SMALL_FIXED_FONT_HEIGHT);
c.setFont(smallfont);
metrics_small=c.getFontMetrics(c.getFont());

metrics_current=metrics_small;
current_font_height=SMALL_FIXED_FONT_HEIGHT;

coef=Math.exp(1)*20;
colours.addElement(Color.black);
colours.addElement(Color.red);
colours.addElement(Color.green);
colours.addElement(Color.blue);
colours.addElement(Color.orange);
colours.addElement(Color.darkGray);
colours.addElement(Color.cyan);
colours.addElement(Color.gray);
colours.addElement(Color.magenta);
colours.addElement(Color.pink);
colours.addElement(Color.black);
colours.addElement(Color.yellow);
colours.addElement(Color.white);
colours.addElement(Color.red);
colours.addElement(Color.green);
colours.addElement(Color.blue);
colours.addElement(Color.orange);
colours.addElement(Color.darkGray);
colours.addElement(Color.cyan);
colours.addElement(Color.gray);
colours.addElement(Color.magenta);
colours.addElement(Color.pink);
colours.addElement(Color.black);
colours.addElement(Color.yellow);
colours.addElement(Color.white);
}

public void initWidth(WNode t) {
t.width=0;
if (t.sibling!=null) {
initWidth(t.sibling);
}
if (t.child!=null) {
initWidth(t.child);
}
}

public void computeNodeSize(WNode t) {
max_ls_size=t.dtnode.subset.size;
computeSize(t);
}

public void computeSize(WNode t) {
if (t.width==0) { //-- we compute the size only once
double correction;
if (t.dtnode.subset.size!=0)
correction=Math.log(coef)/Math.log(coef*max_ls_size/t.dtnode.subset.size);
else
correction=Math.log(coef)/Math.log(coef*max_ls_size);
t.height=(int)(max_width*correction);
t.width=(int)(max_height*correction);
}

t.border=default_border;

if (t.sibling!=null) {
computeSize(t.sibling);
}

if (t.child!=null) {
computeSize(t.child);
}
}

public void drawArc(Graphics g, int x1, int y1, int x2,
int y2, String arclabel) {
g.setColor(Color.black);
g.drawLine((int)(x1*zoom), (int)(y1*zoom), (int)(x2*zoom),(int)(y2*zoom));
g.drawString(arclabel,
(int)(((x1 + x2)*zoom - metrics_current.stringWidth(arclabel)) / 2),
(int)((y1 + y2)*zoom/2));
}

public void drawNode(Graphics g, WNode t) {
int tposx=(int)(t.pos.x*zoom);
int tposy=(int)(t.pos.y*zoom);
int tw=(int)(t.width*zoom);
int th=(int)(t.height*zoom);

int current_x=tposy*t.dtnode.subset.size;
int incr_x;
int y=tposx;

//-- draw the box
if (t.dtnode.subset.size!=0) {
for (int i=0; i if (t.dtnode.subset.summary[i]!=0) {
incr_x=th*t.dtnode.subset.summary[i];
g.setColor((Color)colours.elementAt(i+1));
g.fillRect((int)(current_x/t.dtnode.subset.size),y,
(int)(incr_x/t.dtnode.subset.size)+1,tw);
current_x+=incr_x;
}
}
}

g.setColor(Color.black);
g.drawRect(tposy, tposx, th, tw);

//-- we highlight the current open node
if (t.selected) {
g.setColor(Color.pink);
g.drawRect(tposy-current_font_height, tposx-current_font_height,
th+2*current_font_height, tw+2*current_font_height);
}

//-- we put information beneath the box ...
String bottomtext;
if (t.dtnode.type.equals("test"))
bottomtext=t.label;
else if (t.dtnode.type.equals("open"))
bottomtext="open";
else if (t.dtnode.type.equals("open"))
bottomtext="leaf : " + t.dtnode.majclass;
else
bottomtext="error";

g.setColor(Color.black);
g.drawString(t.label,
tposy + (th - metrics_current.stringWidth(t.label)) / 2,
tposx + tw + current_font_height);

//-- ... and on top of the box
g.drawString(t.dtnode.name, tposy, tposx+1);

}

// increase the zoom
public void increaseZoom() {
if (zoom==0.5)
zoom=0.7;
else if (zoom==0.7)
zoom=1.0;
else if (zoom==1.0)
zoom=1.2;
else if (zoom==1.2) {
zoom=1.5;
metrics_current=metrics_big;
current_font_height=BIG_FIXED_FONT_HEIGHT;
cv.setFont(bigfont);
} else if (zoom==1.5)
zoom=2.0;
else if (zoom==2.0)
zoom=2.5;
else if (zoom==2.5)
zoom=3.0;
}

// decrease the zoom
public void decreaseZoom() {
if (zoom==3.0)
zoom=2.5;
else if (zoom==2.5)
zoom=2.0;
else if (zoom==2.0)
zoom=1.5;
else if (zoom==1.5) {
zoom=1.2;
metrics_current=metrics_small;
current_font_height=SMALL_FIXED_FONT_HEIGHT;
cv.setFont(smallfont);
} else if (zoom==1.2)
zoom=1.0;
else if (zoom==1.0)
zoom=0.7;
else if (zoom==0.7)
zoom=0.5;
}
}
----------------------------------

/*
* DtNode.java
* Copyright (C) 1999 Pierre Geurts
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

import java.util.*;

public class DtNode {
static int nbnodes;
ObjectSet subset;
String type="open"; // leaf, test or open
String majclass="default"; // the majority class in this node
String name;
WNode graphnode; // for the tree visualisation

Test test;
Vector successors;

DtNode(ObjectSet s, SymbAtt goal) {
subset=s;
name="node" + nbnodes++;
ComputeInfoNode(goal);
}

/**
* Compute some information about this node (entropy, subset summary
* and class maj). This should be call when the node is created.
*/
public void ComputeInfoNode(SymbAtt goal) {
subset.computeEntropy(goal);
majclass=subset.getMajClass(goal);
}

/**
* Scan all the cancidate attributes, compute the information gain of the
* best score. Return a vector of attributes ordered by decreasing values
* of information.
*/
public Vector scanAttributes(Vector ca, SymbAtt goal, double entthres, double scorethres) {
Vector result=new Vector();

System.out.println("expanding " + getNodeDescription(goal));

//-- no object in this node (this should never happen)
if (subset.size==0) {
result.addElement("No object in this node -> a leaf");
return result;
}

//-- entropy is low enough, we can stop splitting this node
if (subset.entropy<=entthres) {
result.addElement("Entropy low enough (threshold=" +
entthres + ") -> a leaf");
return result;
}

//-- in the other case, we scan the attributes
// System.out.println("number of candidate attributes : " + ca.size());
System.out.print("[");
double score;
int i=0,j=0;
Attribute att;
for (; i System.out.print("."); // on point per attribute
att=(Attribute)ca.elementAt(i);
score=att.bestscore(subset,goal);
// System.out.println(att.name + " " + score);
//-- the score must be greater than the threshold (forward pruning)
if ((score*subset.size)>scorethres) {
j=0;
while (j score<=((Attribute)result.elementAt(j)).lastbestscore)
j++;
if (j==result.size())
result.addElement(att);
else
result.insertElementAt(att,j);
}
}
System.out.println("]");

//-- we always let the possibility to user to make this node a leaf
result.addElement("make this node a leaf");
return result;
}

public Vector split(Vector scanresult, int choice, SymbAtt goal) {

//-- make this node a leaf
if (choice==scanresult.size()-1) {
System.out.println((String)scanresult.elementAt(choice));
type="leaf";
buildGraphLeafNode(goal);
return null;
}

//-- we take the attribute and construct the partition
Attribute selectedatt=(Attribute)scanresult.elementAt(choice);
Partition partition=selectedatt.bestpartition(subset,goal);
test=partition.test;
successors=new Vector();
type="test";
System.out.println("-> a test node (score : " + selectedatt.lastbestscore +
" , test : " + test.TestDescription + ")");

//-- we create the successor nodes
for (int i=0; i successors.addElement(new DtNode((ObjectSet)partition.sets.elementAt(i),
goal));
}

//-- we create the graphnodes
buildGraphTestNodes();

//- we return the successors (open nodes)
return successors;
}

/**
* expand this node and return a vector of open nodes resulting from
* the expansion
*/
public Vector expand(Vector ca, SymbAtt goal, double entthres, double scorethres) {

//-- if the subset is empty, this is a leaf and the class is default
if (subset.size==0) {
System.out.println("-> a leaf (no objects)");
majclass="default";
type="leaf";
buildGraphLeafNode(goal);
return null;
}

System.out.println("expanding " + getNodeDescription(goal));

//-- if the entropy is lower than the threshold, then we stop the splitting
if (subset.entropy<=entthres) { // a new leaf
System.out.println("-> a leaf (entropy low, " + subset.entropy
+ "<=" + entthres + ")");
type="leaf";
buildGraphLeafNode(goal);
return null;
}

//-- otherwise, we screen all the attributes
double bestscore=0,score;
Attribute bestatt=null,att;
System.out.print("[");
for (int i=0; i System.out.print(".");
att=(Attribute)ca.elementAt(i);
score=att.bestscore(subset,goal);
if (score>bestscore) {
bestscore=score;
bestatt=att;
}
}
System.out.println("]");

//-- the best score must be greater than the threshold (stop-splitting rule)
if ((bestscore*subset.size)<=scorethres) {
System.out.println("-> a leaf (score too low, "
+ (bestscore*subset.size) + "<=" +
scorethres + ")");
type="leaf";
buildGraphLeafNode(goal);
return null;
}

//-- we construct the partition of the learning set
Partition partition=bestatt.bestpartition(subset,goal);
test=partition.test;
successors=new Vector();
type="test";
System.out.println("-> a test node (score : " + bestscore +
" , test : " + test.TestDescription + ")");

//-- we create the successor nodes
for (int i=0; i successors.addElement(new DtNode((ObjectSet)partition.sets.elementAt(i),
goal));
}

//-- we create the graphnodes
buildGraphTestNodes();

//-- we return the successors (open node)
return successors;
}

/**
* complete the graphnode for a leaf
*/
public void buildGraphLeafNode(SymbAtt goal) {
graphnode.label=majclass;
if (majclass.equals("default")) {
graphnode.colour=0;
} else {
graphnode.colour=goal.values.indexOf(majclass)+1;
}
}

/**
* build the graphnodes for the successors of this node
*/
public void buildGraphTestNodes() {
//-- first we put the label of this node (the size will be computed afterwards)
graphnode.label=test.TestDescription;

//-- then the first successor
DtNode dtchild=(DtNode)successors.elementAt(0);
dtchild.graphnode=new WNode("open", (String)test.valuesIssues.elementAt(0),
graphnode, null, null,0,0,0,dtchild);
graphnode.child=dtchild.graphnode;
WNode previousgchild=dtchild.graphnode;
DtNode nextdtchild;

//-- and finally the others
for (int i=1; i nextdtchild=(DtNode)successors.elementAt(i);
nextdtchild.graphnode=new WNode("open", (String)test.valuesIssues.elementAt(i),
graphnode,null,null,0,0,0,nextdtchild);
previousgchild.sibling=nextdtchild.graphnode;
previousgchild=nextdtchild.graphnode;
}
}

/**
* open a node (destroy all his successors and tests)
*/
public void open() {
test=null;
type="open";
graphnode.child=null;
graphnode.colour=0;
graphnode.label="open";
}


/**
* get all the open nodes of this subtree (in a depth first way but
* in the oposite direction (right to left and bottom to top)
*/
public void getOpenNodes(Stack opennodes) {
if (type.equals("open"))
opennodes.push(this);
else if (successors!=null) {
for (int i=successors.size()-1; i>=0; i--) {
((DtNode)successors.elementAt(i)).getOpenNodes(opennodes);
}
}
}

/**
* get the leftmost open node
*/
public DtNode getLeftMostOpenNode() {
if (type.equals("open"))
return this;
else if (successors!=null) {
for (int i=0; i DtNode dtn=((DtNode)successors.elementAt(i)).getLeftMostOpenNode();
if (dtn!=null)
return dtn;
}
return null;
} else
return null;
}

/**
* return the class associated to this object by the subtree corresponding
* to this node
*/
public String getClass(Obj o) {
if (type.equals("leaf") || type.equals("open"))
return majclass;
else
return ((DtNode)successors.elementAt(test.TestIndex(o))).getClass(o);
}

/**
* give a textual description of this node
*/
public String getNodeDescription(SymbAtt goal) {
String s="";
s+=name;
s+=" - LS : " + subset.getSummaryString(goal);
s+=" - ENTROPY : " + subset.entropy;
return s;
}

/**
* print n spaces (to pretty print the decision tree)
*/
private String printNtab(int n) {
String result="";
for (int i=0; i result+=" ";
}
return result;
}

/**
* print a textual description of the subtree corresponding
* to this node.
*/
public String printNode(int depth) {
String result="";
if (type.equals("leaf") || type.equals("open")) {
result+=printNtab(depth);
result+="return \"" + majclass + "\";\n";
} else if (type.equals("test")) {
for (int i=0; i result+=printNtab(depth);
if (i!=0)
result+="} else ";
result+="if (" + test.testDescription(i) + ") {\n";
result+=((DtNode)successors.elementAt(i)).printNode(depth+1);
}
result+=printNtab(depth) + "}\n";
} else {
System.out.println("printNode - bad node type");
return "";
}
return result;
}
}

-------------------------------

/*
* Entropy.java
* Copyright (C) 1999 Pierre Geurts
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

import java.io.*;

/* this class contains some functions to calculate
* entropy values
*/
public class Entropy{
static double entropy(int freq[], int size, int sum) {
// when we don't have example then the entropy is zero
if (sum==0)
return 0.0;
double result=sum*java.lang.Math.log(sum);
for (int i=0; i if (freq[i]!=0)
result-=freq[i]*java.lang.Math.log(freq[i]);
}
result/=java.lang.Math.log((double)2.0);
result/=sum;
return result;
}
}
-------------------------

/*
* NodeDrawer.java
* Copyright (C) 1999 Pierre Geurts
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

import java.awt.*;
import java.util.*;

/**
* a abstract class to allow many representation for
* a node
*/

public abstract class NodeDrawer {
double zoom=1.0;

abstract void computeNodeSize(WNode t);
abstract void drawNode(Graphics g, WNode t);
abstract void drawArc(Graphics g, int x1, int y1, int x2,
int y2, String arclabel);
abstract void increaseZoom();
abstract void decreaseZoom();
}
--------------------------


/*
* NumAtt.java
* Copyright (C) 1999 Pierre Geurts
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

import java.io.*;
import java.util.*;

public class NumAtt extends Attribute{
/* le domaine de l'attribut dans la bd */
float rangemin=(float)1.0, rangemax=(float)0.0;
/* le meilleur score precedemment obtenu par cet attribut */
float bestthreshold;

NumAtt(String s, Database dab) {
name=s;
db=dab;
index=db.addAttToDb(this);
}
public void SetAttValue(Obj o,Object f) {
float fl=((Float)f).floatValue();
if (rangemin>rangemax) {
rangemin=fl;
rangemax=fl;
} else {
if (fl rangemin=fl;
else if (fl>rangemax)
rangemax=fl;
}
o.attributesvalues.setElementAt(f,index);
}
public int ReadAttValue(Obj o, StreamTokenizer stt) {
if (stt.ttype==stt.TT_NUMBER) {
SetAttValue(o,new Float(stt.nval));
return 0;
} else {
System.out.println("A numerical value was expected");
return 1;
}
}

public String describe() {
return toString()+ " - numerical - range : [" + rangemin + "," + rangemax + "]";
}

public String describeBestTest() {
return toString() + " - threshold : " + bestthreshold + " - Information gain : " +
lastbestscore;
}

/* return the best partition for a numerical attribute
* we assume that the best threshold is already computed (by
* using bestscore
*/
public Partition bestpartition(ObjectSet os, SymbAtt goal) {
TestNum t=new TestNum(this,bestthreshold);
Vector v=os.splitOn(t);
return new Partition(t,v);
}

/* searches the best threshold value for a numerical attribute
* assumes that the objectset size is greater than 0
*/
public double bestscore(ObjectSet os, SymbAtt goal) {
// first, the set is ordered by increasing attribute values
os.orderOn(this);

// then prepare the data, we suppose that we have already
// computed the entropy value
int gvs=goal.values.size();
int freqyes[]=new int[gvs+1];
int freqno[]=new int[gvs+1];
// in the beginning, the test is false for all objects
for (int i=0; i freqno[i]=os.summary[i];
}
freqno[gvs]=os.size;
float currentthreshold=rangemin;
double bestscore=0,actualscore=os.entropy;
double entyes,entno;
int ico;
int iconext=goal.values.indexOf(goal.Value((Obj)os.elementAt(0)));
float av;
float avnext=((Float)Value((Obj)os.elementAt(0))).floatValue();

for (int i=0; i // index of the class for this object
ico=iconext;
iconext=goal.values.indexOf(goal.Value((Obj)os.elementAt(i+1)));
av=avnext;
avnext=((Float)Value((Obj)os.elementAt(i+1))).floatValue();
freqno[ico]--;freqno[gvs]--;
freqyes[ico]++;freqyes[gvs]++;
if (
// ico!=iconext && // i'm not sure of this -> skip it
av!=avnext
) {
// only if the class of this point is different from the next point
// class and if its attribute value if also different from the next
// point attribute value
entno=Entropy.entropy(freqno,gvs,freqno[gvs]);
entyes=Entropy.entropy(freqyes,gvs,freqyes[gvs]);
actualscore=os.entropy-(freqno[gvs]*entno+freqyes[gvs]*entyes)/os.size;
if (actualscore>bestscore) {
bestscore=actualscore;
currentthreshold=(float)((av+avnext)/2.0);
}
}
}
bestthreshold=currentthreshold;
lastbestscore=bestscore;
return bestscore;
}
}
--------------------------

/*
* Obj.java
* Copyright (C) 1999 Pierre Geurts
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

import java.util.*;

public class Obj {
/* the name of the object */
String name;
/* the database it belongs to */
Database db;
/* the vector of attributes values */
Vector attributesvalues=new Vector();

Obj(String s, Database db) {
this.db=db;
name=s;
db.addObjToDb(this);
/* it allocates place for the attribute values */
attributesvalues.setSize(db.attributes.size());
}
public String toString() {
return name;
}
}

----------------------

/*
* ObjectSet.java
* Copyright (C) 1999 Pierre Geurts
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

import java.util.*;

/* simplement un vecteur d'object, on verra apres si on garde
ce niveau d'abstraction ou pas
*/

public class ObjectSet {
/* objects list*/
Vector objectslist;
/* a cache value for the entropy in this set */
double entropy;
/* the size of the learning set */
int size;
/* summary, the frequence of each class in this set */
int summary[];

ObjectSet(Vector vo) {
objectslist=vo;
size=vo.size();
}

ObjectSet() {
objectslist=new Vector();
size=0;
}

/* only for compatibility (primary an objectset was simply a vector) */
public int size() {
return size;
}

public Obj elementAt(int index) {
return (Obj)objectslist.elementAt(index);
}
public void addElement(Obj o) {
objectslist.addElement(o);
size++;
}
public void setElementAt(Obj o, int index) {
objectslist.setElementAt(o, index);
}

public int indexOf(Obj o) {
return objectslist.indexOf(o);
}

public String toString() {
return objectslist.toString();
}

/* split a set according to the given test */
public Vector splitOn(Test t) {
int index;
Vector v=new Vector();
Obj o;
for (int i=0; i v.addElement(new ObjectSet());
}
for (int i=0; i o=(Obj)objectslist.elementAt(i);
index=t.TestIndex(o);
((ObjectSet)v.elementAt(index)).addElement(o);
}
return v;
}
/* methods to select subset of objects from the database */

/* select the first n objects from this subset */
public ObjectSet selectFirst(int n) {
ObjectSet os=new ObjectSet();
for (int i=0;i os.addElement((Obj)objectslist.elementAt(i));
}
return os;
}

/* select the last n objects from this subset */
public ObjectSet selectLast(int n) {
ObjectSet os=new ObjectSet();
int i;
if (n>size)
i=0;
else
i=size-n;
for (;i os.addElement((Obj)objectslist.elementAt(i));
}
return os;
}

/* select randomly n objects from this set (very stupid) */
public ObjectSet selectRandom(int n) {
ObjectSet os=new ObjectSet();
Vector v=(Vector)objectslist.clone();
int sv=size;
int pos;
if (n>size)
n=size;
for (int i=0;i pos=(int)(sv*java.lang.Math.random());
os.addElement((Obj)v.elementAt(pos));
v.removeElementAt(pos);
sv--;
}
return os;
}

/* select objects which are not in a given subset */
public ObjectSet selectNotIn(ObjectSet oset) {
ObjectSet os=new ObjectSet();
Obj o;
for (int i=0;i o=(Obj)objectslist.elementAt(i);
if (oset.indexOf(o)==-1)
os.addElement(o);
}
return os;
}

/* method to compute the entropy of an symbolic attribute in this subset
* it computes also the subset summary
*/
public double computeEntropy(SymbAtt goal) {
int sum=size;
int i,x,gvs=goal.values.size();
summary=new int[gvs];
for (i=0; i x=goal.values.indexOf(goal.Value((Obj)objectslist.elementAt(i)));
summary[x]++;
}
entropy=Entropy.entropy(summary, gvs, sum);
return entropy;
}

/* give a textual description of the subset summary */
public String getSummaryString(SymbAtt goal) {
String s="";
for (int i=0; i s+=(String)goal.values.elementAt(i);
s+=":" + summary[i]+ " ";
}
s+="total:" + size;
return s;
}

/* method that gives the majority class in this subset (using the summary) */
public String getMajClass(SymbAtt goal) {
int imax=0;
int maxfreq=summary[0];
for (int i=1; i if (summary[i]>maxfreq) {
maxfreq=summary[i];
imax=i;
}
}
return (String)goal.values.elementAt(imax);
}

/* order a subset on numerical attribute values
* use quicksort algorithm
*/
public void orderOn(NumAtt att) {
orderOn(att,0,size-1);
}

public void orderOn(NumAtt att, int lo0, int hi0) {
int lo=lo0;
int hi=hi0;
float mid;

if (hi0>lo0) {
mid = ((Float)att.Value((Obj)objectslist.elementAt((lo0+hi0)/2))).floatValue();
while (lo<= hi) {
while((lo (((Float)att.Value((Obj)objectslist.elementAt(lo))).floatValue() ++lo;
while((hi>lo0) &&
(((Float)att.Value((Obj)objectslist.elementAt(hi))).floatValue()>mid))
--hi;
if(lo<=hi) {
Object tmp=objectslist.elementAt(lo);
objectslist.setElementAt(objectslist.elementAt(hi),lo);
objectslist.setElementAt(tmp,hi);
++lo;
--hi;
}
}
if(lo0 orderOn(att,lo0,hi);
if (lo orderOn(att,lo,hi0);
}
}
}
---------------------------


/*
* Partition.java
* Copyright (C) 1999 Pierre Geurts
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

import java.util.*;

public class Partition{
/* a test */
Test test;
/* a vector of ObjectSet */
Vector sets;

Partition(Test t, Vector oss) {
test=t;
sets=oss;
}
}
------------------------


/**
* Represents a polygon area for use in spacing/positioning calculations.
*/
class Polygon {
PolyLine lower_head, lower_tail;
PolyLine upper_head, upper_tail;
};

------------------------


/**
* Used to build Polygons.
*/
class PolyLine {
int dx, dy;
PolyLine link;

PolyLine(int dx, int dy, PolyLine link) {
this.dx = dx;
this.dy = dy;
this.link = link;
}
};

--------------------------


/*
* 1.1 version.
*/

import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;

/*
* This displays a framed area. When the user clicks within
* the area, this program displays a dot and a string indicating
* the coordinates where the click occurred.
*/

public class RectangleDemo extends Applet {
RFramedArea framedArea;
Label label;

public void init() {
GridBagLayout gridBag = new GridBagLayout();
GridBagConstraints c = new GridBagConstraints();

setLayout(gridBag);

framedArea = new RFramedArea(this);
c.fill = GridBagConstraints.BOTH;
c.weighty = 1.0;
c.gridwidth = GridBagConstraints.REMAINDER; //end row
gridBag.setConstraints(framedArea, c);
add(framedArea);

label = new Label("Drag within the framed area.");
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1.0;
c.weighty = 0.0;
gridBag.setConstraints(label, c);
add(label);
}

public void updateLabel(Rectangle rect) {
label.setText("Rectangle goes from ("
+ rect.x + ", " + rect.y + ") to ("
+ (rect.x + rect.width - 1) + ", "
+ (rect.y + rect.height - 1) + ").");
}
}

/* This class exists solely to put a frame around the coordinate area. */
class RFramedArea extends Panel {
public RFramedArea(RectangleDemo controller) {
super();

//Set layout to one that makes its contents as big as possible.
setLayout(new GridLayout(1,0));

add(new SelectionArea(controller));
}

public Insets getInsets() {
return new Insets(4,4,5,5);
}

public void paint(Graphics g) {
Dimension d = getSize();
Color bg = getBackground();

g.setColor(bg);
g.draw3DRect(0, 0, d.width - 1, d.height - 1, true);
g.draw3DRect(3, 3, d.width - 7, d.height - 7, false);
}
}

class SelectionArea extends Canvas {
Rectangle currentRect = null;
RectangleDemo controller;

public SelectionArea(RectangleDemo controller) {
super();
this.controller = controller;

MyListener myListener = new MyListener();
addMouseListener(myListener);
addMouseMotionListener(myListener);
}

class MyListener extends MouseAdapter
implements MouseMotionListener {
public void mousePressed(MouseEvent e) {
int x = e.getX();
int y = e.getY();
currentRect = new Rectangle(x, y, 0, 0);
repaint();
}

public void mouseDragged(MouseEvent e) {
updateSize(e);
}

public void mouseMoved(MouseEvent e) {
}

public void mouseReleased(MouseEvent e) {
updateSize(e);
}

void updateSize(MouseEvent e) {
int x = e.getX();
int y = e.getY();
currentRect.setSize(x - currentRect.x,
y - currentRect.y);
repaint();
}
}

public void paint(Graphics g) {
//update has already cleared the previous rectangle,
//so we dn't need to here.

//If currentRect exists, paint a rectangle on top.
if (currentRect != null) {
Dimension d = getSize();
Rectangle box = getDrawableRect(currentRect, d);
controller.updateLabel(box);

//Draw the box outline.
g.drawRect(box.x, box.y,
box.width - 1, box.height - 1);
}
}

Rectangle getDrawableRect(Rectangle originalRect,
Dimension drawingArea) {
int x = originalRect.x;
int y = originalRect.y;
int width = originalRect.width;
int height = originalRect.height;

//Make sure rectangle width and height are positive.
if (width < 0) {
width = 0 - width;
x = x - width + 1;
if (x < 0) {
width += x;
x = 0;
}
}
if (height < 0) {
height = 0 - height;
y = y - height + 1;
if (y < 0) {
height += y;
y = 0;
}
}

//The rectangle shouldn't extend past the drawing area.
if ((x + width) > drawingArea.width) {
width = drawingArea.width - x;
}
if ((y + height) > drawingArea.height) {
height = drawingArea.height - y;
}

//If the width or height is 0, make it 1
//so that the box is visible.
if (width == 0) {
width = 1;
}
if (height == 0) {
height = 1;
}

return new Rectangle(x, y, width, height);
}
}
----------------------


/*
* SimpleNodeDrawer.java
* Copyright (C) 1999 Pierre Geurts
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

import java.awt.*;
import java.util.*;

/**
* a abstract class to allow many representation for
* a node
*/

public class SimpleNodeDrawer extends NodeDrawer {

FontMetrics metrics_small,metrics_big,metrics_current;
Font smallfont, bigfont;
int SMALL_FIXED_FONT_HEIGHT=8;
int BIG_FIXED_FONT_HEIGHT=14;
int current_font_height;
int default_border=5;
Vector colours=new Vector();
Canvas cv;

SimpleNodeDrawer(Canvas c) {
cv=c;
bigfont=new Font("Helvetica", Font.PLAIN, BIG_FIXED_FONT_HEIGHT);
c.setFont(bigfont);
metrics_big=c.getFontMetrics(c.getFont());

smallfont=new Font("Helvetica", Font.PLAIN, SMALL_FIXED_FONT_HEIGHT);
c.setFont(smallfont);
metrics_small=c.getFontMetrics(c.getFont());

metrics_current=metrics_small;
current_font_height=SMALL_FIXED_FONT_HEIGHT;

colours.addElement(Color.black);
colours.addElement(Color.red);
colours.addElement(Color.green);
colours.addElement(Color.blue);
colours.addElement(Color.orange);
colours.addElement(Color.darkGray);
colours.addElement(Color.cyan);
colours.addElement(Color.gray);
colours.addElement(Color.magenta);
colours.addElement(Color.pink);
colours.addElement(Color.black);
colours.addElement(Color.yellow);
colours.addElement(Color.white);
colours.addElement(Color.red);
colours.addElement(Color.green);
colours.addElement(Color.blue);
colours.addElement(Color.orange);
colours.addElement(Color.darkGray);
colours.addElement(Color.cyan);
colours.addElement(Color.gray);
colours.addElement(Color.magenta);
colours.addElement(Color.pink);
colours.addElement(Color.black);
colours.addElement(Color.yellow);
colours.addElement(Color.white);
}

public void computeNodeSize(WNode t) {
t.width=2 * current_font_height;
t.height=metrics_current.stringWidth(t.label) + 10;
t.border=default_border;

if (t.sibling !=null) {
computeNodeSize(t.sibling);
}

if (t.child != null) {
computeNodeSize(t.child);
}
}

public void drawArc(Graphics g, int x1, int y1, int x2,
int y2, String arclabel) {
g.setColor(Color.black);
g.drawLine((int)(x1*zoom), (int)(y1*zoom), (int)(x2*zoom),(int)(y2*zoom));
g.drawString(arclabel,
(int)(((x1 + x2)*zoom - metrics_current.stringWidth(arclabel)) / 2),
(int)((y1 + y2)*zoom/2));
}

public void drawNode(Graphics g, WNode t) {
int tposx=(int)(t.pos.x*zoom);
int tposy=(int)(t.pos.y*zoom);
int tw=(int)(t.width*zoom);
int th=(int)(t.height*zoom);

// Draw highlights
g.setColor(Color.lightGray);
g.drawLine(tposy + 2, tposx + tw + 1, tposy + th,
tposx + tw + 1);
g.drawLine(tposy + th + 1, tposx + tw + 1,
tposy + th + 1, tposx + 2);

// we draw the box corresponding to this node
if (t.colour>=colours.size())
g.setColor(Color.black);
else
g.setColor((Color)colours.elementAt(t.colour));

g.drawRect(tposy, tposx, th, tw);

// we draw the node label
g.drawString(t.label,
tposy + (th - metrics_current.stringWidth(t.label)) / 2,
tposx + tw - (tw - current_font_height) / 2);

if (t.selected) {
int border=(int)(3*zoom);
g.setColor(Color.pink);
g.drawRect(tposy-border, tposx-border, th+2*border, tw+2*border);
}

}

// increase the zoom
public void increaseZoom() {
if (zoom==0.5)
zoom=0.7;
else if (zoom==0.7)
zoom=1.0;
else if (zoom==1.0)
zoom=1.2;
else if (zoom==1.2) {
zoom=1.5;
metrics_current=metrics_big;
current_font_height=BIG_FIXED_FONT_HEIGHT;
cv.setFont(bigfont);
} else if (zoom==1.5)
zoom=2.0;
else if (zoom==2.0)
zoom=2.5;
else if (zoom==2.5)
zoom=3.0;
}

// decrease the zoom
public void decreaseZoom() {
if (zoom==3.0)
zoom=2.5;
else if (zoom==2.5)
zoom=2.0;
else if (zoom==2.0)
zoom=1.5;
else if (zoom==1.5) {
zoom=1.2;
metrics_current=metrics_small;
current_font_height=SMALL_FIXED_FONT_HEIGHT;
cv.setFont(smallfont);
} else if (zoom==1.2)
zoom=1.0;
else if (zoom==1.0)
zoom=0.7;
else if (zoom==0.7)
zoom=0.5;
}
}
-----------------------

/*
* SymbAtt.java
* Copyright (C) 1999 Pierre Geurts
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

/* recherche de la meilleure partition binaire de l'ensemble des valeurs de
l'attribut */

import java.util.*;
import java.io.*;

public class SymbAtt extends Attribute{
Vector values=new Vector();
/* la valeur de l'attribut symbolique qui donne le meilleur score */
Vector bestsubset;

SymbAtt(String s, Database dab) {
name=s;
db=dab;
index=db.addAttToDb(this);
}
public void SetAttValue(Obj o,Object s) {
int i;
for (i=0; i if (s.equals(values.elementAt(i)))
break;
if (i o.attributesvalues.setElementAt(values.elementAt(i),index);
else {
o.attributesvalues.setElementAt(s,index);
values.addElement(s);
}
}
public int ReadAttValue(Obj o, StreamTokenizer stt) {
if (stt.ttype==stt.TT_WORD) {
SetAttValue(o,stt.sval);
return 0;
} else if (stt.ttype==stt.TT_NUMBER) {
// we transform number to a string
SetAttValue(o,"" + stt.nval);
return 0;
} else {
System.out.println("A symbolic value was expected");
return 1;
}
}

public String describe() {
return toString()+ " - symbolic - values : " + values.toString();
}

public String describeBestTest() {
return toString() + " - values : " + bestsubset.toString() + " - Information gain : " + lastbestscore;
}

public double bestscore(ObjectSet os, SymbAtt goal) {
/* attention cette partie est tres tres mal ecrite */

double result;
double tmpresult;
double currentbestscore=-1;
int currentbestvalue=0;
int pbv;
int i,j,x,y;

/* liste des index*/
Vector remainingvalues=new Vector();
for (i=0; i remainingvalues.addElement(new Integer(i));
}

/* les valeurs dans l'ordre dans lequel elles sont selectionnees */
Vector ordervalues=new Vector();
/* les valeurs de score */
Vector scores=new Vector();

int gvs=goal.values.size();
int sum=os.size;

/* pour chaque valeur de l'attribut, on conserve la matrice des frequences */
int tabfreq[][][]=new int[values.size()][2][gvs+1];

/* calcul des matrices de frequences */
for (j=0; j
for (i=0; i x=values.indexOf(this.Value((Obj)os.elementAt(i)));
y=goal.values.indexOf(goal.Value((Obj)os.elementAt(i)));

if (x==j) { /* la valeur est la valeur testee */
tabfreq[j][0][y]++;
tabfreq[j][0][gvs]++;
} else {
tabfreq[j][1][y]++;
tabfreq[j][1][gvs]++;
}
}
/* calcul de l'entropie */
result=os.entropy;
result-=tabfreq[j][0][gvs]*Entropy.entropy(tabfreq[j][0], gvs,tabfreq[j][0][gvs])/sum;
result-=tabfreq[j][1][gvs]*Entropy.entropy(tabfreq[j][1], gvs,tabfreq[j][1][gvs])/sum;

if (result>currentbestscore) {
currentbestscore=result;
currentbestvalue=j;
}
}

/* on va maintenant regrouper les attributs de maniere recursive */
int currenttabfreq[][]=new int[2][gvs+1];
for (i=0;i currenttabfreq[0][i]=0;
currenttabfreq[1][i]=tabfreq[currentbestvalue][0][i]
+ tabfreq[currentbestvalue][1][i];
}
// printtab(currenttabfreq,gvs+1);

/* on ajoute cet element dans la liste */
Integer cbv=new Integer(currentbestvalue);
ordervalues.addElement(cbv);
scores.addElement(new Double(currentbestscore));
i=0;
while (i ((Integer)remainingvalues.elementAt(i)).intValue()!=currentbestvalue)
i++;
remainingvalues.removeElementAt(i);

while (remainingvalues.size()!=1) {
/* copier le tableau courant dans la valeur correspondant
a l'element precedent */
for (i=0;i currenttabfreq[0][i]+=tabfreq[currentbestvalue][0][i];
currenttabfreq[1][i]-=tabfreq[currentbestvalue][0][i];
}
// printtab(currenttabfreq,gvs+1);
/* on va utiliser la matrice correspondant a la precedente
valeur comme moyen de stockage temporaire
*/

pbv=currentbestvalue;

/* recherche de la meilleure valeur a ajouter au sous-ensemble */
currentbestscore=-1;

for (j=0; j int cv=((Integer)remainingvalues.elementAt(j)).intValue();
for (i=0; i tabfreq[pbv][0][i]=tabfreq[cv][0][i]+currenttabfreq[0][i];
tabfreq[pbv][1][i]=currenttabfreq[1][i]-tabfreq[cv][0][i];
}

result=os.entropy;
result-=tabfreq[pbv][0][gvs]*
Entropy.entropy(tabfreq[pbv][0], gvs, tabfreq[pbv][0][gvs])/sum;
result-=tabfreq[pbv][1][gvs]*
Entropy.entropy(tabfreq[pbv][1], gvs, tabfreq[pbv][1][gvs])/sum;
if (result>currentbestscore) {
currentbestscore=result;
currentbestvalue=cv;
}
}
cbv=new Integer(currentbestvalue);
ordervalues.addElement(cbv);
scores.addElement(new Double(currentbestscore));
i=0;
while (i ((Integer)remainingvalues.elementAt(i)).intValue()!=currentbestvalue)
i++;
remainingvalues.removeElementAt(i);
}

/* recherche du meilleur score */
currentbestscore=((Double)scores.elementAt(0)).doubleValue();
currentbestvalue=0;
for (i=1; i double sc=((Double)scores.elementAt(i)).doubleValue();
if (sc>currentbestscore) {
currentbestscore=sc;
currentbestvalue=i;
}
}

/* on garde uniquement les elements de l'ensemble */
ordervalues.setSize(currentbestvalue+1);
bestsubset=new Vector();
for (i=0; i bestsubset.addElement(values.elementAt(((Integer)ordervalues.elementAt(i)).intValue()));

// System.out.println(name + " " + values.toString() + " " + bestsubset.toString());

lastbestscore=currentbestscore;
return currentbestscore;
}

public Partition bestpartition(ObjectSet os, SymbAtt goal) {
TestSymb t=new TestSymb(this, bestsubset);
Vector v=os.splitOn(t);
return new Partition(t,v);
}

/*
public static void printtab(int[][] tab,int size) {
System.out.print("[[");
for (int i=0; i System.out.print("" + tab[0][i] + ", ");
}
System.out.println("]");
System.out.print("[");
for (int i=0; i System.out.print("" + tab[1][i] + ", ");
}
System.out.println("]]");
}
*/

}
-------------------

/*
* Test.java
* Copyright (C) 1999 Pierre Geurts
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

import java.util.*;

/* a test should also be an extension of a Symbolic Attribute
* so that we could use it later
*/
abstract class Test {
/* a description of the test */
String TestDescription;
/* the attribute */
Attribute Att;
/* the number of issues of this test */
int nbIssues;
/* the vector of the values corresponding to each issues */
Vector valuesIssues;
/* TestObject gives the value associated to this object */
abstract String TestObject(Obj o);
/* return a description of the nth value of this test */
abstract String testDescription(int value);
/* TestIndex gives the index of this values in valuesissues */
public int TestIndex(Obj o) {
return valuesIssues.indexOf(TestObject(o));
}
}

----------------------------

/*
* Test.java
* Copyright (C) 1999 Pierre Geurts
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

import java.util.*;

/* a test should also be an extension of a Symbolic Attribute
* so that we could use it later
*/
abstract class Test {
/* a description of the test */
String TestDescription;
/* the attribute */
Attribute Att;
/* the number of issues of this test */
int nbIssues;
/* the vector of the values corresponding to each issues */
Vector valuesIssues;
/* TestObject gives the value associated to this object */
abstract String TestObject(Obj o);
/* return a description of the nth value of this test */
abstract String testDescription(int value);
/* TestIndex gives the index of this values in valuesissues */
public int TestIndex(Obj o) {
return valuesIssues.indexOf(TestObject(o));
}
}

----------------------
/*
* Test.java
* Copyright (C) 1999 Pierre Geurts
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

import java.util.*;

/* a test should also be an extension of a Symbolic Attribute
* so that we could use it later
*/
abstract class Test {
/* a description of the test */
String TestDescription;
/* the attribute */
Attribute Att;
/* the number of issues of this test */
int nbIssues;
/* the vector of the values corresponding to each issues */
Vector valuesIssues;
/* TestObject gives the value associated to this object */
abstract String TestObject(Obj o);
/* return a description of the nth value of this test */
abstract String testDescription(int value);
/* TestIndex gives the index of this values in valuesissues */
public int TestIndex(Obj o) {
return valuesIssues.indexOf(TestObject(o));
}
}

--------------------

import java.awt.*;

/**
* "There flowered a White Tree, and that was for Gondor; but Seven Stars
* were about it, and a high crown above it, the signs of Elendil that no
* lord had borne for years beyond count. And the stars flamed in the
* sunlight, for they were wrought of gems by Arwen daughter of Elrond;
* and the crown was bright in the morning, for it was wrought of mithril
* and gold." - J. R. R. Tolkien, _The Return of the King_
*
* Basic canvas for creating and displaying a WalTree.
*/
public class WalTreeCanvas extends Canvas {
int default_border;

WTFactory wt_factory; // contain functions to draw a tree
NodeDrawer nd; // contain functions to draw a node
WNode t;
boolean dirty; // tell us if the node positions should be computed again
int root_x;

/**
* Constructs new WalTreeCanvas, an associated WTFactory, and inits state.
*/
public WalTreeCanvas() {
super();

wt_factory = new WTFactory();
t = null;
default_border = 5;
root_x = 8;
dirty = false;
}

public Dimension getPreferredSize() {
return new Dimension(2000, 2000);
}

public Dimension getMiminimumSize() {
return new Dimension(40, 40);
}

/**
* Set the tree to be displayed by this canvas.
*/
public void setTree(WNode t) {
this.t = t;
dirty = true;
}

/**
* Set the default border size for nodes
*/
public void setDefaultBorder(int b) {
default_border = b;
}

/**
* Set the distance between parent nodes.
*/
public void setParentDistance(int val) {
wt_factory.setParentDistance(val);
}

/**
* Set the horizontal offset between edge of canvas and root node.
*/
public void setRootOffset(int val) {
root_x = val;
}

/**
* Draw the tree associated with this canvas.
*/
public void paint(Graphics g) {
super.paint(g);

Dimension d = getSize();

/* Wipe background */
g.setColor(Color.white);
g.fillRect(0, 0, d.width, d.height);

if(t == null) {
return;
}

if(dirty == true) {
/* Calculate node offsets */
wt_factory.layout(t);

/* Calculate absolute node positions */

wt_factory.plantTree(t, root_x, root_x-wt_factory.computeMaxOffset(t,0));

dirty = false;
}

/* Paint the beastie */
wt_factory.paintFullTree(g, t, nd);
}
};
------------------------

import java.awt.Point;

/**
* Represents a node (or tree) in the WalTree.
*/
public class WNode {
String label; // the label of the node (test)
String arclabel; // the label of the arc leading to this node
WNode parent, child, sibling;
int width, height, border; // the width, height and border of this node
Point pos, offset;
Polygon contour;
int colour=0; // a colour number
DtNode dtnode; // the associated DtNode
boolean selected=false; // tell us if this node is the current node

public WNode(String l, String a, WNode p, WNode c, WNode s, int w, int h, int b, DtNode dtn) {
label = l;
arclabel=a;
parent = p;
child = c;
sibling = s;
width = w;
height = h;
border = b;
pos = new Point(0, 0);
offset = new Point(0, 0);
contour = new Polygon();
dtnode=dtn;
}

public boolean containsPoint(int x, int y) {
return (((y>=pos.x) && (y<=pos.x+width)) && ((x>=pos.y) && (x<=pos.y+height)));
}

public DtNode getPointedNode(int x,int y) {
if (containsPoint(x,y))
return dtnode;
if (child!=null && y>pos.x) {
// not worth going further down if y DtNode dtchild=child.getPointedNode(x,y);
if (dtchild!=null)
return dtchild;
}
if (sibling!=null)
return sibling.getPointedNode(x,y);
return null;
}
}
-------------------------

/**
* A direct port from Sven Moen's "Drawing Dynamic Trees" article in
* IEEE Software, July 1990. Thanks to Allan Brighton for commenting the
* Brighton Tree Widget source code with the aforementioned reference.
*
* mai 1999 : modified by Pierre Geurts to display decision trees
*
*/

import java.awt.*;
import java.util.*;

/**
* Encapsulates all operations performed on a WalTree.
*/
public class WTFactory {

int parent_dist = 30;

/**
* Allows setting of the distance between levels in the tree.
*/
public void setParentDistance(int val) {
parent_dist = val;
}

/**
* Lays out the tree node spacing in typical tidy fashion.
*/
void layout(WNode t) {
WNode c;

if(t == null) {
return;
}

c = t.child;
while(c != null) {
layout(c);
c = c.sibling;
}

if(t.child != null) {
attachParent(t, join(t));
} else {
layoutLeaf(t);
}
}

/**
* Attaches the specified node to its children, setting offsets.
*/
void attachParent(WNode t, int h) {
int x, y1, y2;

x = t.border + parent_dist;
y2 = (h - t.height) / 2 - t.border;
y1 = y2 + t.height + 2 * t.border - h;
t.child.offset.x = x + t.width;
t.child.offset.y = y1;
t.contour.upper_head = new PolyLine(t.width, 0, new PolyLine(x, y1,
t.contour.upper_head));
t.contour.lower_head = new PolyLine(t.width, 0, new PolyLine(x, y2,
t.contour.lower_head));
}

/**
* Arranges contour for leaf node appropriately.
*/
void layoutLeaf(WNode t) {
t.contour.upper_tail = new PolyLine(t.width + 2 * t.border, 0, null);
t.contour.upper_head = t.contour.upper_tail;
t.contour.lower_tail = new PolyLine(0, -t.height - 2 * t.border, null);
t.contour.lower_head = new PolyLine(t.width + 2 * t.border, 0,
t.contour.lower_tail);
}

/**
* Joins children/siblings together, merging contours.
*/
int join(WNode t) {
WNode c;
int d, h, sum;

c = t.child;
t.contour = c.contour;
sum = h = c.height + 2 * c.border;
c = c.sibling;
while(c != null) {
d = merge(t.contour, c.contour);
c.offset.y = d + h;
c.offset.x = 0;
h = c.height + 2 * c.border;
sum += d + h;
c = c.sibling;
}

return sum;
}

/**
* Merges two polygons together. Returns total height of final polygon.
*/
int merge(Polygon c1, Polygon c2) {
int x, y, total, d;
PolyLine lower, upper, b;

x = y = total = 0;
upper = c1.lower_head;
lower = c2.upper_head;

while(lower != null && upper != null) { /* compute offset total */

d = offset(x, y, lower.dx, lower.dy, upper.dx, upper.dy);
y += d;
total += d;

if(x + lower.dx <= upper.dx) {
y += lower.dy;
x += lower.dx;
lower = lower.link;
} else {
y -= upper.dy;
x -= upper.dx;
upper = upper.link;
}
}

/* store result in c1 */

if(lower != null) {
b = bridge(c1.upper_tail, 0, 0, lower, x, y);
c1.upper_tail = (b.link != null) ? c2.upper_tail : b;
c1.lower_tail = c2.lower_tail;
} else { /* (upper) */
b = bridge(c2.lower_tail, x, y, upper, 0, 0);
if(b.link == null) {
c1.lower_tail = b;
}
}

c1.lower_head = c2.lower_head;

return total;
}

/**
* Calculates the offset for specified points.
*/
int offset(int p1, int p2, int a1, int a2, int b1, int b2) {
int d, s, t;

if(b1 <= p1 || p1 + a1 <= 0) {
return 0;
}

t = b1 * a2 - a1 * b2;
if(t > 0) {
if(p1 < 0) {
s = p1 * a2;
d = s / a1 - p2;
} else if(p1 > 0) {
s = p1 * b2;
d = s / b1 - p2;
} else {
d = -p2;
}
} else if(b1 < p1 + a1) {
s = (b1 - p1) * a2;
d = b2 - (p2 + s / a1);
} else if(b1 > p1 + a1) {
s = (a1 + p1) * b2;
d = s / b1 - (p2 + a2);
} else {
d = b2 - (p2 + a2);
}

if(d > 0) {
return d;
} else {
return 0;
}
}

/**
* bridge
*/
PolyLine bridge(PolyLine line1, int x1, int y1, PolyLine line2, int x2,
int y2) {
int dy, dx, s;
PolyLine r;

dx = x2 + line2.dx - x1;
if(line2.dx == 0) {
dy = line2.dy;
} else {
s = dx * line2.dy;
dy = s / line2.dx;
}

r = new PolyLine(dx, dy, line2.link);
line1.link = new PolyLine(0, y2 + line2.dy - dy - y1, r);

return r;
}

void plantTree(WNode t, int off_x, int off_y) {
WNode c, s;
int cur_y;

t.pos.x = off_x + t.offset.x;
t.pos.y = off_y + t.offset.y;

/* Plant child node */
c = t.child;
if(c != null) {
plantTree(c, t.pos.x, t.pos.y);

/* Plant sibling nodes */
s = c.sibling;
cur_y = t.pos.y + c.offset.y;
while(s != null) {
plantTree(s, t.pos.x + c.offset.x, cur_y);
cur_y += s.offset.y;
s = s.sibling;
}
}
}

/**
* PG 05/1999 : compute the maximum y offset to the right (or bottom)
* of the tree (to put the tree at the most left part (we go down
* along the first branch).
*/
int computeMaxOffset(WNode t, int y) {
WNode c, s;
int cur_y;
int current_pos_y;

current_pos_y = y + t.offset.y;

c = t.child;
if(c != null) {
int min=computeMaxOffset(c, current_pos_y), newmin=min;

/* Plant sibling nodes */
s = c.sibling;
cur_y = current_pos_y + c.offset.y;
while(s != null) {
newmin=computeMaxOffset(s, cur_y);
if (newmin min=newmin;
cur_y += s.offset.y;
s = s.sibling;
}
return min;
} else
return current_pos_y;
}

void paintFullTree(Graphics g, WNode t, NodeDrawer nd) {
if(t == null) {
System.out.println("paintFullTree::null tree.");
return;
}

g.setColor(Color.black);

paintTree(g, t, nd);
}

void paintTree(Graphics g, WNode t, NodeDrawer nd) {
nd.drawNode(g,t);

if(t.parent != null) {
int x1 = t.pos.y + t.height / 2;
int y1 = t.pos.x;
int x2 = t.parent.pos.y + t.parent.height / 2;
int y2 = t.parent.pos.x + t.parent.width;
nd.drawArc(g,x1,y1,x2,y2,t.arclabel);
}

/* Draw siblings, using the main child's x-offset. */
if(t.sibling != null) {
paintTree(g, t.sibling, nd);
}

/* Draw children */
if(t.child != null) {
paintTree(g, t.child, nd);
}
}
}

-------------

tree

import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.*;
import java.awt.*;

// This file gives an example of doing simple
// graphical user interface (GUI) in Java using
// the Swing API.
//
// You can use this file as a template for the GUI
// part of your solution to Homework 2.
//
// The various classes involved are described
// briefly below. The main thing you need to
// modify (other than renaming classes) is the
// DemoPanel class, which is the GUI component
// that should display your tree.
public class GUIExample {

// The main method creates a frame object and
// displays it.
public static void main(String[] args) {
// you will put all preprocessing steps here

// display the frame window
DemoFrame frame = new DemoFrame("x", "y");
frame.setTitle("GUI Demonstration");
frame.show();

}
}

// Frame objects are movable frame windows; they
// can contain other GUI components like buttons,
// text areas, and panels. DemoFrame is a frame
// class that contains a panel; right now, the panel
// displays a hard-coded tree picture (see the
// class DemoPanel).
class DemoFrame extends JFrame {
private DemoPanel panel;

public DemoFrame(String str1, String str2) {
final int DEFAULT_FRAME_WIDTH = 300;
final int DEFAULT_FRAME_HEIGHT = 300;

// set the size of the frame window
setSize(DEFAULT_FRAME_WIDTH, DEFAULT_FRAME_HEIGHT);

// create and install a "listener object"
// (event handler) to listen for window events
WindowCloser listener = new WindowCloser();
addWindowListener(listener);

// create a panel object and install it in
// the "content pane"
panel = new DemoPanel(str1, str2);
Container contentPane = getContentPane();
contentPane.add(panel, "Center");

}

// The class WindowCloser is a listener (event
// handler) class.
private class WindowCloser extends WindowAdapter {
// When the user closes the frame window, we
// kill the program.
public void windowClosing(WindowEvent event) {
System.exit(0);
}
}
}

// THIS IS THE CLASS YOU NEED TO MODIFY.
// Panel objects are GUI components that you
// can draw on. A panel object should store
// as instance data all the information it needs
// to repaint itself. In this simple example,
// objects of type DemoPanel just store a string
// called childName, which is used to draw a
// diagram of a small, hard-coded "tree".
class DemoPanel extends JPanel {
private String firstVar;
private String secondVar;

public DemoPanel(String str1, String str2) {
firstVar = str1;
secondVar = str2;
}

// The paintComponent method is called every time
// that the panel needs to be displayed or refreshed.
// Anything you want drawn on the panel should be drawn
// in this method. In this example, a small tree is
// "hard-coded". More typically, the panel could store
// a reference to an object with a graphical representation
// (like a tree), and we'd call an instance method of that
// object to get it to draw itself. Note: this method
// gets passed (as parameter "page") a reference to the
// current graphical context object of the GUI component;
// all drawing is done through the "page" reference.
public void paintComponent(Graphics page) {
// leave the next line in
super.paintComponent(page);

// replace this code with a method call that draws your tree

page.setColor(Color.green);
page.fillOval(ROOT_X, ROOT_Y, 2*RADIUS, 2*RADIUS);
page.fillOval(ROOT_X+H_SKIP, ROOT_Y+V_SKIP,
2*RADIUS, 2*RADIUS);
page.drawLine(ROOT_X+RADIUS,ROOT_Y+RADIUS,ROOT_X+H_SKIP+RADIUS,ROOT_Y+V_SKIP+RADIUS);

page.setColor(Color.black);
page.drawString(firstVar, ROOT_X + RADIUS - SPACE, ROOT_Y + RADIUS + SPACE);
page.drawString(secondVar, ROOT_X + H_SKIP + RADIUS - SPACE, ROOT_Y + V_SKIP + RADIUS + SPACE);

}

private static final int ROOT_X = 70;
private static final int ROOT_Y = 100;
private static final int V_SKIP = 60;
private static final int H_SKIP = 60;
private static final int RADIUS = 15;
private static final int SPACE = 3;
}









---------------------------


import java.io.*;
import java.util.*;

public class ID3 {


int numAttributes; // The number of attributes including the output attribute
String []attributeNames; // The names of all attributes. It is an array of dimension numAttributes. The last attribute is the output attribute

/* Possible values for each attribute is stored in a vector. domains is an array of dimension numAttributes.
Each element of this array is a vector that contains values for the corresponding attribute
domains[0] is a vector containing the values of the 0-th attribute, etc..
The last attribute is the output attribute
*/
Vector []domains;

/* The class to represent a data point consisting of numAttributes values of attributes */
class DataPoint {

/* The values of all attributes stored in this array. i-th element in this array
is the index to the element in the vector domains representing the symbolic value of
the attribute. For example, if attributes[2] is 1, then the actual value of the
2-nd attribute is obtained by domains[2].elementAt(1). This representation makes
comparing values of attributes easier - it involves only integer comparison and
no string comparison.
The last attribute is the output attribute
*/
public int []attributes;

public DataPoint(int numattributes) {
attributes = new int[numattributes];
}
};


/* The class to represent a node in the decomposition tree.
*/
class TreeNode {
public double entropy; // The entropy of data points if this node is a leaf node
public Vector data; // The set of data points if this is a leaf node
public int decompositionAttribute; // If this is not a leaf node, the attribute that is used to divide the set of data points
public int decompositionValue; // the attribute-value that is used to divide the parent node
public TreeNode []children; // If this is not a leaf node, references to the children nodes
public TreeNode parent; // The parent to this node. The root has parent == null

public TreeNode() {
data = new Vector();
}

};

/* The root of the decomposition tree */
TreeNode root = new TreeNode();


/* This function returns an integer corresponding to the symbolic value of the attribute.
If the symbol does not exist in the domain, the symbol is added to the domain of the attribute
*/
public int getSymbolValue(int attribute, String symbol) {
int index = domains[attribute].indexOf(symbol);
if (index < 0) {
domains[attribute].addElement(symbol);
return domains[attribute].size() -1;
}
return index;
}

/* Returns all the values of the specified attribute in the data set */
public int []getAllValues(Vector data, int attribute) {
Vector values = new Vector();
int num = data.size();
for (int i=0; i< num; i++) {
DataPoint point = (DataPoint)data.elementAt(i);
String symbol = (String)domains[attribute].elementAt(point.attributes[attribute] );
int index = values.indexOf(symbol);
if (index < 0) {
values.addElement(symbol);
}
}

int []array = new int[values.size()];
for (int i=0; i< array.length; i++) {
String symbol = (String)values.elementAt(i);
array[i] = domains[attribute].indexOf(symbol);
}
values = null;
return array;
}


/* Returns a subset of data, in which the value of the specfied attribute of all data points is the specified value */
public Vector getSubset(Vector data, int attribute, int value) {
Vector subset = new Vector();

int num = data.size();
for (int i=0; i< num; i++) {
DataPoint point = (DataPoint)data.elementAt(i);
if (point.attributes[attribute] == value) subset.addElement(point);
}
return subset;

}


/* Calculates the entropy of the set of data points.
The entropy is calculated using the values of the output attribute which is the last element in the array attribtues
*/
public double calculateEntropy(Vector data) {

int numdata = data.size();
if (numdata == 0) return 0;

int attribute = numAttributes-1;
int numvalues = domains[attribute].size();
double sum = 0;
for (int i=0; i< numvalues; i++) {
int count=0;
for (int j=0; j< numdata; j++) {
DataPoint point = (DataPoint)data.elementAt(j);
if (point.attributes[attribute] == i) count++;
}
double probability = 1.*count/numdata;
if (count > 0) sum += -probability*Math.log(probability);
}
return sum;

}

/* This function checks if the specified attribute is used to decompose the data set
in any of the parents of the specfied node in the decomposition tree.
Recursively checks the specified node as well as all parents
*/
public boolean alreadyUsedToDecompose(TreeNode node, int attribute) {
if (node.children != null) {
if (node.decompositionAttribute == attribute )
return true;
}
if (node.parent == null) return false;
return alreadyUsedToDecompose(node.parent, attribute);
}

/* This function decomposes the specified node according to the ID3 algorithm.
Recursively divides all children nodes until it is not possible to divide any further
I have changed this code from my earlier version. I believe that the code
in my earlier version prevents useless decomposition and results in a better decision tree!
This is a more faithful implementation of the standard ID3 algorithm
*/
public void decomposeNode(TreeNode node) {

double bestEntropy=0;
boolean selected=false;
int selectedAttribute=0;

int numdata = node.data.size();
int numinputattributes = numAttributes-1;
node.entropy = calculateEntropy(node.data);
if (node.entropy == 0) return;

/* In the following two loops, the best attribute is located which
causes maximum decrease in entropy
*/
for (int i=0; i< numinputattributes; i++) {
int numvalues = domains[i].size();
if ( alreadyUsedToDecompose(node, i) ) continue;
// Use the following variable to store the entropy for the test node created with the attribute i
double averageentropy = 0;
for (int j=0; j< numvalues; j++) {
Vector subset = getSubset(node.data, i, j);
if (subset.size() == 0) continue;
double subentropy = calculateEntropy(subset);
averageentropy += subentropy * subset.size(); // Weighted sum
}

averageentropy = averageentropy / numdata; // Taking the weighted average
if (selected == false) {
selected = true;
bestEntropy = averageentropy;
selectedAttribute = i;
} else {
if (averageentropy < bestEntropy) {
selected = true;
bestEntropy = averageentropy;
selectedAttribute = i;
}
}

}

if (selected == false) return;

// Now divide the dataset using the selected attribute
int numvalues = domains[selectedAttribute].size();
node.decompositionAttribute = selectedAttribute;
node.children = new TreeNode [numvalues];
for (int j=0; j< numvalues; j++) {
node.children[j] = new TreeNode();
node.children[j].parent = node;
node.children[j].data = getSubset(node.data, selectedAttribute, j);
node.children[j].decompositionValue = j;
}

// Recursively divides children nodes
for (int j=0; j< numvalues; j++) {
decomposeNode(node.children[j]);
}

// There is no more any need to keep the original vector. Release this memory
node.data = null; // Let the garbage collector recover this memory

}


/** Function to read the data file.
The first line of the data file should contain the names of all attributes.
The number of attributes is inferred from the number of words in this line.
The last word is taken as the name of the output attribute.
Each subsequent line contains the values of attributes for a data point.
If any line starts with // it is taken as a comment and ignored.
Blank lines are also ignored.
*/
public int readData(String filename) throws Exception {

FileInputStream in = null;

try {
File inputFile = new File(filename);
in = new FileInputStream(inputFile);
} catch ( Exception e) {
System.err.println( "Unable to open data file: " + filename + "\n" + e);
return 0;
}

BufferedReader bin = new BufferedReader(new InputStreamReader(in) );

String input;
while(true) {
input = bin.readLine();
if (input == null) {
System.err.println( "No data found in the data file: " + filename + "\n");
return 0;
}
if (input.startsWith("//")) continue;
if (input.equals("")) continue;
break;
}


StringTokenizer tokenizer = new StringTokenizer(input,",");
numAttributes = tokenizer.countTokens();
//System.out.println("numAttributes"+numAttributes);
if (numAttributes <= 1) {
System.err.println( "Read line: " + input);
System.err.println( "Could not obtain the names of attributes in the line");
System.err.println( "Expecting at least one input attribute and one output attribute");
return 0;
}

domains = new Vector[numAttributes];
for (int i=0; i < numAttributes; i++) domains[i] = new Vector();
attributeNames = new String[numAttributes];

for (int i=0; i < numAttributes; i++) {
attributeNames[i] = tokenizer.nextToken();
}


while(true) {
input = bin.readLine();
if (input == null) break;
if (input.startsWith("//")) continue;
if (input.equals("")) continue;

tokenizer = new StringTokenizer(input,",");
int numtokens = tokenizer.countTokens();
//System.out.println("numtokens"+numtokens);
if (numtokens != numAttributes) {
System.err.println( "Read " + root.data.size() + " data");
System.err.println( "Last line read: " + input);
System.err.println( "Expecting " + numAttributes + " attributes");
return 0;
}

DataPoint point = new DataPoint(numAttributes);
for (int i=0; i < numAttributes; i++) {
point.attributes[i] = getSymbolValue(i, tokenizer.nextToken() );
}
root.data.addElement(point);

}

bin.close();

return 1;

} // End of function readData
//-----------------------------------------------------------------------

/* This function prints the decision tree in the form of rules.
The action part of the rule is of the form
outputAttribute = "symbolicValue"
or
outputAttribute = { "Value1", "Value2", .. }
The second form is printed if the node cannot be decomposed any further into an homogenous set
*/
public void printTree(TreeNode node, String tab) {

int outputattr = numAttributes-1;

if (node.children == null) {
int []values = getAllValues(node.data, outputattr );
if (values.length == 1) {
System.out.println(tab + "\t" + attributeNames[outputattr] + " = \"" + domains[outputattr].elementAt(values[0]) + "\";");
return;
}
System.out.print(tab + "\t" + attributeNames[outputattr] + " = {");
for (int i=0; i < values.length; i++) {
System.out.print("\"" + domains[outputattr].elementAt(values[i]) + "\" ");
if ( i != values.length-1 ) System.out.print( " , " );
}
System.out.println( " };");
return;
}

int numvalues = node.children.length;
for (int i=0; i < numvalues; i++) {
System.out.println(tab + "if( " + attributeNames[node.decompositionAttribute] + " == \"" +
domains[node.decompositionAttribute].elementAt(i) + "\") {" );
printTree(node.children[i], tab + "\t");
if (i != numvalues-1) System.out.print(tab + "} else ");
else System.out.println(tab + "}");
}


}

/* This function creates the decision tree and prints it in the form of rules on the console
*/
public void createDecisionTree() {
decomposeNode(root);
printTree(root, "");
}


/* Here is the definition of the main function */
public static void main(String[] args) throws Exception {

int num = args.length;
if (num != 1) {
System.out.println("You need to specify the name of the datafile at the command line " );
return;
}


ID3 me = new ID3();

long startTime = System.currentTimeMillis(); // To print the time taken to process the data

int status = me.readData(args[0]);
if (status <= 0) return;

me.createDecisionTree();


long endTime = System.currentTimeMillis();
long totalTime = (endTime-startTime)/1000;

System.out.println( totalTime + " Seconds");


}
/* End of the main function */

}

----------------------------------------

Thursday, March 26, 2009

http://cis.sac.accd.edu/~lschulze/ITSE1302.html

http://cis.sac.accd.edu/~lschulze/C++%20Programming%20Notes.html

Program




import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

import java.sql.*;

public class TestQueueIntSimple extends JPanel implements ActionListener{

// initialize the class variables,access specifier are using private
private JLabel labelt;
private JFrame frame;
private JPanel panel;
//private JLabel labelmid;
private JLabel putvalueLable;
private JLabel takenvalueLable;
private JLabel queuedepthLable;
private JLabel errormsgLable;


private JTextField putvalue;
private JTextField takenvalue;

private JTextField queuedepth;
public JTextField errormsg;


private JButton button;
private JButton button2;
private JButton button3;

private JTextArea tarea;
private JScrollPane scrollpane;
QueueIntSimple qs = new QueueIntSimple();

public TestQueueIntSimple(){

frame= new JFrame(" -- Queue Implemantion -- ");
frame.getContentPane().setLayout(null);

putvalueLable = new JLabel("Enter value to put");
putvalue = new JTextField(15);
takenvalueLable = new JLabel("Value taken");
takenvalue = new JTextField(15);

queuedepthLable = new JLabel("Queue depth");
queuedepth = new JTextField(15);

labelt = new JLabel("Queue Implemantion");
labelt.setFont(new Font("Serif", Font.BOLD, 25));
errormsgLable = new JLabel("Error messages");
errormsg = new JTextField(15);




button = new JButton("PUT");
button2 = new JButton("TAKE");
button3 = new JButton("DISPLAY");
tarea = new JTextArea();

labelt.setBounds(250,20,350,70);

putvalueLable.setBounds(50,70,150,70);
takenvalueLable.setBounds(50,120,150,70);

putvalue.setBounds(220,90,60,27);
takenvalue.setBounds(220,140,60,27);

queuedepthLable.setBounds(50,170,150,70);
queuedepth.setBounds(220,190,60,27);

errormsgLable.setBounds(50,220,150,70);

errormsg.setBounds(220,240,180,27);




button.setBounds(100,280,80,27);
button2.setBounds(200,280,80,27);
button3.setBounds(300,280,120,27);
tarea.setBounds(220,320,180,180);

frame.getContentPane().add(labelt);
frame.getContentPane().add(putvalueLable);
frame.getContentPane().add(putvalue);
frame.getContentPane().add(takenvalueLable);
frame.getContentPane().add(takenvalue);

frame.getContentPane().add(queuedepthLable);
frame.getContentPane().add(queuedepth);
frame.getContentPane().add(errormsgLable);
frame.getContentPane().add(errormsg);



frame.getContentPane().add(button);
frame.getContentPane().add(button2);
frame.getContentPane().add(button3);
frame.getContentPane().add(tarea);

button.addActionListener(this);
button2.addActionListener(this);
button3.addActionListener(this);

frame.setSize(550,550);
frame.setVisible(true);



}


public void actionPerformed(ActionEvent event){
if(event.getSource() == button)
{
int value = Integer.parseInt(putvalue.getText());
if(qs.queueDepth() == 5){
errormsg.setText("Queue is full");
}
qs.putValue(value);
queuedepth.setText(qs.queueDepth()+"");
}else if(event.getSource() == button2){
if(qs.queueDepth() == 0){
errormsg.setText("Queue is empty");
}
takenvalue.setText(qs.takenValue()+"");
queuedepth.setText(qs.queueDepth()+"");
System.out.println("vvvvv"+qs.queueDepth());
}else if(event.getSource() == button3){
tarea.setText(qs.toString());
}


}


public static void main(String arg[]){
TestQueueIntSimple tqs = new TestQueueIntSimple();
}
}




----------------------------------

public class QueueIntSimple {
private int queue[]; //array in int
private int capacity; //capacity of the queue
private int count; //indicates number of elements currently stored in the queue
// elements[0] is front, elements[count-1] is back

public QueueIntSimple() {
queue = new int[5];
capacity =5;
}


public int getSize() { return count; }
public boolean isEmpty() { return count==0; }
public boolean isFull() { return count == capacity; }


public void putValue(int value) {
if(isFull()) {
System.out.println("Queue is full");
return;
}
System.out.println("Inserting " + value + " at Queue[" + count + "]");
queue[count++]=value;
}


public int poll() {
if(isEmpty()) {
System.out.println("Poll:Queue is empty");

}
return queue[0];
}


public int takenValue() {
int item = poll();
count--;
// shift elements up
for(int i=0; i queue[i] = queue[i + 1];
}
return item;
}

public int queueDepth() {
int depth = 0;
for(int i=0; i<5; i++) {
if(0< queue[i]){
depth++;
}
}
return depth;
}


public String toString() {
String s = "";
for(int i = 0; i if (queue[i] > 0) {
s =s+"Queue["+i+"] : "+queue[i]+"\n";
}
}
return s;
}

public static void main(String ar[]){
QueueIntSimple qs = new QueueIntSimple();
qs.putValue(4);
qs.putValue(2);
qs.putValue(1);

System.out.println(qs.toString());

qs.takenValue();

System.out.println(qs.toString());

}
}

Solution for table

Movies
Theater Date Time Capacity DisplayType Title Length Rating
1 25-Feb-08 7:00 PM 300 Digital Data Projector 27 Dresses 01:47 PG-13
1 25-Feb-08 9:00 PM 300 Digital Data Projector 27 Dresses 01:47 PG-13
1 25-Feb-08 11:00 PM 300 Digital Data Projector 27 Dresses 01:47 PG-13
2 25-Feb-08 7:00 PM 200 Film Projector Welcome Home Roscoe Jenkins 01:54 PG-13
2 25-Feb-08 9:15 PM 200 Film Projector Welcome Home Roscoe Jenkins 01:54 PG-13
2 25-Feb-08 11:30 PM 200 Film Projector Welcome Home Roscoe Jenkins 01:54 PG-13
3 25-Feb-08 5:00 PM 150 Digital Data Projector 27 Dresses 01:47 PG-13
3 25-Feb-08 7:00 PM 150 Digital Data Projector 27 Dresses 01:47 PG-13
3 25-Feb-08 9:00 PM 150 Digital Data Projector Chronicles of Riddick 01:37 PG
3 25-Feb-08 11:00 PM 150 Digital Data Projector Chronicles of Riddick 01:37 PG
4 25-Feb-08 6:30 PM 200 Film Projector No Country for Old Men 02:02 R
4 25-Feb-08 9:00 PM 200 Film Projector No Country for Old Men 02:02 R
4 25-Feb-08 11:30 PM 200 Film Projector No Country for Old Men 02:02 R
5 25-Feb-08 7:00 PM 250 Digital Data Projector Welcome Home Roscoe Jenkins 01:54 PG-13
5 25-Feb-08 10:00 PM 250 Digital Data Projector No Country for Old Men 02:02 R
1 26-Feb-08 7:00 PM 300 Digital Data Projector Jumper 01:28 PG-13
1 26-Feb-08 8:45 PM 300 Digital Data Projector Jumper 01:28 PG-13
etc…



----------------------------

Books
ISBN Title Author1 Author2 Author3
1879389873 Learn UNIX in 28 days Jones, Mary Smith, Frank
8737734222 The Civil War: Brother Against Brother Templeton, Hank Templeton, Frank
9873483122 Database Security and Encryption Johnson, Fred Lee, Kirby Neeves, Whitney
1298834831 The Future of Planet Earth Scotten, Raymond
etc…

Wednesday, March 25, 2009

Solution




Lab1– Queue Data Structure
You have now used the stack class as part of your lab work. The stack concept is a very common algorithm which uses the inventory concept of last in first out (LIFO). The last item pushed onto the stack is the first item popped off the stack.

One implementation of the Queue problem is shown in the Queue Example folder. Create a command prompt window and type java TestQueue. Notice how read-only JTextFields are grayed out so that the user cannot write into those objects. Also notice that pressing the ENTER key when entering data creates an event which does the same as pressing the Button object. This makes entering data very fast into the GUI.

Another useful algorithm would be a class that would provide an inventory of first in first out (FIFO) commonly called a queue.












Here is an example of FIFO which follows the diagrams above:
1. Put a 5
2. Put a 45
3. Put a 12
4. Take a 5
5. Take a 45
6. Take a 12
7. FIFO inventory empty

Note the first item 5 is the first item to be removed.

The assignment is to create a queue class which incorporates the FIFO storage method. You might consider the stack class as a starting model. If you did that you would be able to use the concept of a put() which would be similar to the push() from the stack class but the creation of a take() would be very different than the pop() from the stack class. The take(), to duplicate the above pictorial example, would take the bottom item and then need to shift all the current inventory down one cell and reduce the depth of the inventory by one.

The queue will be only a maximum of five deep for ease of testing and will only store integers.

Of course, be sure to provide the ability to not over flow the inventory system or to protect from taking data from an empty inventory system.

Create a test Java GUI application to test the above class. Give the user the ability to Put into the queue, Take from a queue or Display the current contents of the queue. There should be confirming data indicating the number of items currently in the stack after each put() or take(). There should be a message generated if the stack is overflowed or empty.

The project should have a file containing the class QueueIntSimple, a file containing the extended Application class to test the class (e.g. TestQueueIntSimple). Don’t forget to supply proof of your program as part of what you turn in.

The GUI applet or application might look like the follow diagram:






















Note 1 – the use of a “Display Queue” button, that each time pressed will display the current contents of the queue as text in the window frame as shown.

Note 2 – the Queue class should be a non-GUI application that provides only the behavior specified above. The Test Queue class should be the GUI application designed to test the Queue class. It can also contain the main() method required by all Java applications.

LAB 2 This would be an expansion of the FIFO class design of Lab 5. Here you would consider two types of data to be stored in inventory; one type of data would have a higher priority. The higher priority data would be retrived on a FIFO basis before standard data is retrived.

There are several design approches to this problem. A couple are discussed here. The first is to create two queues, one to hold the standard priority data and a second queue to hold the high priority data. The second method would use only one queue and place data at the end of the queue if standard data or to insert the high priority data at the proper location in the queue.

The first method is based on removing data from the beginning of the high priory queue if there is any data there before removing data from the standard priority queue. The put processes would place data at the end of each appropreate queue. From the user’s perspective, there is only a single queue with two priorities when implementing this approach.

With the second method there might be a put_high() method would place data ahead of data placed with put(). Of course put_high() data would not be placed ahead of other put_high() data already in inventory. The take() method would still take data from the beginning of the array, no matter what type of data. You might consider the need to keep track of both the total count in inventory as well as the count_high of total number of high priority data items in inventory

The queue(s) will be only ten deep for ease of testing and will only store integers. Design note – a total of 10 items can be stored in the data queue at any one point in time independent of the implementation choice chosen. The 10 items could be all high-priority data, all low-priority data or any combination of the two.

The project should have a file(s) containing the class(es), a file containing the test program to demonstrate the developed class(es). Don’t forget to supply proof of your program as part of what you turn in. Remember that Alt button with Prnt Scrn button captures the active window to the Windows clip board memory for pasting in a program like Word.



Lab 3 The instructor recommends invoking the example in the “Inheritance Example” folder – java TestEmployee.

The following will be the inheritance for the Employee class:










The Person class will have the data String for name and a means to get and set the name. The Employee class will extend from Person and add the capabilities to have an employee number as an int and an employee salary as a double.

Create an array of 100 Employees. Then create a user interface that will display a means for entering in the data and then saving the data to one of the Employee array objects. The “Save Employee” button will save the data to the array. The “Forward” and “Back” button will allow the user to move and display the current data in each array object. The “Clear Employee” button will allow the users to null out the String for the name, and set the salary and employee number to zero.

The project should have a file(s) containing the class(es), a file containing the test program to demonstrate the developed class(es). Don’t forget to supply proof of your program as part of what you turn in. Remember that Alt button with Prnt Scrn button captures the active window to the Windows clip board memory for pasting in a program like Word.


EXTRA CREDIT
Lab Simple inheritance program. Refer to the Test.java code below and run the Java console application found in FirstLookAnimals.


















The Unified Modeling Language (UML) notation to represent inheritance is an arrow from the derived class to the base class as shown in th above diagram.

A very simple start to understanding polymorphism will be found in the subdirectory to this lab called Shapes. Go take a look.

The following code is the starting code for the test program. Please add the ability to supply how many animals to create rather that my hard coded 10. Also give the user the opportunity to loop to select another number of animals to create. The Test.java program should also be converted from a console to GUI application.

//Test.java

//FirstLook at inheritance.
//Thing.java, Animal.java, Dog.java, Cat.java, Rabbit.java
//and Test.java make up this first simple example.

public class Test extends Object
{
public static void main( String args[] )
{
System.out.println( "Welcome to simple inheritance Test!" );

Animal barnyard[];
barnyard = new Animal[10];//cannot use Thing as it cannot speak()

for( int z = 0; z < 10; z++)//proof of dynamic binding at run time!!!!
{ //10 could be a variable selected by user
//fewer selections as Animal cannot be used
int selection = ( int ) ( Math.random() * 4 );//0 through 3

switch( selection )
{
case 0:
barnyard[z] = new Dog(); //child to parent
break;
case 1:
barnyard[z] = new Cat(); //child to parent
break;
case 2:
barnyard[z] = new Rabbit();//child to parent
break;
case 3:
barnyard[z] = new Animal();//parent to parent
break;
}//end switch

}//end for

for( int z = 0; z < 10; z++)
{
barnyard[z].name();
barnyard[z].speak();

}//end for
System.out.println();
}//end main
}//end Test class
/* proof
Welcome to simple inheritance Test!

Cat Meow
Dog Woof
Animal Blank
Cat Meow
Animal Blank
Animal Blank
Rabbit Wiggle Nose
Animal Blank
Cat Meow
Rabbit Wiggle Nose
*/

You are to write the classes that support the above Test.java program and produce a proof similar to that shown above. The classes in the project will be Thing, Animal, Cat, Rabbit and Dog. You must write the Animal, Cat, Rabbit, Dog and revise Test.

The Thing class extends Object. The Animal class extends Thing. Finally, Cat, Rabbit and Dog extend Animal.

I will start you out with the code for Thing.
//Thing.java

public class Thing extends Object
{
public void name()
{
System.out.print("\nThing");
}

}//end Thing

You will need to add the ability to speak() to each of the other classes, which can be simply a System.out.print("\nWoof"); if it was the Dog class, for example.

Here is a suggested window:

















Every time you press the Display button you generate the selected number of animal types. Place the output in a scrolling text area. Add number in front of the animal types to keep track of what is happening to the output.