diff --git a/src/main/java/net/berack/upo/ai/problem3/LikelihoodWeightingGUI.java b/src/main/java/net/berack/upo/ai/problem3/LikelihoodWeightingGUI.java index f76141c..ff664a4 100644 --- a/src/main/java/net/berack/upo/ai/problem3/LikelihoodWeightingGUI.java +++ b/src/main/java/net/berack/upo/ai/problem3/LikelihoodWeightingGUI.java @@ -3,14 +3,16 @@ package net.berack.upo.ai.problem3; import java.awt.Dimension; import java.awt.FileDialog; import java.awt.Font; +import java.util.Collection; +import javax.swing.BorderFactory; import javax.swing.GroupLayout; import javax.swing.JFrame; -import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JPanel; import javax.swing.JSeparator; +import javax.swing.JTextArea; import net.berack.upo.ai.MyPanel; @@ -21,8 +23,9 @@ import net.berack.upo.ai.MyPanel; public class LikelihoodWeightingGUI extends MyPanel { private LikelihoodWeighting lw = null; + private OutcomeChartGUI[] chartGUI = null; - private final JPanel scroll = new JPanel(); + private final JPanel scroll = new JPanel(); // tried using JScrollPane but nothing shows up private final int totalRuns = 1000; /** @@ -61,6 +64,7 @@ public class LikelihoodWeightingGUI extends MyPanel { try { var net = SmileLib.getNetworkFrom(fileName); this.lw = new LikelihoodWeighting(net); + this.chartGUI = null; this.updateLW(); } catch (Exception e) { e.printStackTrace(); @@ -72,8 +76,23 @@ public class LikelihoodWeightingGUI extends MyPanel { */ private void updateLW() { this.lw.updateNetwork(totalRuns); - var nodes = this.lw.getAllNodes(); + + if(chartGUI == null) buildPanel(nodes); + + var i = 0; + for(var node : nodes) chartGUI[i++].updateValues(node.values, node.evidence); + + this.invalidate(); + this.validate(); + this.repaint(); + } + + /** + * Crea il pannello da zero usando i nodi passati in input come valori + * @param nodes i nodi da mostrare + */ + private void buildPanel(Collection nodes) { var panel = new JPanel(); var layout = new GroupLayout(panel); @@ -84,16 +103,31 @@ public class LikelihoodWeightingGUI extends MyPanel { var gBarch = layout.createParallelGroup(); var vGroup = layout.createSequentialGroup(); + this.chartGUI = new OutcomeChartGUI[nodes.size()]; + var i = 0; + for(var node : nodes) { - var label = new JLabel(node.name); - var barch = new OutcomeChartGUI(node, i -> { - if(node.evidence == i) node.net.clearEvidence(node.handle); - else node.net.setEvidence(node.handle, i); + var net = node.net; + var handle = node.handle; + + var label = new JTextArea(node.name); + label.setEditable(false); + label.setLineWrap(true); + label.setWrapStyleWord(true); + label.setOpaque(false); + label.setBorder(BorderFactory.createEmptyBorder()); + + var barch = new OutcomeChartGUI(node.outcomes, e -> { + if(net.isEvidence(handle) && net.getEvidence(handle) == e) + net.clearEvidence(handle); + else net.setEvidence(handle, e); this.updateLW(); }); + this.chartGUI[i++] = barch; var font = label.getFont(); - label.setFont(new Font(font.getName(), font.getStyle(), font.getSize() + 4)); + font = new Font(font.getName(), Font.BOLD, font.getSize() + 2); + label.setFont(font); gLabel.addComponent(label); gBarch.addComponent(barch); @@ -108,13 +142,13 @@ public class LikelihoodWeightingGUI extends MyPanel { layout.setVerticalGroup(vGroup); layout.setHorizontalGroup(hGroup); + var sizes = this.scroll.getPreferredSize(); + sizes.height = panel.getMinimumSize().height; + sizes.width -= 10; + panel.setPreferredSize(sizes); + this.scroll.removeAll(); this.scroll.add(panel); - this.repaint(); - - this.invalidate(); - this.validate(); - this.repaint(); } @Override @@ -124,17 +158,19 @@ public class LikelihoodWeightingGUI extends MyPanel { var open = new JMenuItem("Open"); open.addActionListener(action -> this.openFile()); - var net1 = new JMenuItem("WetGrass net"); - net1.addActionListener(action -> this.openFile("lw/WetGrass.xdsl")); + var nets = new JMenuItem[3]; + nets[0] = new JMenuItem("Alarm net"); + nets[0].addActionListener(action -> this.openFile("lw/Alarm.xdsl")); - var net2 = new JMenuItem("Malaria net"); - net2.addActionListener(action -> this.openFile("lw/Malaria.xdsl")); + nets[1] = new JMenuItem("WetGrass net"); + nets[1].addActionListener(action -> this.openFile("lw/WetGrass.xdsl")); + nets[2] = new JMenuItem("Malaria net"); + nets[2].addActionListener(action -> this.openFile("lw/Malaria.xdsl")); menu.add(open); menu.add(new JSeparator()); - menu.add(net1); - menu.add(net2); + for(var net : nets) menu.add(net); return menu; } diff --git a/src/main/java/net/berack/upo/ai/problem3/NetworkNode.java b/src/main/java/net/berack/upo/ai/problem3/NetworkNode.java index 195747e..08c86c3 100644 --- a/src/main/java/net/berack/upo/ai/problem3/NetworkNode.java +++ b/src/main/java/net/berack/upo/ai/problem3/NetworkNode.java @@ -37,7 +37,7 @@ public class NetworkNode { NetworkNode(Network net, int handle, Map nodes) { this.handle = handle; this.type = net.getNodeType(handle); - this.name = net.getNodeId(handle); + this.name = net.getNodeName(handle); this.net = net; this.outcomes = net.getOutcomeIds(handle); diff --git a/src/main/java/net/berack/upo/ai/problem3/OutcomeChartGUI.java b/src/main/java/net/berack/upo/ai/problem3/OutcomeChartGUI.java index 83b1fdf..2b577f2 100644 --- a/src/main/java/net/berack/upo/ai/problem3/OutcomeChartGUI.java +++ b/src/main/java/net/berack/upo/ai/problem3/OutcomeChartGUI.java @@ -8,6 +8,7 @@ import java.util.function.Consumer; import javax.swing.BorderFactory; import javax.swing.JButton; +import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.border.EmptyBorder; @@ -26,39 +27,45 @@ public class OutcomeChartGUI extends JPanel { new Color(127,255,0), }; + private JButton[] outcomes; + private Label[] valuesChart; + private JLabel[] valuesPercent; + /** * Crea il JPanel da visualizzare a partire da un NetworkNode appropriamente inizializzato. * Quando verrà visualizzato, il nodo avrà il nome degli output e i suoi valori in % * con una barra colorata per indicare la grandezza visivamente. * - * @param node il nodo di cui si vogliono visualizzare gli outcome + * @param labels i label degli output del nodo * @param action una azione da fare nel caso in cui venga premuto su un outcome */ - public OutcomeChartGUI(NetworkNode node, Consumer action) { - var labels = node.outcomes; - var values = node.values; - - if(labels.length != values.length) throw new IllegalArgumentException("Arrays length myst be equals!"); - this.setBorder(BorderFactory.createCompoundBorder(new EmptyBorder(1, 0, 0, 0), BorderFactory.createLineBorder(Color.GRAY))); - + public OutcomeChartGUI(String[] labels, Consumer action) { var layout = new GridLayout(labels.length, 2); this.setLayout(layout); + this.setBorder(BorderFactory.createCompoundBorder(new EmptyBorder(1, 0, 0, 0), BorderFactory.createLineBorder(Color.GRAY))); + + this.outcomes = new JButton[labels.length]; + this.valuesChart = new Label[labels.length]; + this.valuesPercent = new JLabel[labels.length]; for(var i = 0; i < labels.length; i++) { - var value = values[i] * 100; - var lName = new JButton(labels[i]); - var lValue = new Label(String.format("% 4.2f%%", value)); + var lValue = new JLabel(); var barchart = new Label(); - var size = barchart.getPreferredSize(); + + this.outcomes[i] = lName; + this.valuesChart[i] = barchart; + this.valuesPercent[i] = lValue; final var index = i; lName.setContentAreaFilled(false); lName.setFocusable(false); - lName.addActionListener(a -> action.accept(index)); - if(node.evidence == i) lName.setForeground(Color.RED); + if(action == null) lName.setBorder(null); + else lName.addActionListener(a -> action.accept(index)); - size.width = (int) (value * 1.5); + var size = barchart.getPreferredSize(); + size.width = 100; + size.height = 100; barchart.setPreferredSize(size); barchart.setBackground(COLORS[i % COLORS.length]); @@ -76,4 +83,28 @@ public class OutcomeChartGUI extends JPanel { this.add(panel2); } } + + /** + * Modifica i valori mostrati a schermo cambiando anche la grandezza + * della barra indicante il valore + * @param values i nuovi valori da mostrare + * @param evidence indica l'evidenza del nodo + */ + public void updateValues(double[] values, int evidence) { + if(this.outcomes.length != values.length) throw new IllegalArgumentException("Arrays length myst be equals!"); + + for(var i = 0; i < this.outcomes.length; i++) { + var value = values[i] * 100; + var barchart = this.valuesChart[i]; + + var size = barchart.getSize(); + size.width = (int) (value * 1.5); + barchart.setSize(size); + barchart.setPreferredSize(size); + + this.valuesPercent[i].setText(String.format("% 4.2f%%", value)); + if(evidence == i) this.outcomes[i].setForeground(Color.RED); + else this.outcomes[i].setForeground(Color.BLACK); + } + } } diff --git a/src/main/resources/lw/Alarm.xdsl b/src/main/resources/lw/Alarm.xdsl new file mode 100644 index 0000000..54daa50 --- /dev/null +++ b/src/main/resources/lw/Alarm.xdsl @@ -0,0 +1,92 @@ + + + + + + + + 0.001 0.9990000000000001 + + + + + 0.002 0.998 + + + + + Burglary Earthquake + 0.95 0.05000000000000004 0.9399999999999999 0.06000000000000005 0.29 0.71 0.001 0.999 + + + + + Alarm + 0.9 0.09999999999999998 0.05 0.95 + + + + + Alarm + 0.7 0.3 0.001 0.999 + + + + + Earthquake + 0.9 0.09999999999999998 0.01 0.99 + + + + + + Burglary + + + + 55 39 141 92 + + + + Alarm + + + + 178 176 248 219 + + + + Earthquake + + + + 259 32 368 100 + + + + JohnCall + + + + 46 290 139 345 + + + + MaryCall + + + + 302 286 391 341 + + + + Radio + + + + 441 176 512 220 + + + + +