GUI
- renamed LW to the correct name - copied two nets as resources - removed unnecessary code in NetworkNode - Created MainGUI - changed some code in SmileLib
This commit is contained in:
@@ -1,38 +0,0 @@
|
||||
package net.berack.upo.ai;
|
||||
|
||||
import java.util.Scanner;
|
||||
import java.util.function.Function;
|
||||
|
||||
import net.berack.upo.ai.problem1.Puzzle8GUI;
|
||||
import net.berack.upo.ai.problem2.TrisGUI;
|
||||
|
||||
public class Main {
|
||||
|
||||
public static void main(String[] args) {
|
||||
var value = read("What do you want to play?\n1. Puzzle8\n2. Tris\n", new Scanner(System.in), num -> num > 0 && num < 2);
|
||||
var window = switch (value) {
|
||||
case 1 -> new Puzzle8GUI();
|
||||
case 2 -> new TrisGUI();
|
||||
default -> null;
|
||||
};
|
||||
|
||||
if(window != null) {
|
||||
window.toFront();
|
||||
window.requestFocus();
|
||||
}
|
||||
}
|
||||
|
||||
private static int read(String out, Scanner in, Function<Integer, Boolean> control) {
|
||||
var ret = 0;
|
||||
|
||||
do {
|
||||
try {
|
||||
System.out.print(out);
|
||||
var str = in.nextLine();
|
||||
ret = Integer.parseInt(str);
|
||||
} catch (NumberFormatException ignore) {}
|
||||
} while(!control.apply(ret));
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
92
src/main/java/net/berack/upo/ai/MainGUI.java
Normal file
92
src/main/java/net/berack/upo/ai/MainGUI.java
Normal file
@@ -0,0 +1,92 @@
|
||||
package net.berack.upo.ai;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuBar;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JSeparator;
|
||||
|
||||
import net.berack.upo.ai.decision.PrototypeGUI;
|
||||
import net.berack.upo.ai.decision.VehicleGUI;
|
||||
import net.berack.upo.ai.problem1.Puzzle8GUI;
|
||||
import net.berack.upo.ai.problem2.TrisGUI;
|
||||
import net.berack.upo.ai.problem3.LikelihoodWeightingGUI;
|
||||
|
||||
/**
|
||||
* Classe che rappresenta il main di tutto il progetto
|
||||
* In essa si può navigare in tutti gli esercizi e testarli
|
||||
* @author Berack
|
||||
*/
|
||||
public class MainGUI extends JFrame {
|
||||
|
||||
public final Puzzle8GUI Puzzle8GUI = new Puzzle8GUI();
|
||||
public final TrisGUI TrisGUI = new TrisGUI();
|
||||
public final LikelihoodWeightingGUI LikelihoodWeightingGUI = new LikelihoodWeightingGUI();
|
||||
public final PrototypeGUI PrototypeGUI = new PrototypeGUI();
|
||||
public final VehicleGUI VehicleGUI = new VehicleGUI();
|
||||
|
||||
public static void main(String[] args) {
|
||||
new MainGUI();
|
||||
}
|
||||
|
||||
private final JMenuBar menuBar = new JMenuBar();
|
||||
|
||||
/**
|
||||
* Crea una finestra con nulla da mostrare, ma si può visualizzare uno degli esercizi tramite
|
||||
* la barre dei menù che permette di cambiare da un esercizio all'altro
|
||||
*/
|
||||
private MainGUI() {
|
||||
super("Progetto per AI");
|
||||
this.buildMenu();
|
||||
this.setJMenuBar(menuBar);
|
||||
|
||||
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
this.setSize(400, 400);
|
||||
this.setResizable(false);
|
||||
this.setLocationRelativeTo(null);
|
||||
this.setVisible(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Crea la barra dei menu aggiungendo tutti i menù passati in input
|
||||
* @param menus una lista di menù da aggiungere
|
||||
*/
|
||||
private void buildMenu(JMenu...menus) {
|
||||
menuBar.removeAll();
|
||||
var menu = new JMenu("View");
|
||||
|
||||
var puzzle = new JMenuItem("Puzzle8 Game");
|
||||
puzzle.addActionListener(action -> this.setPanel(Puzzle8GUI));
|
||||
var tris = new JMenuItem("Tris Game");
|
||||
tris.addActionListener(action -> this.setPanel(TrisGUI));
|
||||
var lw = new JMenuItem("Likelihood Weighting");
|
||||
lw.addActionListener(action -> this.setPanel(LikelihoodWeightingGUI));
|
||||
var prototype = new JMenuItem("Prototype net");
|
||||
prototype.addActionListener(action -> this.setPanel(PrototypeGUI));
|
||||
var vehicle = new JMenuItem("Vehicle net");
|
||||
vehicle.addActionListener(action -> this.setPanel(VehicleGUI));
|
||||
|
||||
menu.add(puzzle);
|
||||
menu.add(tris);
|
||||
menu.add(lw);
|
||||
menu.add(new JSeparator());
|
||||
menu.add(prototype);
|
||||
menu.add(vehicle);
|
||||
|
||||
menuBar.add(menu);
|
||||
for(var m : menus) menuBar.add(m);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cambia il pannello principale con quello passato in input
|
||||
* @param panel il pannello da mostrare
|
||||
*/
|
||||
private void setPanel(MyPanel panel) {
|
||||
this.setContentPane(panel);
|
||||
this.buildMenu(panel.getMenu());
|
||||
this.pack();
|
||||
this.invalidate();
|
||||
this.validate();
|
||||
this.repaint();
|
||||
}
|
||||
}
|
||||
20
src/main/java/net/berack/upo/ai/MyPanel.java
Normal file
20
src/main/java/net/berack/upo/ai/MyPanel.java
Normal file
@@ -0,0 +1,20 @@
|
||||
package net.berack.upo.ai;
|
||||
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
/**
|
||||
* Classe utilizzata per far si che tutti i frame della finestra abbiano lo stesso metodo
|
||||
* per la generazione dei menu.
|
||||
* @author Berack
|
||||
*/
|
||||
public abstract class MyPanel extends JPanel {
|
||||
|
||||
/**
|
||||
* Crea un menu da aggiungere alla lista, in modo che appaia solamente quando
|
||||
* la finestra venga utilizzata.
|
||||
* Questo metodo viene usato solo dalla finestra MainGUI
|
||||
* @return il menu contestuale da aggiungere
|
||||
*/
|
||||
abstract public JMenu getMenu();
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package net.berack.upo.ai.decision;
|
||||
|
||||
public class ConsoleInterface {
|
||||
|
||||
}
|
||||
20
src/main/java/net/berack/upo/ai/decision/PrototypeGUI.java
Normal file
20
src/main/java/net/berack/upo/ai/decision/PrototypeGUI.java
Normal file
@@ -0,0 +1,20 @@
|
||||
package net.berack.upo.ai.decision;
|
||||
|
||||
import javax.swing.JMenu;
|
||||
|
||||
import net.berack.upo.ai.MyPanel;
|
||||
|
||||
/**
|
||||
* Classe che mostra le decisioni possibili, insieme ai guadagni
|
||||
* per la rete Prototipo.xdsl
|
||||
* @author Berack
|
||||
*/
|
||||
public class PrototypeGUI extends MyPanel {
|
||||
|
||||
@Override
|
||||
public JMenu getMenu() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'getMenu'");
|
||||
}
|
||||
|
||||
}
|
||||
19
src/main/java/net/berack/upo/ai/decision/VehicleGUI.java
Normal file
19
src/main/java/net/berack/upo/ai/decision/VehicleGUI.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package net.berack.upo.ai.decision;
|
||||
|
||||
import javax.swing.JMenu;
|
||||
|
||||
import net.berack.upo.ai.MyPanel;
|
||||
|
||||
/**
|
||||
* Classe che mostra le decisioni possibili, insieme ai guadagni
|
||||
* per la rete Veicolo.xdsl
|
||||
*/
|
||||
public class VehicleGUI extends MyPanel {
|
||||
|
||||
@Override
|
||||
public JMenu getMenu() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'getMenu'");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,31 +1,25 @@
|
||||
package net.berack.upo.ai.problem1;
|
||||
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuBar;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import net.berack.upo.ai.problem1.Puzzle8.Move;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.GridLayout;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuItem;
|
||||
|
||||
import net.berack.upo.ai.MyPanel;
|
||||
import net.berack.upo.ai.problem1.Puzzle8.Move;
|
||||
|
||||
/**
|
||||
* Classe che permette di visualizzare graficamente il gioco Puzzle8
|
||||
* In questa classe si trova un main che crea una istanza di questa finestra
|
||||
*
|
||||
* @author Berack96
|
||||
*/
|
||||
public class Puzzle8GUI extends JFrame {
|
||||
|
||||
public static void main(String[] args) {
|
||||
new Puzzle8GUI();
|
||||
}
|
||||
public class Puzzle8GUI extends MyPanel {
|
||||
|
||||
/**
|
||||
* Carica staticamente le immagini necessarie per giocare al gioco
|
||||
@@ -50,49 +44,20 @@ public class Puzzle8GUI extends JFrame {
|
||||
* Come default viene creato il puzzle "GOAL" ovvero non mescolato.
|
||||
*/
|
||||
public Puzzle8GUI() {
|
||||
super("Puzzle 8 game");
|
||||
super();
|
||||
|
||||
var grid = new GridLayout(Puzzle8.LENGTH, Puzzle8.LENGTH);
|
||||
grid.setHgap(6);
|
||||
grid.setVgap(grid.getHgap());
|
||||
|
||||
var panel = new JPanel(grid);
|
||||
this.setLayout(grid);
|
||||
for(var i = 0; i < Puzzle8.LENGTH; i++) {
|
||||
for(var j = 0; j < Puzzle8.LENGTH; j++) {
|
||||
var comp = new MyComponent(Puzzle8.LENGTH, j, i);
|
||||
panel.add(comp);
|
||||
this.add(comp);
|
||||
this.buttons[j][i] = comp;
|
||||
}
|
||||
}
|
||||
|
||||
this.add(panel);
|
||||
this.attachMenu();
|
||||
|
||||
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
this.pack();
|
||||
this.setResizable(false);
|
||||
this.setLocationRelativeTo(null);
|
||||
this.setVisible(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Metodo utile per non mettere tutto nel costruttore.
|
||||
* Qui viene creata la menubar
|
||||
*/
|
||||
private void attachMenu() {
|
||||
var menuBar = new JMenuBar();
|
||||
|
||||
var menu1 = new JMenu("Game");
|
||||
var item1 = new JMenuItem("Shuffle");
|
||||
item1.addActionListener(action -> this.shuffleGame());
|
||||
menu1.add(item1);
|
||||
|
||||
var item2 = new JMenuItem("Show solution");
|
||||
item2.addActionListener(action -> this.solveGame());
|
||||
menu1.add(item2);
|
||||
|
||||
menuBar.add(menu1);
|
||||
this.setJMenuBar(menuBar);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -194,4 +159,18 @@ public class Puzzle8GUI extends JFrame {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JMenu getMenu() {
|
||||
var menu = new JMenu("Game");
|
||||
var item1 = new JMenuItem("Shuffle");
|
||||
item1.addActionListener(action -> this.shuffleGame());
|
||||
menu.add(item1);
|
||||
|
||||
var item2 = new JMenuItem("Show solution");
|
||||
item2.addActionListener(action -> this.solveGame());
|
||||
menu.add(item2);
|
||||
|
||||
return menu;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
package net.berack.upo.ai.problem2;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.GridLayout;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JCheckBoxMenuItem;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuBar;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JSeparator;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.GridLayout;
|
||||
import net.berack.upo.ai.MyPanel;
|
||||
|
||||
/**
|
||||
* Classe che permette di visualizzare graficamente il gioco Tris
|
||||
@@ -20,11 +19,7 @@ import java.awt.GridLayout;
|
||||
*
|
||||
* @author Berack96
|
||||
*/
|
||||
public class TrisGUI extends JFrame {
|
||||
|
||||
public static void main(String[] args) {
|
||||
new TrisGUI();
|
||||
}
|
||||
public class TrisGUI extends MyPanel {
|
||||
|
||||
/**
|
||||
* Caricamento statico delle immagini
|
||||
@@ -57,54 +52,17 @@ public class TrisGUI extends JFrame {
|
||||
* Come default viene abilitata la AI come secondo giocatore.
|
||||
*/
|
||||
public TrisGUI() {
|
||||
super("Tris");
|
||||
super();
|
||||
|
||||
var grid = new GridLayout(Tris.LENGTH, Tris.LENGTH);
|
||||
var panel = new JPanel(grid);
|
||||
this.setLayout(grid);
|
||||
for(var i = 0; i < Tris.LENGTH; i++) {
|
||||
for(var j = 0; j < Tris.LENGTH; j++) {
|
||||
var comp = new MyComponent(Tris.LENGTH, j, i);
|
||||
panel.add(comp);
|
||||
this.add(comp);
|
||||
this.buttons[j][i] = comp;
|
||||
}
|
||||
}
|
||||
|
||||
this.add(panel);
|
||||
this.attachMenu();
|
||||
|
||||
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
this.pack();
|
||||
this.setResizable(false);
|
||||
this.setLocationRelativeTo(null);
|
||||
this.setVisible(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Metodo utile per non mettere tutto nel costruttore.
|
||||
* Qui viene creata la menubar
|
||||
*/
|
||||
private void attachMenu() {
|
||||
var menuBar = new JMenuBar();
|
||||
|
||||
var menu1 = new JMenu("Game");
|
||||
var item1 = new JMenuItem("Reset");
|
||||
item1.addActionListener(action -> this.reset());
|
||||
menu1.add(item1);
|
||||
|
||||
var separator = new JSeparator();
|
||||
menu1.add(separator);
|
||||
|
||||
var item2 = new JCheckBoxMenuItem("AI Enabled");
|
||||
item2.setSelected(this.ai != null);
|
||||
item2.addChangeListener(action -> this.ai = item2.getState()? new TrisAi(this.tris):null);
|
||||
menu1.add(item2);
|
||||
|
||||
this.aiFirst = new JCheckBoxMenuItem("AI First");
|
||||
this.aiFirst.setSelected(false);
|
||||
menu1.add(this.aiFirst);
|
||||
|
||||
menuBar.add(menu1);
|
||||
this.setJMenuBar(menuBar);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -175,4 +133,26 @@ public class TrisGUI extends JFrame {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JMenu getMenu() {
|
||||
var menu = new JMenu("Game");
|
||||
var item1 = new JMenuItem("Reset");
|
||||
item1.addActionListener(action -> this.reset());
|
||||
menu.add(item1);
|
||||
|
||||
var separator = new JSeparator();
|
||||
menu.add(separator);
|
||||
|
||||
var item2 = new JCheckBoxMenuItem("AI Enabled");
|
||||
item2.setSelected(this.ai != null);
|
||||
item2.addChangeListener(action -> this.ai = item2.getState()? new TrisAi(this.tris):null);
|
||||
menu.add(item2);
|
||||
|
||||
this.aiFirst = new JCheckBoxMenuItem("AI First");
|
||||
this.aiFirst.setSelected(false);
|
||||
menu.add(this.aiFirst);
|
||||
|
||||
return menu;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
package net.berack.upo.ai.problem3;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import smile.Network;
|
||||
|
||||
/**
|
||||
* Calcolo dei valori tramite l'algoritmo del Likelyhood Weighting
|
||||
* Calcolo dei valori tramite l'algoritmo del Likelihood Weighting
|
||||
* @author Berack
|
||||
*/
|
||||
public class LikelyhoodWeighting {
|
||||
public class LikelihoodWeighting {
|
||||
|
||||
public final Network net;
|
||||
private final Map<Integer, NetworkNode> nodes = new HashMap<>();
|
||||
@@ -19,14 +21,14 @@ public class LikelyhoodWeighting {
|
||||
* Inizializza un nuovo oggetto che calcolerà i valori per la rete inserita
|
||||
* @param net la rete a cui calcolare i valori
|
||||
*/
|
||||
public LikelyhoodWeighting(Network net) {
|
||||
public LikelihoodWeighting(Network net) {
|
||||
this.net = Objects.requireNonNull(net);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recupera i valori del nodo dopo averli calcolati
|
||||
* Nel caso in cui non si abbia ancora fatto {@link #updateNetwork(int)} allora restituirà
|
||||
* una eccezione di tiop UnsupportedOperationException
|
||||
* una eccezione di tipo UnsupportedOperationException
|
||||
* @param node il nodo da vedere
|
||||
* @return l'array di valori da restituire
|
||||
*/
|
||||
@@ -35,6 +37,17 @@ public class LikelyhoodWeighting {
|
||||
return nodes.get(node).values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Permette di recuperare tutti i nodi.
|
||||
* Nel caso in cui non si abbia ancora fatto {@link #updateNetwork(int)} allora restituirà
|
||||
* una eccezione di tipo UnsupportedOperationException
|
||||
* @return Una collezione di tutti i nodi.
|
||||
*/
|
||||
public Collection<NetworkNode> getAllNodes() {
|
||||
if(nodes.size() == 0) throw new UnsupportedOperationException("You should run first updateNetwork method");
|
||||
return this.nodes.values();
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcola i valori possibili per la rete.
|
||||
* Per poterli vedere utilizzare il metodo {@link #getNodeValue(int)}
|
||||
@@ -74,4 +87,9 @@ public class LikelyhoodWeighting {
|
||||
node.values[i] /= sum;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.nodes.values().toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
package net.berack.upo.ai.problem3;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.FileDialog;
|
||||
import java.awt.Font;
|
||||
|
||||
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 net.berack.upo.ai.MyPanel;
|
||||
|
||||
/**
|
||||
* Classe usata per far vedere il risultato di una run di lw su un network
|
||||
* @author Berack
|
||||
*/
|
||||
public class LikelihoodWeightingGUI extends MyPanel {
|
||||
|
||||
private LikelihoodWeighting lw = null;
|
||||
|
||||
private final JPanel scroll = new JPanel();
|
||||
private final int totalRuns = 1000;
|
||||
|
||||
/**
|
||||
* Crea il pannello con gli elementi di default.
|
||||
* Siccome non c'è nessun network, il pannello sarà vuoto finchè non si apriranno dei network
|
||||
*/
|
||||
public LikelihoodWeightingGUI() {
|
||||
this.scroll.setPreferredSize(new Dimension(500, 400));
|
||||
this.add(this.scroll);
|
||||
}
|
||||
|
||||
/**
|
||||
* Crea una finestra di dialog per la richiesta di un file.
|
||||
* Il file richiesto è in forma .xdsl
|
||||
*/
|
||||
public void openFile() {
|
||||
var parent = this.getParent();
|
||||
while(parent.getParent() != null) parent = parent.getParent();
|
||||
if(!(parent instanceof JFrame)) throw new IllegalArgumentException(parent.getClass().getName());
|
||||
|
||||
var dialog = new FileDialog((JFrame) parent, "Select net");
|
||||
dialog.setLocationRelativeTo(null);
|
||||
dialog.setFile("*.xdsl");
|
||||
dialog.setMode(FileDialog.LOAD);
|
||||
dialog.setVisible(true);
|
||||
|
||||
if(dialog.getFile() != null) this.openFile(dialog.getDirectory() + dialog.getFile());
|
||||
}
|
||||
|
||||
/**
|
||||
* Carica il file indicato nella finestra, esegue l'algoritmo e mostra i risultati
|
||||
* @param fileName il nome del file
|
||||
*/
|
||||
public void openFile(String fileName) {
|
||||
|
||||
try {
|
||||
var net = SmileLib.getNetworkFrom(fileName);
|
||||
this.lw = new LikelihoodWeighting(net);
|
||||
this.updateLW();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Esegue l'algoritmo sul network corrente e mostra i risultati
|
||||
*/
|
||||
private void updateLW() {
|
||||
this.lw.updateNetwork(totalRuns);
|
||||
|
||||
var nodes = this.lw.getAllNodes();
|
||||
var panel = new JPanel();
|
||||
var layout = new GroupLayout(panel);
|
||||
|
||||
panel.setLayout(layout);
|
||||
layout.setAutoCreateGaps(true);
|
||||
|
||||
var gLabel = layout.createParallelGroup();
|
||||
var gBarch = layout.createParallelGroup();
|
||||
var vGroup = layout.createSequentialGroup();
|
||||
|
||||
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);
|
||||
this.updateLW();
|
||||
});
|
||||
|
||||
var font = label.getFont();
|
||||
label.setFont(new Font(font.getName(), font.getStyle(), font.getSize() + 4));
|
||||
|
||||
gLabel.addComponent(label);
|
||||
gBarch.addComponent(barch);
|
||||
vGroup.addGroup(layout.createParallelGroup()
|
||||
.addComponent(label)
|
||||
.addComponent(barch));
|
||||
}
|
||||
|
||||
var hGroup = layout.createSequentialGroup();
|
||||
hGroup.addGroup(gLabel).addGroup(gBarch);
|
||||
|
||||
layout.setVerticalGroup(vGroup);
|
||||
layout.setHorizontalGroup(hGroup);
|
||||
|
||||
this.scroll.removeAll();
|
||||
this.scroll.add(panel);
|
||||
this.repaint();
|
||||
|
||||
this.invalidate();
|
||||
this.validate();
|
||||
this.repaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JMenu getMenu() {
|
||||
var menu = new JMenu("File");
|
||||
|
||||
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 net2 = new JMenuItem("Malaria net");
|
||||
net2.addActionListener(action -> this.openFile("lw/Malaria.xdsl"));
|
||||
|
||||
|
||||
menu.add(open);
|
||||
menu.add(new JSeparator());
|
||||
menu.add(net1);
|
||||
menu.add(net2);
|
||||
|
||||
return menu;
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ import smile.Network;
|
||||
public class NetworkNode {
|
||||
|
||||
final int handle;
|
||||
final String name;
|
||||
final String[] outcomes;
|
||||
final double[] definition;
|
||||
final int evidence;
|
||||
@@ -36,12 +37,16 @@ public class NetworkNode {
|
||||
NetworkNode(Network net, int handle, Map<Integer, NetworkNode> nodes) {
|
||||
this.handle = handle;
|
||||
this.type = net.getNodeType(handle);
|
||||
this.name = net.getNodeId(handle);
|
||||
this.net = net;
|
||||
|
||||
this.outcomes = net.getOutcomeIds(handle);
|
||||
this.values = new double[this.outcomes.length];
|
||||
this.evidence = net.isEvidence(handle)? net.getEvidence(handle) : -1;
|
||||
if(this.isEvidence()) this.values[this.evidence] = 1.0d;
|
||||
if(this.isEvidence()) {
|
||||
this.values[this.evidence] = 1.0d;
|
||||
this.sample = this.evidence;
|
||||
}
|
||||
|
||||
var parentsHandle = net.getParents(handle);
|
||||
this.parents = new NetworkNode[parentsHandle.length];
|
||||
@@ -111,11 +116,10 @@ public class NetworkNode {
|
||||
var tot = this.definition.length;
|
||||
|
||||
for(var p : this.parents) {
|
||||
var pIndex = p.isEvidence()? p.evidence : p.sample;
|
||||
if(pIndex < 0) throw new IllegalArgumentException("Parent"); // in theory impossible since Topological sorted
|
||||
if(p.sample < 0) throw new IllegalArgumentException("Parent"); // in theory impossible since Topological sorted
|
||||
|
||||
tot /= p.outcomes.length;
|
||||
init += tot * pIndex;
|
||||
init += tot * p.sample;
|
||||
}
|
||||
|
||||
return init;
|
||||
@@ -132,4 +136,9 @@ public class NetworkNode {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.net.getNodeId(this.handle) + "->" + Arrays.toString(this.values);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package net.berack.upo.ai.problem3;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.GridLayout;
|
||||
import java.awt.Label;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
|
||||
/**
|
||||
* Classe che rappresenta gli outcome di un nodo di un network.
|
||||
* I valori deli outcome vengono visualizzati con un grafico.
|
||||
* @author Berack
|
||||
*/
|
||||
public class OutcomeChartGUI extends JPanel {
|
||||
public static final Color[] COLORS = {
|
||||
new Color(255,127,0),
|
||||
new Color(0,127,255),
|
||||
new Color(0,255,127),
|
||||
new Color(255,0,127),
|
||||
new Color(127,0,255),
|
||||
new Color(127,255,0),
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 action una azione da fare nel caso in cui venga premuto su un outcome
|
||||
*/
|
||||
public OutcomeChartGUI(NetworkNode node, Consumer<Integer> 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)));
|
||||
|
||||
var layout = new GridLayout(labels.length, 2);
|
||||
this.setLayout(layout);
|
||||
|
||||
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 barchart = new Label();
|
||||
var size = barchart.getPreferredSize();
|
||||
|
||||
final var index = i;
|
||||
lName.setContentAreaFilled(false);
|
||||
lName.setFocusable(false);
|
||||
lName.addActionListener(a -> action.accept(index));
|
||||
if(node.evidence == i) lName.setForeground(Color.RED);
|
||||
|
||||
size.width = (int) (value * 1.5);
|
||||
barchart.setPreferredSize(size);
|
||||
barchart.setBackground(COLORS[i % COLORS.length]);
|
||||
|
||||
|
||||
var panel1 = new JPanel();
|
||||
panel1.setLayout(new GridLayout(1, 2));
|
||||
panel1.add(lName);
|
||||
panel1.add(lValue);
|
||||
|
||||
var panel2 = new JPanel();
|
||||
panel2.setLayout(new BorderLayout());
|
||||
panel2.add(barchart, BorderLayout.LINE_START);
|
||||
|
||||
this.add(panel1);
|
||||
this.add(panel2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
package net.berack.upo.ai.problem3;
|
||||
|
||||
import java.net.URLDecoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import smile.Network;
|
||||
|
||||
/**
|
||||
@@ -18,18 +20,19 @@ import smile.Network;
|
||||
*/
|
||||
public class SmileLib {
|
||||
|
||||
public static final String RESOURCE_PATH;
|
||||
static {
|
||||
var loader = SmileLib.class.getClassLoader();
|
||||
var wrongPath = loader.getResource("").getFile();
|
||||
var path = wrongPath.substring(1);
|
||||
try {
|
||||
RESOURCE_PATH = URLDecoder.decode(path, "ASCII");
|
||||
var jsmile = "jsmile";
|
||||
var loader = SmileLib.class.getClassLoader();
|
||||
var resource = loader.getResource(jsmile);
|
||||
var uri = resource.toURI();
|
||||
var path = Path.of(uri).toString();
|
||||
System.setProperty("jsmile.native.library", path);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Decodification of path failed!\n" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
System.setProperty("jsmile.native.library", RESOURCE_PATH + "jsmile");
|
||||
new smile.License(
|
||||
"SMILE LICENSE 02a07eb5 5c5fa64a 2a276459 " +
|
||||
"THIS IS AN ACADEMIC LICENSE AND CAN BE USED " +
|
||||
@@ -60,8 +63,12 @@ public class SmileLib {
|
||||
public static Network getNetworkFrom(String file) {
|
||||
var net = new Network();
|
||||
try {
|
||||
net.readFile(RESOURCE_PATH + file);
|
||||
} catch (smile.SMILEException e) {
|
||||
var loader = SmileLib.class.getClassLoader();
|
||||
var in = loader.getResourceAsStream(file);
|
||||
var str = new String(in.readAllBytes(), StandardCharsets.UTF_8);
|
||||
|
||||
net.readString(str);
|
||||
} catch (Exception e) {
|
||||
net.readFile(file);
|
||||
}
|
||||
|
||||
@@ -78,15 +85,15 @@ public class SmileLib {
|
||||
* @return una lista ordinata di nodi
|
||||
*/
|
||||
public static List<NetworkNode> buildListFrom(Network net) {
|
||||
var nodes = new HashMap<Integer, NetworkNode>();
|
||||
var list = new ArrayList<NetworkNode>();
|
||||
var nodes = new HashMap<Integer, NetworkNode>();
|
||||
var list = new ArrayList<NetworkNode>();
|
||||
|
||||
for(var handle : net.getAllNodes()) {
|
||||
var node = new NetworkNode(net, handle, nodes);
|
||||
list.add(node);
|
||||
nodes.put(handle, node);
|
||||
}
|
||||
|
||||
return list;
|
||||
for(var handle : net.getAllNodes()) {
|
||||
var node = new NetworkNode(net, handle, nodes);
|
||||
list.add(node);
|
||||
nodes.put(handle, node);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user