I want to write an Apache Spark code that completes the calculation of a PCA by adding informations on global summary value of each component, higher eigen values, individual contribution to an axis, quality of a projection of an individual on an axis.
It works. And from a vector of 50 features, it calculates them (three first individual, here) :
+-------------+-------------------------------------------+------------------------------------------+--------------------+---------------------------------------------+------------------------------------------+
|features |scaledFeatures |pca |xStdCarre |contributionIndividuelleAxe |qualiteProjectionIndividuAxe |
+-------------+-------------------------------------------+------------------------------------------+--------------------+---------------------------------------------+------------------------------------------+
|[100.0,100.0]|[3.665634766586407,3.156450874585141] |[-4.823943018707778,-0.36004738290505234] |23.400060365676286 |[0.29741427723298436,0.006561249644731516] |[0.9944600947215109,0.00553990527848926] |
|[86.1,70.3] |[2.711113911293206,0.8064410737434008] |[-2.4872869831159297,-1.3468070793732898] |8.000485845427955 |[0.07906955024417166,0.09180747147437675] |[0.773277605373604,0.22672239462639585] |
|[67.9,69.2] |[1.461309625945275,0.7194036737122256] |[-1.5419971620115105,-0.5246067298266516] |2.6529674686309654 |[0.03038957477136533,0.013929481805149522] |[0.8962624969082515,0.10373750309174866] |
Remark : the column 'features' doesn't exist anymore at the end of the process. It is removed as soon as the features are standardized. But I added this column in this example to make it more readable.
I do this calculation using few private methods :
One creates the initial features vector.
A short code then standardizes it and ask Spark to calculate the PCA from it.
Another private method calculates the higher eigen values of each component, the correlation the principal component has with the variable it summarizes, and the global quality that a principal component gives for a feature.
A last one calculates the individual contribution of each individual in the calculation of each principal component, and how fine is projected each individual on each axis.
Because I begin with ML (from spark-mllib), I think I miss out some of its important abilities that could have made my code clearer, simplier. Can you give me hints of what I should have done to create a code taking a better advantage of what Apache Spark ML can do ?
package test;
import static java.lang.Math.sqrt;
import static org.apache.spark.sql.functions.*;
import static org.apache.spark.sql.types.DataTypes.*;
import java.io.*;
import java.util.*;
import org.apache.spark.api.java.function.*;
import org.apache.spark.ml.feature.*;
import org.apache.spark.ml.linalg.*;
import org.apache.spark.sql.*;
import org.apache.spark.sql.api.java.*;
import org.apache.spark.sql.types.*;
import org.junit.jupiter.api.*;
import org.springframework.boot.test.context.*;
import org.springframework.test.context.*;
/**
* Analyse en composantes principales.
*/
#ActiveProfiles("test")
#SpringBootTest(classes = SparkTestApplicationGestion.class)
public class AnalyseComposantesPrincipalesIT extends AbstractStatsTest implements Serializable {
/** Serial ID. */
private static final long serialVersionUID = 7301395393891047373L;
/**
* Recherche de composantes principales.
*/
#Test
#DisplayName("ACP : le classement des universités américaines")
public void composantePrincipale() {
// Créer le dataset des features (des vecteurs) :
// features
// [100.0,100.0]
// [86.1,70.3]
// [67.9,69.2]
// ...
Dataset<Row> dsHiCiSCi = denseRowWithVectors(
// Le classement (variables HiCi et SCi des universités américaines).
d(100, 100), d(86.1, 70.3), d(67.9, 69.2), d(54.0, 65.4), d(65.9, 61.7),
d(58.4, 50.3), d(56.5, 69.6), d(59.3, 46.5), d(50.8, 54.1), d(46.3, 65.4),
d(57.9, 63.2), d(54.5, 65.1), d(57.4, 75.9), d(59.3, 64.6), d(56.9, 70.8),
d(52.4, 74.1), d(52.9, 67.2), d(54.0, 59.8), d(41.3, 67.9), d(41.9, 80.9),
d(60.7, 77.1), d(38.5, 68.6), d(40.6, 62.2), d(39.2, 77.6), d(38.5, 63.2),
d(44.5, 57.6), d(35.5, 38.4), d(39.2, 53.4), d(46.9, 57.0), d(41.3, 53.9),
d(27.7, 23.2), d(46.9, 62.0), d(48.6, 67.0), d(39.9, 45.7), d(42.6, 42.7),
d(31.4, 63.1), d(40.6, 53.3), d(46.9, 54.8), d(23.4, 54.2), d(30.6, 38.0),
d(31.4, 51.0), d(27.7, 56.6), d(45.1, 58.0), d(46.9, 64.2), d(35.5, 48.9),
d(25.7, 51.7), d(39.9, 44.8), d(24.6, 56.9), d(39.9, 65.6), d(37.1, 52.7));
long n = dsHiCiSCi.count();
int p = 2; // Deux variables.
int nombreComposantes = 2;
// Afficher les valeurs des universités.
dsHiCiSCi.show((int)n, false);
// Centrer réduire les valeurs (Standardizing).
// scaledFeatures
// [3.665634766586407,3.156450874585141]
// [2.711113911293206,0.8064410737434008]
// [1.461309625945275,0.7194036737122256]
// ...
StandardScaler scaler = new StandardScaler().setInputCol("features").setOutputCol("scaledFeatures")
.setWithStd(true) // Réduire
.setWithMean(true); // Centrer
Dataset<Row> centreReduit = scaler.fit(dsHiCiSCi).transform(dsHiCiSCi).select("scaledFeatures");
// Faire calculer par ML les composantes principales (nombreComposantes extraites de p variables).
//
// scaledFeatures pca
// [3.665634766586407,3.156450874585141] [-4.823943018707778,-0.36004738290505234]
// [2.711113911293206,0.8064410737434008] [-2.4872869831159297,-1.3468070793732898]
// [1.461309625945275,0.7194036737122256] [-1.5419971620115105,-0.5246067298266516]
// ...
PCA pcaOperationDefinition = new PCA().setInputCol("scaledFeatures").setOutputCol("pca").setK(nombreComposantes);
Dataset<Row> composantesPrincipalesCalculees = pcaOperationDefinition.fit(centreReduit).transform(centreReduit);
composantesPrincipalesCalculees.show((int)n, false);
// Calculer la plus grande valeur propre de chaque composante, sa corrélation avec la variable qu'elle résume, et la qualité globale du résumé qu'elle en fait.
//
// valeurPropre correlationComposanteAvecXi qualiteResumeComposante
// 1.5648493047635532 0.8845477106305665 0.7824246523817766
// 0.3951506952364467 0.44449448547560555 0.19757534761822335
Dataset<Row> valeursPropresEtQualite = valeurPropreEtQualiteGlobaleResume(pcaOperationDefinition, composantesPrincipalesCalculees.select(col("pca")), n, p);
valeursPropresEtQualite.show(false);
// Calculer les contributions individuelles et la qualité de la représentation de chaque individu sur chaque axe.
//
// xStdCarre contributionIndividuelleAxe qualiteProjectionIndividuAxe
// 23.400060365676286 [0.29741427723298436,0.006561249644731516] [0.9944600947215109,0.00553990527848926]
// 8.000485845427955 [0.07906955024417166,0.09180747147437675] [0.773277605373604,0.22672239462639585]
// 2.6529674686309654 [0.03038957477136533,0.013929481805149522] [0.8962624969082515,0.10373750309174866]
// ...
Dataset<Row> contributionsEtQualiteProjectionIndividuelles = contributionsEtQuailiteIndividuelle(composantesPrincipalesCalculees, valeursPropresEtQualite, n);
contributionsEtQualiteProjectionIndividuelles.show((int)n, false);
}
/**
* Renvoyer les valeurs propres (eigen values), la corrélation des composantes aux variables Xi, et la qualité globale du résumé qu'elle en donne.
* #param pcaOperationDefinition Définition de l'opération d'ACP demandée.
* #param pca Résultat de l'ACP.
* #param n Nombre d'éléments dans la matrice de départ.
* #param p Nombre de variables.
* #return Dataset contenant les valeurs propres, la corrélation des composantes aux variables Xi, et la qualité globale du résumé de chaque composante.
*/
private Dataset<Row> valeurPropreEtQualiteGlobaleResume(PCA pcaOperationDefinition, Dataset<Row> pca, long n, int p) {
int nombreComposantes = pcaOperationDefinition.getK();
double[] valeursPropres = new double[nombreComposantes]; // Plus grande valeur propre de R pour une composante.
double[] correlationsComposantesAvecXi = new double[nombreComposantes]; // Corrélation de la composante avec Xi.
double[] qualiteComposantes = new double[nombreComposantes]; // Qualité globale du résumé proposé par la composante.
List<Row> enregistrements = new ArrayList<>();
List<Row> composantesTousIndividusUniversites = pca.select(col("pca")).collectAsList();
for(Row composantesIndividuUniversite : composantesTousIndividusUniversites) {
for(int numeroComposante = 1; numeroComposante <= nombreComposantes; numeroComposante ++) {
double composante = ((DenseVector)composantesIndividuUniversite.get(0)).values()[numeroComposante-1]; // Φ[numero_composante]
valeursPropres[numeroComposante-1] += composante * composante;
}
}
for(int numeroComposante = 1; numeroComposante <= nombreComposantes; numeroComposante ++) {
valeursPropres[numeroComposante-1] = valeursPropres[numeroComposante-1] / n;
// Calcul de la qualité du résumé de la composante :
correlationsComposantesAvecXi[numeroComposante-1] = sqrt(valeursPropres[numeroComposante-1]) * (1 / sqrt(p));
qualiteComposantes[numeroComposante-1] = valeursPropres[numeroComposante-1] / p;
Row row = RowFactory.create(valeursPropres[numeroComposante-1], correlationsComposantesAvecXi[numeroComposante-1], qualiteComposantes[numeroComposante-1]);
enregistrements.add(row);
}
// Construire le dataset avec le schéma [valeurPropre (double), qualiteResumeComposante (double)].
StructType schema = new StructType(new StructField[] {
new StructField("valeurPropre", DoubleType, false, Metadata.empty()),
new StructField("correlationComposanteAvecXi", DoubleType, false, Metadata.empty()),
new StructField("qualiteResumeComposante", DoubleType, false, Metadata.empty()),
});
return this.session.createDataFrame(enregistrements, schema);
}
/**
* Calculer les contributions individuelles par axe et la qualité de la projection pour l'individu.
* #param acp Individus centrés réduits et ACP.
* #param valeursPropresEtQualitesComposantes Dataset des valeurs propres et qualité des composantes, par variable.
* #param n Nombre d'individus.
* #return Dataset d'ACP complété de la contribution individuelle et de la qualité des composantes.
*/
private Dataset<Row> contributionsEtQuailiteIndividuelle(Dataset<Row> acp, Dataset<Row> valeursPropresEtQualitesComposantes, long n) {
this.session.udf().register("xCarresCentresReduitsUDF", new UDF1<DenseVector, Double>() {
/** Serial ID. */
private static final long serialVersionUID = 1L;
/**
* Renvoyer la somme des x carrés centrés réduits des variables d'un individu.
* #param individuCentreReduit Individu aux variables centrées réduites.
*/
#Override
public Double call(DenseVector individuCentreReduit) {
double sommeXCarreCentresReduits = 0.0;
double[] variablesIndividuCentreesReduites = individuCentreReduit.values();
for(int index=0; index < individuCentreReduit.size(); index ++) {
sommeXCarreCentresReduits += variablesIndividuCentreesReduites[index] * variablesIndividuCentreesReduites[index];
}
return sommeXCarreCentresReduits;
}
}, DoubleType);
// Faire la somme, par individu, des carrés des valeurs centrées réduites x* de chaque variable se rapportant à un individu.
Dataset<Row> ds = acp.withColumn("xStdCarre", callUDF("xCarresCentresReduitsUDF", col("scaledFeatures")));
// Calculer les contributions individuelles par axe.
List<Double> listeValeursPropres = valeursPropresEtQualitesComposantes.select("valeurPropre").map((MapFunction<Row, Double>)v -> v.getDouble(0), Encoders.DOUBLE()).collectAsList();
DenseVector valeursPropres = (DenseVector)Vectors.dense(listeValeursPropres.stream().mapToDouble(Double::doubleValue).toArray());
this.session.udf().register("contributionIndividuelleAxe", new UDF1<DenseVector, DenseVector>() {
/** Serial ID. */
private static final long serialVersionUID = 1L;
/**
* Renvoyer la contribution individuelle d'un individu sur un axe.
* #param composantes Composantes principales d'un individu.
*/
#Override
public DenseVector call(DenseVector composantes) {
double[] contributions = new double[composantes.size()];
for(int axe=1; axe <= contributions.length; axe++) {
double composante = composantes.values()[axe-1];
double valeurPropre = valeursPropres.values()[axe-1];
contributions[axe-1] = ((composante * composante) / n) / valeurPropre;
}
return (DenseVector)Vectors.dense(contributions);
}
}, new VectorUDT());
ds = ds.withColumn("contributionIndividuelleAxe", callUDF("contributionIndividuelleAxe", col("pca")));
// Calculer la qualité de la projection, par individu, sur les axes.
this.session.udf().register("qualiteProjectionIndividuAxe", new UDF2<DenseVector, Double, DenseVector>() {
/** Serial ID. */
private static final long serialVersionUID = 1L;
/**
* Renvoyer la qualité de la projection, par individu, sur les axes.
* #param composantes Individu aux variables centrées réduites.
* #param xStdCarre valeurs centrées réduites, au carré, cumulées pour toutes les variables associées à l'individu.
*/
#Override
public DenseVector call(DenseVector composantes, Double xStdCarre) {
double[] qualite = new double[composantes.size()];
for(int axe=1; axe <= qualite.length; axe++) {
double composante = composantes.values()[axe-1];
qualite[axe-1] = (composante * composante) / xStdCarre;
}
return (DenseVector)Vectors.dense(qualite);
}
}, new VectorUDT());
return ds.withColumn("qualiteProjectionIndividuAxe", callUDF("qualiteProjectionIndividuAxe", col("pca"), col("xStdCarre")));
}
/**
* Créer un Dataset Row par des vecteurs denses constitués à partir d'upplets de valeurs.
* #param listeUppletsValeurs liste de n-upplets.
* #return Dataset Dense.
*/
private Dataset<Row> denseRowWithVectors(double[]... listeUppletsValeurs) {
List<Row> data = new ArrayList<>();
for(double[] upplet : listeUppletsValeurs) {
Vector vecteur = Vectors.dense(upplet);
data.add(RowFactory.create(vecteur));
}
StructType schema = new StructType(new StructField[] {
new StructField("features", new VectorUDT(), false, Metadata.empty()),
});
return this.session.createDataFrame(data, schema);
}
/**
* Renvoyer un ensemble de valeurs doubles sous la forme d'un tableau.
* #param valeurs Valeurs.
* #return Tableau de doubles.
*/
private double[] d(double... valeurs) {
return valeurs;
}
}
I've got the following code:
It's a class used to store a monthly summary of expenses. voci is an arraylist used to store the expenses (name and cost). mese is the month of the summary, anno the year of summary. My problem is that when I call the showRiepilogo() method i must see the list of the expenses of that month but i can't see nothing. Someone can tell me why please?
class RiepilogoMensile extends Riepilogo {
private ArrayList<Voce> voci = new ArrayList<Voce>();
private int mese;
private int anno;
public RiepilogoMensile(int mese, int anno, String autore, ArrayList<Voce> voci) {
super(autore);
this.mese = mese;
this.anno = anno;
// il blocco successivo è necessario???in teoria il costruttore viene invocato solo una volta.. bisogna cambiare solo la set e la get?.. provo!
// aggiunta delle voci
boolean voceExist = false;
// variabile temporanea che contiene gli anni da aggiungere
ArrayList<Voce> oldVoci = new ArrayList<Voce>();
oldVoci.addAll(this.voci);
ArrayList<Voce> newVoci = new ArrayList<Voce>();
newVoci.addAll(voci);
// controllo se le voci da aggiungere sono già presenti
for (Voce a : oldVoci) {
voceExist = false;
for (int i = 0; i < newVoci.size(); i++) {
if (a.equals(newVoci.get(i))) {
voceExist = true;
break;
}
}
if (!voceExist)
voci.add(a);
}
// test costruttore
System.out.println("Test costruttore voci--> INIZIO");
for(Voce v:voci)
System.out.println(v.getNome()+" "+v.getSpesa());
System.out.println("Test costruttore voci--> FINE");
}
public ArrayList<Voce> getVoci() {
ArrayList<Voce> temp = new ArrayList<Voce>();
temp.addAll(this.voci);
return (temp);
}
public void setVoci(ArrayList<Voce> voci) {
// aggiunta delle voci
boolean voceExist = false;
// variabile temporanea che contiene gli anni da aggiungere
ArrayList<Voce> oldVoci = new ArrayList<Voce>();
oldVoci.addAll(this.voci);
ArrayList<Voce> newVoci = new ArrayList<Voce>();
newVoci.addAll(voci);
// controllo se le voci da aggiungere sono già presenti
for (Voce a : oldVoci) {
voceExist = false;
for (int i = 0; i < newVoci.size(); i++) {
if (a.equals(newVoci.get(i))) {
voceExist = true;
break;
}
}
if (!voceExist)
this.voci.add(a);
}
}
#Override
public void showRiepilogo() {
String messaggio = "\nRiepilogo del " + anno + " di " + Voce.intToString(mese) + " creato da " + getAutore()
+ ": ";
System.out.println(messaggio);
utils.showRow(messaggio.length() - 2, '-'); // tolgo 2 perchè non devo considerare \n
System.out.println();
System.out.println("Test stampa voci in showRiepilogo() voci--> INIZIO");
// stampa voci
for (Voce v : voci)
System.out.println(v.getNome() + " " + v.getSpesa() + " EURO " + (v.getSpesa() > 0 ? "<--ENTRATA" : "USCITA-->"));
for(int i=0;i<voci.size();i++) {
System.out.println(voci.get(i).getNome() + " " + voci.get(i).getSpesa() + " EURO " + (voci.get(i).getSpesa() > 0 ? "<--ENTRATA" : "USCITA-->"));
}
System.out.println("Test stampa voci in showRiepilogo() voci--> FINE");
}
}
When I call showRiepilogo() from main i can't see nothing instead i could see the content of voci ArrayList.
riepiloghiMensili.get(index).showRiepilogo();
Someone know why?
Thanks in advice, Elias.
You have a very weird constructor, you try to loop over the member this.voci but since your doing this in the constructor this.voci will always be an empty array. Look at the declaration:
private ArrayList<Voce> voci = new ArrayList<Voce>();
Your setVoci(...) method will fail for the same reason, this.voci is empty and the for loop will never be entered and no objects added to the array.
Change your constructor to just set the array to the given parameter
this.voci = voci
I would also recommend to do the same for the setVoci method or to rename it because a set... method is expected to set a member to the given parameter.
the reference of the ArrayList I've tried and it doesn't works well!Doing as what you tell to do assigns the same ArrayList to all the istances of RiepilogoMensile.
I've done that and all works fine:
class RiepilogoMensile extends Riepilogo {
private ArrayList<Voce> voci = new ArrayList<Voce>();
private int mese;
private int anno;
public RiepilogoMensile(int mese, int anno, String autore, ArrayList<Voce> voci) {
super(autore);
this.mese = mese;
this.anno = anno;
this.voci.addAll(voci);
}
public ArrayList<Voce> getVoci() {
ArrayList<Voce> temp = new ArrayList<Voce>();
temp.addAll(this.voci);
return (temp);
}
public void setVoci(ArrayList<Voce> voci) {
this.voci.addAll(voci);
// aggiunta delle voci
boolean voceExist = false;
// variabile temporanea che contiene gli anni da aggiungere
ArrayList<Voce> oldVoci = new ArrayList<Voce>();
oldVoci.addAll(this.voci);
ArrayList<Voce> newVoci = new ArrayList<Voce>();
newVoci.addAll(voci);
// controllo se le voci da aggiungere sono già presenti
for (Voce a : oldVoci) {
voceExist = false;
for (int i = 0; i < newVoci.size(); i++) {
if (a.equals(newVoci.get(i))) {
voceExist = true;
break;
}
}
if (!voceExist)
this.voci.add(a);
}
}
Thanks insted!
Bye, Elias.
I am trying to draw a graph using java, to do this I got all the infos of my graph into an instance of a class in my main program. To draw the graph I need to transfer this infos into a xml file like this.
My graph is much simpler than the example of the link, my problem is: I have no idea how to transfer my instance of the class to this format.
Below the codes I have (the codes are correct, i just need a way to transfer the atributes of the instance of the class "atividade" to the xml format of the link:
Atividade Class:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package trabalho_m3;
import java.util.Arrays;
public class Atividade {
private int idAtividade;
private String nomeAtividade;
private float tempoDuracao, tInicioCedo, tTerminoCedo, tTerminoTarde, tInicioTarde, folga;
private int qtdPredecessores, qtdSucessores;
private Atividade predecessores[], sucessores[];
private int cnt_aux1 = 0, cnt_aux2 = 0;
public Atividade(int id, String nome, float duracao, int nPre, int nSuc){
this.idAtividade = id;
this.nomeAtividade = nome;
this.tempoDuracao = duracao;
this.qtdPredecessores = nPre;
this.qtdSucessores = nSuc;
this.predecessores = new Atividade[this.qtdPredecessores];
this.sucessores = new Atividade[this.qtdSucessores];
}
/*
* Método que calcula o TEMPO DE INÍCIO CEDO(Tes), assim como
* o TEMPO DE TÉRMINO CEDO(Tef) das atividades do projeto.
*/
public void calcular_Tes_Tef(){
// Cálculo do Tempo de Início Cedo da atividade (Tes).
if(this.qtdPredecessores == 0){
this.tInicioCedo = 0;
} else {
this.tInicioCedo = this.maxTefPredecessores(this.predecessores);
}
// Cálculo do Tempo de Término Cedo da atividade (Tef).
this.tTerminoCedo = (this.tInicioCedo + this.tempoDuracao);
}
/*
* Método que calcula o TEMPO DE TÉRMINO TARDE(Tlf), assim como
* o TEMPO DE INÍCIO TARDE(Tls) das atividades do projeto.
*/
public void calcular_Tlf_Tls(){
// Cálculo do Tempo de Término Tarde da atividade (Tlf).
if(this.qtdSucessores == 0){
this.tTerminoTarde = this.tTerminoCedo;
} else {
this.tTerminoTarde = this.minTlsSucessores(this.sucessores);
}
// Cálculo do Tempo de Início Tarde da atividade (Tls).
this.tInicioTarde = (this.tTerminoTarde - this.tempoDuracao);
}
/*
* Método calcula a FOLGA(R) das atividades do projeto.
*/
public void calcular_R(){
// Cálculo da Folga (R).
this.folga = (this.tTerminoTarde - this.tTerminoCedo);
}
/*
* Método encontra o valor MÁXIMO do Tef entre os predecessores
* de uma atividade.
*
* MAX{Tef(K)}; onde K representa as atividades precedentes.
*/
public float maxTefPredecessores(Atividade predecessores[]){
float maxTef = predecessores[0].tTerminoCedo;
for(int i = 1; i < predecessores.length; i++){
if(maxTef < predecessores[i].tTerminoCedo){
maxTef = predecessores[i].tTerminoCedo;
}
}
return maxTef;
}
/*
* Método encontra o valor MÍNIMO do Tls entre os sucessores
* de uma atividade.
*
* MIN{Tls(K)}; onde K representa as atividades sucessoras.
*/
public float minTlsSucessores(Atividade sucessores[]){
float minTls = sucessores[0].tInicioTarde;
for(int i = 1; i < sucessores.length; i++){
if(sucessores[i].tInicioTarde < minTls){
minTls = sucessores[i].tInicioTarde;
}
}
return minTls;
}
/*
* Vincula a uma dada atividade suas precedencias, incluindo
* seus precedentes no Array predecessores[].
*/
public void setarAtividadePredecessora(Atividade atividadePre){
if(cnt_aux1 == this.qtdPredecessores){
System.out.println("A atividade " + this.nomeAtividade + " nao suporta mais pre-requisitos!");
} else {
this.predecessores[this.cnt_aux1] = atividadePre;
this.cnt_aux1++;
}
}
/*
* Vincula a uma dada atividade seus sucessores.
*/
public void setarAtividadeSucessora(Atividade atividadeSuc){
if(cnt_aux2 == this.qtdSucessores){
System.out.println("A atividade " + this.nomeAtividade + " nao suporta mais atividades sucessoras!");
} else {
this.sucessores[this.cnt_aux2] = atividadeSuc;
this.cnt_aux2++;
}
}
// Retorna o NOME de uma atividade.
public String getNome(){
return this.nomeAtividade;
}
// Retorna a FOLGA(R) de uma atividade.
public float getFolga(){
return this.folga;
}
public float getPredecessores(){
return this.qtdPredecessores;
}
public float getId(){
return this.idAtividade;
}
public float getSucessores(){
return this.qtdSucessores;
}
/*
* Imprime todas as informações de uma atividade:
* Id, Nome, Precedencias, Sucessores, t, Tes, Tef, Tlf, Tls, R.
*/
public void informacoesAtividade(){
System.out.println();
System.out.println("Id: " + this.idAtividade);
System.out.println("Nome: " + this.nomeAtividade);
if(this.qtdPredecessores == 0){
System.out.println("Precedencia: --");
} else {
System.out.print("Precedencia: ");
for(int i = 0; i < this.predecessores.length; i++){
System.out.print(predecessores[i].nomeAtividade + " ");
}
System.out.println();
}
if(this.qtdSucessores == 0){
System.out.println("Sucessores: --");
} else {
System.out.print("Sucessores: ");
for(int j = 0; j < this.sucessores.length; j++){
System.out.print(sucessores[j].nomeAtividade + " ");
}
System.out.println();
}
System.out.println();
System.out.println("t: " + this.tempoDuracao);
System.out.println("Tes: " + this.tInicioCedo);
System.out.println("Tef: " + this.tTerminoCedo);
System.out.println("Tlf: " + this.tTerminoTarde);
System.out.println("Tls: " + this.tInicioTarde);
System.out.println("R: " + this.folga);
System.out.println();
}
}
Main:
package trabalho_m3;
import java.io.IOException;
import java.util.Scanner;
public class TRABALHO_M3 {
public static void Tes_Tef(Atividade[] Ativ){
for(int i = 0; i < Ativ.length; i++){
Ativ[i].calcular_Tes_Tef();
}
}
public static void Tlf_Tls(Atividade[] Ativ){
for(int i = (Ativ.length - 1); i >= 0; i--){
Ativ[i].calcular_Tlf_Tls();
}
}
public static void R(Atividade[] Ativ){
for(int i = 0; i < Ativ.length; i++){
Ativ[i].calcular_R();
}
}
public static void atividadeInfo(Atividade[] Ativ){
for(int i = 0; i < Ativ.length; i++){
Ativ[i].informacoesAtividade();
}
}
public static void caminhoCritico(Atividade[] Ativ){
System.out.print("Caminho Critico: ");
for(int i = 0; i < Ativ.length; i++){
if(Ativ[i].getFolga() == 0.0){
System.out.print(Ativ[i].getNome() + " ");
}
}
System.out.println();
}
public static void main(String[] args) throws IOException {
int qtd = 0;
int aux;
String rotulo;
float peso;
int predecessores, sucessores;
Scanner s = new Scanner(System.in);
System.out.println("Informe a quantidade de atividades: ");
qtd = s.nextInt();
Atividade atividades[] = new Atividade[qtd];
for (int i = 0; i < qtd; i++){
System.out.println("Informe o rótulo da atividade["+(i+1)+"]: ");
rotulo = s.next();
System.out.println("Informe a duracao da atividade["+(i+1)+"]: ");
peso = s.nextFloat();
System.out.println("Informe a quantidade de predecessores da atividade["+(i+1)+"]: ");
predecessores = s.nextInt();
System.out.println("Informe a quantidade de sucessores da atividade["+(i+1)+"]: ");
sucessores = s.nextInt();
atividades[i] = new Atividade(i,rotulo,peso,predecessores,sucessores);
System.out.println("Pressione Enter para continuar...");
System.in.read();
}
for (int i = 0; i < qtd; i++){
for (int b = 0; b < qtd; b++){
System.out.println("Atividade "+atividades[b].getNome()+" - ID = "+atividades[b].getId());
}
System.out.println("Pressione Enter para continuar...");
System.in.read();
if (atividades[i].getPredecessores() > 0 ) {
System.out.println("Atividades Predecessoras de "+atividades[i].getNome());
for (int k=0; k<atividades[i].getPredecessores(); k++){
System.out.println("Informe o ID da atividade predecessora de numero "+(k+1)+" ...");
aux = s.nextInt();
atividades[i].setarAtividadePredecessora(atividades[aux]);
System.out.println("Pressione Enter para continuar...");
System.in.read();
Runtime.getRuntime().exec("clear");
}
} else {
System.out.println("A atividade ["+atividades[i].getNome()+"] não possui predecessores");
System.out.println("Pressione Enter para continuar...");
System.in.read();
}
for (int b = 0; b < qtd; b++){
System.out.println("Atividade "+atividades[b].getNome()+" - ID = "+atividades[b].getId());
}
System.out.println("Pressione Enter para continuar...");
System.in.read();
if (atividades[i].getSucessores() > 0 ) {
System.out.println("Atividades Sucessoras de "+atividades[i].getNome());
for (int k=0; k<atividades[i].getSucessores(); k++){
System.out.println("Informe o id da atividade sucessora de numero "+(k+1)+" ...");
aux = s.nextInt();
atividades[i].setarAtividadeSucessora(atividades[aux]);
System.out.println("Pressione Enter para continuar...");
System.in.read();
}
} else {
System.out.println("A atividade ["+atividades[i].getNome()+"] não possui sucessores");
System.out.println("Pressione Enter para continuar...");
System.in.read();
}
}
Tes_Tef(atividades);
Tlf_Tls(atividades);
atividadeInfo(atividades);
R(atividades);
caminhoCritico(atividades);
}
}
OBS .: I need to transfer to a xml file because the lib i am going to use to draw the graph needs it. I am going to use the prefuse lib.
If all you need is to draw the graph with prefuse, you do not need to create a xml file for that. You can a prefuse graph object and add nodes, edges directly to it. Here is a simple example with 2 nodes, 1 edge, and a property value on 1 node:
Graph graph = new Graph();
graph.getNodeTable().addColumn("duration", double.class);
Node n1 = graph.addNode();
n1.setDouble("duration", 20.0);
Node n2 = graph.addNode();
Edge e = graph.addEdge(n1, n2);
You would need to iterate over all nodes and edge of your custom class.
I've got following .bat-file which is proposed to open a fully working java_cmd portable task.
#echo off
cd /d "%~dp0"
:: cd ..\CommonFiles
:: set Path=%cd%\bin;%path%
set Path=%~d0\PortableApps\CommonFiles\bin;%path%
:: set "JAVA_HOME=%~d0\PortableApps\CommonFiles\jre"
set "JAVA_HOME=%~d0\PortableApps\CommonFiles"
nircmd regsetval dword "HKCU\console" "QuickEdit" "1" >nul 2>&1
cd /d "\Documents\workspaces\java"
start "Java_cmd" cmd /k "cs -w 100x25 -b 100x3000"
I have translated to the following as far:
using Microsoft.Win32;
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using con = System.Console;
namespace javacmd
{
class Program
{
const int HWND_BROADCAST = 0xffff;
const uint WM_SETTINGCHANGE = 0x001a;
[DllImport("user32", SetLastError = true, CharSet = CharSet.Auto)]
static extern bool SendNotifyMessage(IntPtr hWnd, uint Msg, UIntPtr wParam, string lParam);
static string codeBase = Assembly.GetExecutingAssembly().CodeBase;
static string drive = Path.GetPathRoot(codeBase);
static string oldjavahome = "";
static int Main(string[] args)
{
PrintOutStart();
string args0 = null;
try
{
if (args == null || args0 == "?" || args0 == "/?" || args0 == "--?" || args0 == "help" || args0 == "/help" || args0 == "--help")
{
return PrintOutHelp();
}
else
{
args0 = args[0];
}
}
catch
{
return PrintOutHelp();
}
if (args0 != null)
{
if (!File.Exists(args0+ ".java"))
{
con.WriteLine($"Error: FileNotFound!\nDie Datei {args0} wurde nicht gefunden. Bitte überprüfen Sie, dass\nSie den Namen richtig geschrieben haben!");
con.WriteLine("");
con.Write("Drücken Sie eine beliebige Taste . . . ");
con.ReadLine();
return 1;
}
else
{
string javahome = Path.Combine(drive, #"PortableApps\CommonFiles");
string javabin = Path.Combine(drive, #"PortableApps\CommonFiles\bin");
using (var key = Registry.LocalMachine.OpenSubKey(#"SYSTEM\CurrentControlSet\Control\Session Manager\Environment", true))
{
var ojh = key.GetValue("JAVA_HOME");
if (ojh != null)
{
oldjavahome = ojh.ToString();
if (oldjavahome != javahome)
{
key.SetValue("JAVA_HOME", javahome);
}
}
var path = key.GetValue("path");
if (path != null)
{
if (!path.ToString().Contains(javabin))
{
key.SetValue("Path", javabin + ";" + path);
}
}
SendNotifyMessage((IntPtr)HWND_BROADCAST, WM_SETTINGCHANGE, (UIntPtr)0, "Environment");
}
Process p = new Process() { StartInfo = new ProcessStartInfo() { FileName = "javac", Arguments = $"{args0}.java", CreateNoWindow = true, RedirectStandardOutput = true } };
try
{
p.Start();
p.WaitForExit();
con.WriteLine($"output javac: \"{p.StandardOutput}\"");
}
catch
{
con.WriteLine("Error while compiling!\nFehler während des Kompilier-Vorgangs!");
con.WriteLine("");
con.Write("Drücken Sie eine beliebige Taste . . . ");
con.ReadLine();
return 1;
}
p.StartInfo.FileName = "java";
p.StartInfo.Arguments = args0;
try
{
p.Start();
p.WaitForExit();
con.WriteLine($"output java: \"{p.StandardOutput}\"");
}
catch
{
con.WriteLine("Fehler während des Start-Vorgangs!");
con.WriteLine("");
con.Write("Drücken Sie eine beliebige Taste . . . ");
con.ReadLine();
return 1;
}
}
}
else
{
con.WriteLine("Der benötigte Parameter \"args0\" hat den Wert \"null\". Bitte versuchen Sie es erneut!");
con.WriteLine("");
con.Write("Drücken Sie eine beliebige Taste . . . ");
con.ReadLine();
return 1;
}
return 0;
}
private static void PrintOutStart()
{
con.WriteLine("");
con.WriteLine("###################################################");
con.WriteLine("# #");
con.WriteLine("# javacmd #");
con.WriteLine("# #");
con.WriteLine("###################################################");
con.WriteLine("");
}
private static int PrintOutHelp()
{
string name = Path.GetFileNameWithoutExtension(codeBase);
con.WriteLine("Der javacmd compiliert und startet eine angegebene .java-Datei mit nur einem Befehl.");
con.WriteLine("");
con.WriteLine("Syntax: " + name + ".exe [name | [ | / | --]? | [ | / | --]help]");
con.WriteLine("");
con.WriteLine(" name\t\t\tDie zu startende Datei (ohne die Endung \".java\").");
con.WriteLine(" [ | / | --]?\t\tZeigt die Hilfe an. Dies entspricht einer Eingabe ohne Optionen.");
con.WriteLine(" [ | / | --]help\tZeigt die Hilfe an. Dies entspricht einer Eingabe ohne Optionen.");
con.WriteLine("");
con.WriteLine("Wird der javacmd ohne Argument aufgerufen, zeigt er diese Hilfe an.");
con.WriteLine("");
con.Write("Drücken Sie eine beliebige Taste . . . ");
con.ReadLine();
return 1;
}
}
}
The problem is that it throws a System.Security.SecurityException whilst opening the reigstry key. I think this is caused by missing admin rights - which I don't get on all computers I wanna use the program. How do I get this code running the same as the batch code?
My program is located in \Documents\workspaces\java where Documents is a child of (root) usb drive.
Thanks in advance!
So I create objects MyFrame, and stores them in a MyFrame array. The problem is when the loop is done, all the objects in the array are equal to the last object created.
Here's the code:
MyFrame [] response = new MyFrame[8];
for(int i = 0; i<numberSplit; i++){
response[i] = new MyFrame("","", infoS[i],"");
}
Here the full class if you run the main you will see that's in splitInfo and if I manually print each element in the array upon creation it works :
import java.io.*;
import java.util.*;
public class MyFrame {
// Variable qui donne une valeur fixe aux fanions.
private static BitSet [] frame = new BitSet [6];
private static BitSet flag_1 = new BitSet(8);
private static BitSet address = new BitSet(8);
private static BitSet control = new BitSet(8);
private static BitSet fcs = new BitSet(16);
private static String info = null;
// Constructeur pour créer des trames
public MyFrame (BitSet address, BitSet control, String info, BitSet fcs){
this.frame = frame;
flag_1.set(1,7);
this.frame[0] = flag_1;
this.frame[1] = address;
this.frame[2] = control;
this.frame[3] = stringToBitSet(info);
this.frame[4] = fcs;
this.frame[5] = flag_1;
}
public MyFrame (String address, String control, String info, String fcs){
this.frame = frame;
flag_1.set(1,7);
this.frame[0] = flag_1;
this.frame[1] = stringToBitSet(address);
this.frame[2] = stringToBitSet(control);
this.frame[3] = stringToBitSet(info);
this.frame[4] = stringToBitSet(fcs);
this.frame[5] = flag_1;
}
// Constructeur qui prend comme entree une trame en String et la longueur du champ
// d'information
public MyFrame (String frameS, int infoL){
int endIL = 24+infoL;
this.frame = frame;
this.frame[0] = stringToBitSet(frameS.substring(0,7));
this.frame[1] = stringToBitSet(frameS.substring(8,16));
this.frame[2] = stringToBitSet(frameS.substring(16,24));
this.frame[3] = stringToBitSet(frameS.substring(24,endIL));
this.frame[4] = stringToBitSet(frameS.substring(endIL,endIL+16));
this.frame[5] = stringToBitSet(frameS.substring(endIL+16,endIL+24));
}
// Constructeur-copieur
public MyFrame (MyFrame frm){
this.frame[0] = (BitSet)frm.frame[0].clone();
this.frame[1] = (BitSet)frm.frame[1].clone();
this.frame[2] = (BitSet)frm.frame[2].clone();
this.frame[3] = (BitSet)frm.frame[3].clone();
this.frame[4] = (BitSet)frm.frame[4].clone();
this.frame[5] = (BitSet)frm.frame[5].clone();
}
// GETTERS
public BitSet getAddress(){
return this.frame[1];
}
public BitSet getCtrl(){
return this.frame[2];
}
public BitSet getInfo(){
return this.frame[3];
}
public BitSet getFCS(){
return this.frame[4];
}
public BitSet getFlag(){
return this.frame[5];
}
public void setAddress(String add){
this.frame[1] =stringToBitSet(add);
}
// Convertit un BitSet en String.
public static String bitSetToString(BitSet bs, int length){
String result ="";
String tempString="";
for(int i=0; i < length; i++){
boolean temp = bs.get(i);
if (temp){
tempString = "1";
}else{
tempString = "0";
}
result = result.concat(tempString);
}
return result;
}
//Convertit un String en BitSet.
public static BitSet stringToBitSet(String bits){
int length = bits.length();
BitSet result = new BitSet (length);
for(int i=0; i < length; i++){
if (bits.charAt(i) == '1'){
result.set(i);
}
}
return result;
}
// puisqu'on utilise le PrintWriter on prend la trame et on la transpose en une grande String
// prend la longueur du champ info en parametre puisqu'il est variable
public String toString(int infoL){
String result = "";
result = result.concat(bitSetToString(this.frame[0],8));
result = result.concat(bitSetToString(this.frame[1],8));
result = result.concat(bitSetToString(this.frame[2],8));
result = result.concat(bitSetToString(this.frame[3],infoL));
result = result.concat(bitSetToString(this.frame[4],16));
result = result.concat(bitSetToString(this.frame[5],8));
return result;
}
// print
public static void print (MyFrame trame, int infoL) {
System.out.println("Fanion : "+bitSetToString(trame.frame[0],8));
System.out.println("Addresse : " +bitSetToString(trame.frame[1],8));
System.out.println("Control : "+bitSetToString(trame.frame[2],8));
System.out.println("Info : "+bitSetToString(trame.frame[3],infoL));
System.out.println("FCS : "+bitSetToString(trame.frame[4],16));
System.out.println("Fanion : "+bitSetToString(trame.frame[5],8));
}
// Methode qui prend une trame en parametre et retourne une trame reponse
public MyFrame [] processFrame(){
MyFrame [] response = new MyFrame [8];
BitSet control = this.getCtrl();
String ctrlS = MyFrame.bitSetToString(control,8);
BufferedReader userIn = new BufferedReader(new InputStreamReader(System.in)) ;
String address, info;
// Determine quel type de trame la trame est
if(!control.get(0)){
System.out.println("Cette trame est de type I");
}else if (control.get(0) && !control.get(1)){
System.out.println("Cette trame est de type S");
// RR
if (ctrlS.substring(0,4).equals("1000")){
System.out.println("RR");
// Desire envoyer des trames
System.out.println("Desirez-vous envoyer une ou des trame(s)?");
for(;;){
try{
if( userIn.readLine().equals("oui")){
System.out.println("Les addresses sont en format binaire et commence toujours par 1");
System.out.println("Par exemple : Station Primaire = 10101010");
System.out.println("Station Secondaire 00 = 10000000");
System.out.println("Station Secondaire 01 = 10000001");
System.out.println("Station Secondaire 10 = 10000010");
System.out.println("...");
System.out.println("Station Secondaire 11111111 = 11111111");
System.out.println("\n");
System.out.println("Entrer l'addresse pour quel station ces trames sont destinées : ");
address = userIn.readLine();
System.out.println("Veuillez entrer l'information en binaire que vous-voulez envoyer à l'addresse "+ address +" : ");
info = userIn.readLine();
response = splitInfo(info);
print(response[0],512);
// ajoute l'addresse au trames
for(int i = 0; i < response.length-1; i++){
response [i].setAddress(address);
}
// retourne la serie de trames
return response;
// N'a aucune trame a envoyer
}else if (userIn.readLine().equals("non")){
response [0] = new MyFrame ("10101010", "10000000","","0000000000000000");
return response;
}else{
System.out.println("Veuillez entrer soit 'oui' soit 'non'");
}
break;
}catch(IOException e){
System.out.println(e);
}
}
}
// RNR
else if(ctrlS.substring(0,1).equals("1001")){
}
// FRAME ERROR
else{}
}else if (control.get(0) && control.get(1)){
System.out.println("Cette trame est de type U : ");
// SRNM
if (ctrlS.equals("11001001")){
System.out.print("SRNM \n");
response [0] = new MyFrame("10101010","11001110","","0000000000000000");
return response;
}
// DISC
else if(ctrlS.equals("11001010")){
}
// UA
else if(ctrlS.equals("11001110")){
System.out.print("UA \n");
}
// FRMR : Report receipt of an unacceptable frame
else{
}
}
return null;
}
// Methode qui prend un string d'information a envoyer et le subdivise en
// string binaire de 512 bits et cree le nombre de trame en consequence
// par defaut la limite en terme de longeur totale est de 8 (4096 bits)
public static MyFrame [] splitInfo (String info){
Integer binVal = new Integer(256);
String infoBin = "";
String [] infoS = new String [8];
MyFrame [] response = new MyFrame [8];
int numberSplit = 0;
// Transcode les caractere en UTF-8 binaire
try{
byte [] string = info.getBytes("UTF-8");
for(int i = 0 ; i<= string.length-1; i++){
infoBin = infoBin.concat(binVal.toBinaryString(string[i]));
}
// Si le message resultant est plus que 64 octets (512 bits)
// le splitter en message de 512 bits
if (infoBin.length() >511){
for (int i = 0; i<=((int)(infoBin.length()/512)); i++){
if(((i+1)*512) > infoBin.length()){
infoS[i] = infoBin.substring(512*i, infoBin.length());
}else{
infoS[i] = infoBin.substring(512*i, 512*(i+1));
}
numberSplit++;
}
// Creer les trames
for (int i = 0; i<numberSplit; i++){
MyFrame temp = new MyFrame ("","",infoS[i],"0000000000000000");
response[i] = new MyFrame(temp);
//print(temp,512);
}
print(response[0],512);
print(response[1],512);
//System.out.println(response[0]);
//System.out.println(response[1]);
//print(response2[0],512);
return response;
}else{
response [0] = new MyFrame("","",infoBin,"0000000000000000");
return response;
}
}catch(Exception e){}
return null;
}
public static void main(String args[]){
MyFrame trame = new MyFrame("0000000"+1,"10001000","","0000000000000011");
print(trame,0);
MyFrame trame2 = new MyFrame(trame.toString(0), 0);
print(trame2,0);
BitSet compare = new BitSet(8);
compare.set(0,2,true);
compare.set(4);
compare.set(7,true);
System.out.println("compare : " + compare.toString() + " ctrl : " + trame2.frame[2]);
System.out.println(trame2.frame[2].equals(compare));
trame2.setAddress("10111001");
MyFrame [] x = splitInfo("HEAKdsANSDLASDIASDLMASLDMASKDHAKSNDKAasdasdadasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdasdsdasdasdasdasdasdasdasdasdasdasdasSMDKASNDKNASKDNASODDFKANSKBFNSKANSDADKABSFKBNASKDNAKSDNOKGJIKASNDIKNASDNA");
}
}
A good way to test if the objects are really different objects is System.out.println(System.identityHashCode(object))
but the code you posted, as said before, is creating and saving distinct objects.
From the code snippet above, that's not possible. Each of them is a seperate new object.
Couple of things
If MyFrame is a custom class, did you override equals/hashcode poorly?
Are you seeing the same info across MyFrame instances? Could it be a poorly declared static variable?