Sorting of two-dimensional array based on two parameters - java

The following code performs 'hierarchical' sorting of a two-dimensional matrix. Firstly, it sorts elements based on the values of ranks. Secondly, it takes this sorted matrix, searches elements that have the same values of ranks, and sorts them based on dist. In descending order.
Question 1: Is it possible to achieve the same result in the easier way? I tried to create a Comparator, but it provided incorrect result for this particular case.
Question 2: How to get indexes of unsorted elements after sorting?
import java.util.ArrayList;
public class Test {
public static void main(String args[]) {
ArrayList<ArrayList<Double>> values = new ArrayList<ArrayList<Double>>();
ArrayList<Double> ranks = new ArrayList<Double>();
ArrayList<Double> dist = new ArrayList<Double>();
ranks.add(8.0);
ranks.add(3.0);
ranks.add(8.0);
ranks.add(1.0);
dist.add(1.8);
dist.add(2.8);
dist.add(1.9);
dist.add(2.1);
values.add(0,ranks);
values.add(1,dist);
int len = ranks.size();
ArrayList<ArrayList<Double>> sortedranks = new ArrayList<ArrayList<Double>>();
sortedranks = order(values,0,ranks.size());
boolean swapped = true;
int j = 0;
double tmp1, tmp2;
while (swapped) {
swapped = false;
j++;
for (int i = 0; i < len - j; i++) {
double val1 = sortedranks.get(0).get(i);
double val2 = sortedranks.get(0).get(i+1);
if (val1==val2) {
if (sortedranks.get(1).get(i) < sortedranks.get(1).get(i+1)) {
tmp1 = sortedranks.get(1).get(i);
tmp2 = sortedranks.get(1).get(i+1);
sortedranks.get(1).remove(i);
sortedranks.get(1).remove(i);
sortedranks.get(1).add(i,tmp2);
sortedranks.get(1).add(i+1,tmp1);
swapped = true;
}
}
}
}
for (int i = 0; i < len; i++) {
System.out.println("Ranks " + i + " : " + sortedranks.get(0).get(i)
+ ", Distances : " + sortedranks.get(1).get(i));
}
}
public static ArrayList<ArrayList<Double>> order(ArrayList<ArrayList<Double>> values, int i_start, int i_fin) {
boolean swapped = true;
int j = 0;
int i_rank = 0;
int i_dist = 1;
double tmp1_rank, tmp2_rank, tmp1_dist, tmp2_dist;
while (swapped) {
swapped = false;
j++;
for (int i = i_start; i < i_fin - j; i++) {
if (values.get(i_rank).get(i) < values.get(i_rank).get(i+1)) {
tmp1_rank = values.get(i_rank).get(i);
tmp2_rank = values.get(i_rank).get(i+1);
tmp1_dist = values.get(i_dist).get(i);
tmp2_dist = values.get(i_dist).get(i+1);
values.get(i_rank).remove(i);
values.get(i_rank).remove(i);
values.get(i_dist).remove(i);
values.get(i_dist).remove(i);
values.get(i_rank).add(i,tmp2_rank);
values.get(i_rank).add(i+1,tmp1_rank);
values.get(i_dist).add(i,tmp2_dist);
values.get(i_dist).add(i+1,tmp1_dist);
swapped = true;
}
}
}
return values;
}
}
The code that uses Comparator (does not work for my case):
public class MyEntry implements Comparable<MyEntry> {
private Double rank;
private Double dist;
public MyEntry(double rank, double dist) {
this.rank = rank;
this.dist = dist;
}
public static Comparator<MyEntry> ValueComparator = new Comparator<MyEntry>() {
public int compare(MyEntry value1, MyEntry value2) {
Double rfirst = value1.rank;
Double rsecond = value2.rank;
Double dfirst = value1.dist;
Double dsecond = value2.dist;
if (rsecond != rfirst) {
return (int) (rsecond - rfirst);
}
else {
return (int) (dsecond - dfirst);
}
}
};
}

Your Comperator approach would work, but is has a few bugs.
First of all I would replace the Doubles in MyEntry by double.
Comparing Double is not the same as comparing double
For example:
Double a = 1.0;
Double b = 1.0;
System.out.println(a == b);
System.out.println(a.equals(b));
System.out.println(a.doubleValue()== b.doubleValue());
Will return
false
true
true
Then in the comparison you cast to int, but this implies flooring that data.
(int) (2 - 1.9) will give 0
Better is to compare using < and return -1 or 1.
public static Comparator<MyEntry> ValueComparator = new Comparator<MyEntry>() {
public int compare(MyEntry value1, MyEntry value2) {
double rfirst = value1.rank;
double rsecond = value2.rank;
double dfirst = value1.dist;
double dsecond = value2.dist;
if (rsecond != rfirst) {
return rsecond < rfirst?-1:1;
}
else if(dsecond!=dfirst){
return dsecond < dfirst ?-1:1;
}
return 0;
}
}
For your second question you require an index. This could be done in two ways. First option is to include the index in MyEntry like this:
public class MyEntry implements Comparable<MyEntry> {
private double rank;
private double dist;
private int index;
private static int nextIndex = 0;
public MyEntry(double rank, double dist) {
this.rank = rank;
this.dist = dist;
this.index = nextIndex++;
}
This way you will be able to retain the index but it is not so flexible.
A more flexible approach could be to have the index in a separate array, and sort that.
class IndexedArrayComparator implements Comparator<Integer>{
MyEntry[] array;
public IndexedArrayComparator(MyEntry[] entries){
this.array=entries;
}
public Integer[] createIndexes(){
Integer[] index = new Integer[array.length];
for(int i =0;i<index.length;i++){
index[i]=i;
}
return index;
}
public int compare(Integer i0, Integer i1) {
double rfirst = array[i0].rank;
double rsecond = array[i1].rank;
double dfirst = array[i0].dist;
double dsecond = array[i1].dist;
if (rsecond != rfirst) {
return rsecond > rfirst?-1:1;
}
else if(dsecond!=dfirst){
return dsecond > dfirst ?-1:1;
}
return 0;
}
}
You can then use it like this:
MyEntry[] entries = new MyEntry[5];
entries[0]= new MyEntry(1.1,5);
entries[1]= new MyEntry(1.1,4);
entries[2]= new MyEntry(2.1,5);
entries[3]= new MyEntry(0.1,3);
entries[4]= new MyEntry(3.1,1);
IndexedArrayComparator comp = new IndexedArrayComparator(entries);
Integer[] index = comp.createIndexes();
Arrays.sort(index,comp);
for(int i =0;i<index.length;i++){
MyEntry e = entries[index[i]];
System.out.println(String.format("%2d:r= %3.1f, d= %3.1f" ,index[i],e.rank,e.dist));
}
Which will give:
3:r= 0.1, d= 3.0
1:r= 1.1, d= 4.0
0:r= 1.1, d= 5.0
2:r= 2.1, d= 5.0
4:r= 3.1, d= 1.0
The second way of sorting while maintaining the index is also described here. Credits to Jon Skeet

Related

Comparing products given three seperate lists

You are given a list of n products, each with a name, price and weight.
Find out how many duplicates of a product are present within the list. A duplicate is a product with all parameters, equal to some other product.
input is 3 lists
Name Price Weight
1. ball 2 1
2. box 2 2
3. ball 2 1
4. ball 2 1
5. box 2 3
output:
2
explanation:
(1.) is same as (3.) and is also same as (4.) so there is 2... 1->3 and 1->4
Function Description
numDuplicates has the following parameter(s):
name: string array of size n, where names[i] denotes the name of the ith product
price: int array of size n, where prices[i] denotes the price of the ith product
weight: int array of size n, where weights[i] denotes the weight of the ith product
function you need to fill out:
public static int numDuplicates(List<String> name, List<Integer> price, List<Integer> weight) {
// Write your code here
//return an int
}
this is what i wrote for my code and is O(n^2) but some test-cases are running out of time so i think it wants an O(n) solution but i cant think of it...
class Result {
/*
* Complete the 'numDuplicates' function below.
*
* The function is expected to return an INTEGER.
* The function accepts following parameters:
* 1. STRING_ARRAY name
* 2. INTEGER_ARRAY price
* 3. INTEGER_ARRAY weight
*/
public static int numDuplicates(List<String> name, List<Integer> price, List<Integer> weight) {
int count = 0;
List<obj> classList = new ArrayList<obj>();
for(int i=0; i<name.size(); i++){
obj holder = new obj(name.get(i),price.get(i),weight.get(i));
classList.add(holder);
}
for(int i=0; i<classList.size(); i++){
for(int j=i+1; j<classList.size();j++){
if(classList.get(i).isDuplicate(classList.get(j))){
count++;
classList.remove(classList.get(j));
j--;
}
}
}
return count;
}
}
class obj{
String name;
int price;
int weight;
public obj(String name, int price, int weight){
this.name = name;
this.price = price;
this.weight = weight;
}
public boolean isDuplicate(obj x){
if(this.name.equals(x.name) && this.price == x.price && this.weight == x.weight){
return true;
}
return false;
}
}
i created my own object class, and i created a compare method but i think it might be inefficent
For :
public static int numDuplicates(List<String> name, List<Integer> price, List<Integer> weight) {
// Write your code here
//return an int
}
Use Like below:
public static int numDuplicates(List<String> name, List<Integer> price, List<Integer> weight) {
List<String> f1 = new ArrayList<String>();
int countTotal = name.size();
for (int i = 0; i < countTotal; i++) {
f1.add(name.get(i) + price.get(i) + weight.get(i));
}
//Unique List item
Set<String> uniqueItemSet = new HashSet<String>(f1);
Integer uniqueItems = uniqueItemSet.size();
int countAll = f1.size();
return(countAll-uniqueItems);
}
public static int numDuplicates(List<String> name, List<Integer> price, List<Integer> weight) {
Set<String> uniqueProducts = new HashSet<String>();
for (int i = 0; i < name.size(); i++)
uniqueProducts.add(name.get(i) + " " + price.get(i) + " " + weight.get(i));
return name.size() - uniqueProducts.size();
}
public static int numDuplicates(List<String> names, List<Integer> price,
List<Integer> weight) {
int count = 0;
String product = "";
Map<String, Integer> dupMap = new HashMap<String, Integer>();
for (int i = 0; i < names.size(); i++) {
product = names.get(i) + price.get(i) + weight.get(i);
if (dupMap.get(product) != null) {
count++;
} else {
dupMap.put(product, 1);
}
}
return count;
}
List<string> final = new List<string>();
int countTotal = name.Count;
for (int i = 0; i < countTotal; i++) {
final.Add(name.ElementAt(i) + price.ElementAt(i) + weight.ElementAt(i));
}
var uniqueItems = final.Distinct();
int countDistinct = uniqueItems.Count();
return(countTotal-countDistinct);
public static int numDuplicates(List<String> name, List<Integer> price, List<Integer> weight) {
int res=0;
HashSet<String> set = new HashSet<String>();
for(int i=0;i<name.size();i++){
String cmb = name.get(i) + "_" + price.get(i)+ "_" + weight.get(i);
if(set.contains(cmb)){
res++;
}
else{
set.add(cmb);
}
}
return res;
}
}
Or you may put the values in a pandas dataframe, then take the length of that data frame, use drop_duplicate function on to the dataframe to drop duplicates, take the revised dataframe's length, and then calculate the difference in length and print.

Code test - Maximize cost for a given weight of a Package

You want to send your friend a package with different things. Each thing you put inside the package has such parameters as index number, weight and cost. The package has a weight limit. Your goal is to determine which things to put into the package so that the total weight is less than or equal to the package limit and the total cost is as large as possible.
You would prefer to send a package which weights less in case there is more than one package with the same price.
INPUT SAMPLE:
Your program should accept as its first argument a path to a filename. The input file contains several lines. Each line is one test case.
Each line contains the weight that the package can take (before the colon) and the list of things you need to choose. Each thing is enclosed in parentheses where the 1st number is a thing's index number, the 2nd is its weight and the 3rd is its cost. Eg:
81 : (1,53.38,45)(2,88.62,98) (3,78.48,3)(4,72.30,76) (5,30.18,9)(6,46.34,48)
8 : (1,15.3,34)
75:(1,85.31,29) (2,14.55,74)(3,3.98,16) (4,26.24,55)(5,63.69,52) (6,76.25,75)(7,60.02,74) (8,93.18,35)(9,89.95,78)
56 : (1,90.72,13)(2,33.80,40) (3,43.15,10)(4,37.97,16) (5,46.81,36)(6,48.77,79) (7,81.80,45)(8,19.36,79) (9,6.76,$64)
OUTPUT SAMPLE:
For each set of things that you put into the package provide a list (items’ index numbers are separated by comma).
E.g.
4 //for package1
- //for package2
2,7 //for package3
8,9 //for package4
CONSTRAINTS:
Max weight that a package can take is ≤ 100 There might be up to 15 items you need to choose from Max weight and cost of an item is ≤ 100
Is there a more elegant and easy to understand solution than https://discuss.codechef.com/questions/104934/package-problemin-java
Here is the code (KnapSack):
public class FriendPackageKnapsack {
public static void parserThings(String[] sub2, List<Package> things,
double maxWeight) {
for (int i = 0; i < sub2.length; i++) {
String[] sub3 = (sub2[i].substring(1, sub2[i].length() - 1)).split(",");
int id = Integer.parseInt(sub3[0]);
double weight = Double.parseDouble(sub3[1]);
double cost = Double.parseDouble(sub3[2].substring(1, sub3[2].length()));
if (weight <= maxWeight) {
Package condidat = new Package(id, weight, cost);
things.add(condidat);
}
}
}
public static String getOptimumFor(List<Package> things, int r, int maxWt) {
int indexSolution = 0;
String returnData = "";
double maxWeight = 0;
double maxCost = 0;
int[] data = new int[r];
List<Integer> res = new ArrayList<Integer>();
int[] arr = new int[things.size()];
for (int i = 0; i < things.size(); i++) {
arr[i] = i;
}
getCombination(arr, data, res, 0, 0);
for (int i = 0; i <= res.size() - r; i += r) {
double someWeight = 0;
double someCost = 0;
for (int j = 0; j < r; j++) {
someWeight += things.get(res.get(i + j)).getWeight();
someCost += things.get(res.get(i + j)).getCost();
}
if (someWeight <= maxWt) {
if ((someCost > maxCost)
|| ((someCost == maxCost) && (someWeight <= maxWeight))) {
indexSolution = i;
maxWeight = someWeight;
maxCost = someCost;
}
}
}
for (int k = indexSolution; k < r + indexSolution; k++) {
returnData += res.get(k) + ",";
}
return returnData + maxCost + "," + maxWeight;
}
public static void getCombination(int[] arr, int[] data, List<Integer> res, int start,
int index) {
if (index == data.length) {
for (int j = 0; j < data.length; j++) { res.add(data[j]); }
return;
}
for (int i = start; i < arr.length && arr.length - i >= data.length - index; i++) {
data[index] = arr[i];
getCombination(arr, data, res, i + 1, index + 1);
}
}
public static void main(String[] args) {
File file = new File("packageproblem.txt");
BufferedReader in = null;
try {
in = new BufferedReader(new FileReader(file));
}
catch (FileNotFoundException e) { e.printStackTrace(); }
String line = "";
List<Package> things = new ArrayList<>();
try {
while ((line = in.readLine()) != null) {
String s = "";
// Parsing line
String[] sub1 = line.split(" : ");
int N = Integer.parseInt(sub1[0]);
String[] sub2 = sub1[1].split(" ");
if (sub2.length > 1) {
things.clear();
parserThings(sub2, things, N);
double maxCost = 0;
double maxWeight = 0;
for (int i = 1; i <= things.size(); i++) {
String resultat = getOptimumFor(things, i, N);
// System.out.println(resultat);
String[] sub4 = resultat.split(",");
double cost = Double.parseDouble(sub4[sub4.length - 2]);
double weight = Double.parseDouble(sub4[sub4.length - 1]);
if (cost == maxCost) {
if (weight < maxWeight) {
maxCost = cost;
maxWeight = weight;
s = resultat;
}
}
if (cost > maxCost) {
maxCost = cost;
maxWeight = weight;
s = resultat;
}
}
// System.out.println(s);
String[] sub5 = s.split(",");
String ss = "";
for (int i = 0; i < sub5.length - 2; i++) {
ss += things.get(Integer.parseInt(sub5[i])).getId() + ",";
}
if (ss.equals("")) { System.out.println("-"); }
else { System.out.println(ss.substring(0, ss.length() - 1)); }
}
else { System.out.println("-"); }
}
}
catch (IOException e) { e.printStackTrace(); }
}
}
class Package {
private int id;
private double weight;
private double cost;
public Package(int id, double weight, double cost) {
this.id = id;
this.weight = weight;
this.cost = cost;
}
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public double getWeight() { return weight; }
public void setWeight(double weight) { this.weight = weight; }
public double getCost() { return cost; }
public void setCost(double cost) { this.cost = cost; }
}
The code is taken from here.
You can find a full solution of this problem in java here
https://github.com/rantibi/package-challenge

Generic Matrix Class conversions between different numbers

so I have to create a Matrix class that will generically combine different objects in an array. I know I can do this by checking the types but I want to find a better way. This has to work on Doubles, Integers, Floats, Shorts, Longs, Strings, etc. Here is my current code for this:
public class Matrix<E>{
private E mat2[];
private static final int SIZE = 4;
public Matrix(){
mat2 = (E[]) new Object[SIZE];
}
public Matrix(E a1, E a2, E b1, E b2){
mat2 = (E[]) new Object[SIZE];
mat2[0] = a1;
mat2[1] = a2;
mat2[2] = b1;
mat2[3] = b2;
}
public void add(Matrix<E> info){
if(mat2[0] instanceof Number){
for(int i = 0; i < SIZE; i++){
Double tmp = ((Double)info.getElement(i)).doubleValue();
Double other = tmp + ((Double)mat2[i]).doubleValue();
mat2[i] = (E) other;
}
}
}
public E getElement(int index){ return mat2[index];}
public String toString(){
String info = "[";
for(int i = 0; i < SIZE; i++){
info += "\t" + mat2[i];
info += (i % 2 == 1) ? "\t]\n[" : "";
}
return info.substring(0, info.length() - 1);
}
public static void main(String... arg){
Matrix<Integer> matInt = new Matrix<Integer>(new Integer(1), new Integer(0), new Integer(0), new Integer(1));
Matrix<Integer> matInt2 = new Matrix<Integer>(new Integer(1), new Integer(0), new Integer(0), new Integer(1));
System.out.println(matInt);
Matrix<String> matStr = new Matrix<String>("One", "Two", "Three", "Four");
System.out.println(matStr);
matInt.add(matInt2);
System.out.println(matInt);
}
}
Now let me draw your attention to this method:
public void add(Matrix<E> info){
if(mat2[0] instanceof Number){
for(int i = 0; i < SIZE; i++){
Double tmp = ((Double)info.getElement(i)).doubleValue();
Double other = tmp + ((Double)mat2[i]).doubleValue();
mat2[i] = (E) other;
}
}
}
I am assuming Double right now so that if it is a floating point number, it will maintain the decimal but if it isn't I was hoping to cut it off. I can easily accomplish what I need by doing something along the lines of:
public void add(Matrix<E> info){
if(mat2[0] instanceof Number){
for(int i = 0; i < SIZE; i++){
if(type == Double){
Double tmp ((Double)info.getElement(i)).doubleValue();
Double other = tmp + ((Double)mat2[i]).doubleValue();
mat2[i] = (E) other;
}
if(type == Integer){
//do integer instead
}
if(type == String){
//do String instead
}
}
}
}
but I am wondering if I can find a more Generic war of doing this without all the checks. The program is for an assignment so I must use generics. The idea is to be able to add and multiply the types in the array 'mat2'. So if I have Integer types they need to add together. If I have Strings they need to add together as well.

implementing Subset Sum with genetic Algorithm

import java.util.Collections;
import java.util.Vector;
public class Metaheuristic {
private static int[] DATA;
private static int NUM_CHROMOSOMES ;
private static int MAX_POWER;
private static int MAX_NUMBER;
private static int FITNESS_THRESHOLD;
private static float MUTATE = (float) .05;
private Vector population;
private boolean done = true;
int numRuns = 0;
public void GeneticAlgorithm (int[] data, int target, int n){
NUM_CHROMOSOMES = n;
MAX_POWER = data.length;
MAX_NUMBER = (int) Math.pow(2, MAX_POWER) - 1;
FITNESS_THRESHOLD = target;
DATA = new int[data.length];
DATA = data;
Metaheuristic s = new Metaheuristic();
s.start();
//System.out.println("s");
}
public Metaheuristic(){
generateRandomPopulation();
}
private void generateRandomPopulation(){
System.out.println("***Randomly Generating population with: " + NUM_CHROMOSOMES + " Chromosome(s)***");
population = new Vector();
for(int i = 0; i < NUM_CHROMOSOMES; ++i){
int randomValue = (int) (Math.random()*MAX_NUMBER);
population.add(new Chromosome(randomValue, MAX_POWER));
}
System.out.println("First Population: " + population +"\n");
}
public void start(){
Collections.sort(population);
Chromosome fitess = (Chromosome) population.lastElement();
done = fitess.fitness(DATA, FITNESS_THRESHOLD) >= MAX_POWER? true:false;
if(done){
System.out.println("DONE, solution found: " + fitess);
}
else{
numRuns++;
System.out.println("FITESS: " + fitess + " fitness: " + fitess.fitness(DATA, FITNESS_THRESHOLD ));
generateNewPopulation();
start();
}
}
private void generateNewPopulation(){
System.out.println("***Generating New Population");
Vector temp = new Vector();
for(int i = 0; i < population.size()/2; ++i){
Chromosome p1 = selectParent();
Chromosome p2 = selectParent();
temp.add(cross1(p1, p2));
temp.add(cross2(p1, p2));
}
population.clear();
population.addAll(temp);
System.out.println("New Population: " + population + "\n");
}
private Chromosome selectParent(){
int delta = population.size();
delta = NUM_CHROMOSOMES - NUM_CHROMOSOMES/2;
int num = (int) (Math.random()*10 + 1);
int index;
if(num >= 4){
index = (int) (Math.random()*delta + NUM_CHROMOSOMES/2);
}
else{
index = (int) (Math.random()*delta);
}
return (Chromosome) population.get(index);
}
private Chromosome cross1(Chromosome parent1, Chromosome parent2){
String bitS1 = parent1.getBitString();
String bitS2 = parent2.getBitString();
int length = bitS1.length();
String newBitString = bitS1.substring(0, length/2) + bitS2.substring(length/2, length);
Chromosome offspring = new Chromosome();
offspring.setBitString(newBitString);
if(shouldMutate()){
mutate(offspring);
}
return offspring;
}
private Chromosome cross2(Chromosome parent1, Chromosome parent2){
String bitS1 = parent1.getBitString();
String bitS2 = parent2.getBitString();
int length = bitS1.length();
String newBitString = bitS2.substring(0, length/2) + bitS1.substring(length/2, length);
Chromosome offspring = new Chromosome();
offspring.setBitString(newBitString);
if(shouldMutate()){
mutate(offspring);
}
return offspring;
}
private boolean shouldMutate(){
double num = Math.random();
int number = (int) (num*100);
num = (double) number/100;
return (num <= MUTATE);
}
private void mutate(Chromosome offspring){
String s = offspring.getBitString();
int num = s.length();
int index = (int) (Math.random()*num);
String newBit = flip(s.substring(index, index+1));
String newBitString = s.substring(0, index) + newBit + s.substring(index+1, s.length());
offspring.setBitString(newBitString);
}
private String flip(String s){
return s.equals("0")? "1":"0";
}
public static void main(String[] args) {
double average = 0;
int sum = 0;
for(int i = 0; i < 10; ++i){
Metaheuristic s = new Metaheuristic();
s.start();
sum = sum + s.numRuns;
average = (double) sum / (double)(i+1);
System.out.println("Number of runs: " + s.numRuns);
}
System.out.println("average runs: " + average);
}
}
import java.lang.Comparable;
public class Chromosome implements Comparable{
protected String bitString;
public static int[] DATA;
public int TARGET;
public Chromosome(){
}
public Chromosome(int value, int length){
bitString = convertIntToBitString(value, length);
}
public void setBitString(String s){
bitString = s;
}
public String getBitString(){
return bitString;
}
public int compareTo(Object o) {
Chromosome c = (Chromosome) o;
int num = countOnes(this.bitString) - countOnes(c.getBitString());
return num;
}
public int fitness(int[] data, int target){
DATA = new int[data.length];
System.arraycopy(data, 0, DATA, 0, data.length);
TARGET = target;
return countOnes(bitString);
}
public boolean equals(Object o){
if(o instanceof Chromosome){
Chromosome c = (Chromosome) o;
return c.getBitString().equals(bitString);
}
return false;
}
public int hashCode(){
return bitString.hashCode();
}
public String toString(){
return "Chromosome: " + bitString;
}
public static int countOnes(String bits){
int sum = 0;
for(int i = 0; i < bits.length(); ++ i){
String test = bits.substring(i, i+1);
sum = sum + (DATA[i]*Integer.parseInt(test));
}
return sum;
}
public static String convertIntToBitString(int val, int length){
int reval = val;
StringBuffer bitString = new StringBuffer(length);
for(int i = length-1; i >=0; --i ){
if( reval - (Math.pow(2, i)) >= 0 ){
bitString.append("1");
reval = (int) (reval - Math.pow(2, i));
}
else{
bitString.append("0");
}
}
return bitString.toString();
}
/* public static void main(String[] args){
//System.out.println(convertIntToBitString(2046, 10));
Chromosome c = new Chromosome(1234, 10);
System.out.println(c.fitness());
}*/
}
My fitness function is f(x ) = s · (C − P(x )) + (1 − s) · P(x ) in which C is my target value to reach and P(*x ) = (Sigma) wixi, where wi is the element's set and xi is 0 or 1 (the element is chosen or not). also s is 0 or 1, depends on p(x) value. please help me to write this fitness.
I have just tried it but the program run with errors.
You have several problems in your code, and obviously you didn't debug it. Here are some tips though.
First NUM_CHROMOSOMES is 0, because it's an uninitialized field (of the GeneticAlgorithm which you don't use).
Since NUM_CHROMOSOMES is 0, this for loop is useless:
for (int i = 0; i < NUM_CHROMOSOMES; ++i) {
Then, this line:
int randomValue = (int) (Math.random() * MAX_NUMBER);
Since MAX_NUMBER is never manually initialized (same as NUM_CHROMOSOMES, its value is 0, and so is randomValue.
Anyway, population is empty and since you don't test for emptyness, this line:
Chromosome fitess = (Chromosome) population.lastElement();
... throws an exception, because there is no such thing as a last element in your empty population Vector.
As a side note, StringBuffer, Vector are obsolete classes, and you never need to import Comparable, since it belongs to the java.lang package.

Altering the value of k in kNN algorithm - Java

I have applied the KNN algorithm for classifying handwritten digits. the digits are in vector format initially 8*8, and stretched to form a vector 1*64..
As it stands my code applies the kNN algorithm but only using k = 1. I'm not entirely sure how to alter the value k after attempting a couple of things I kept getting thrown errors. If anyone could help push me in the right direction it would be really appreciated. The training dataset can be found here and the validation set here.
ImageMatrix.java
import java.util.*;
public class ImageMatrix {
private int[] data;
private int classCode;
private int curData;
public ImageMatrix(int[] data, int classCode) {
assert data.length == 64; //maximum array length of 64
this.data = data;
this.classCode = classCode;
}
public String toString() {
return "Class Code: " + classCode + " Data :" + Arrays.toString(data) + "\n"; //outputs readable
}
public int[] getData() {
return data;
}
public int getClassCode() {
return classCode;
}
public int getCurData() {
return curData;
}
}
ImageMatrixDB.java
import java.util.*;
import java.io.*;
import java.util.ArrayList;
public class ImageMatrixDB implements Iterable<ImageMatrix> {
private List<ImageMatrix> list = new ArrayList<ImageMatrix>();
public ImageMatrixDB load(String f) throws IOException {
try (
FileReader fr = new FileReader(f);
BufferedReader br = new BufferedReader(fr)) {
String line = null;
while((line = br.readLine()) != null) {
int lastComma = line.lastIndexOf(',');
int classCode = Integer.parseInt(line.substring(1 + lastComma));
int[] data = Arrays.stream(line.substring(0, lastComma).split(","))
.mapToInt(Integer::parseInt)
.toArray();
ImageMatrix matrix = new ImageMatrix(data, classCode); // Classcode->100% when 0 -> 0% when 1 - 9..
list.add(matrix);
}
}
return this;
}
public void printResults(){ //output results
for(ImageMatrix matrix: list){
System.out.println(matrix);
}
}
public Iterator<ImageMatrix> iterator() {
return this.list.iterator();
}
/// kNN implementation ///
public static int distance(int[] a, int[] b) {
int sum = 0;
for(int i = 0; i < a.length; i++) {
sum += (a[i] - b[i]) * (a[i] - b[i]);
}
return (int)Math.sqrt(sum);
}
public static int classify(ImageMatrixDB trainingSet, int[] curData) {
int label = 0, bestDistance = Integer.MAX_VALUE;
for(ImageMatrix matrix: trainingSet) {
int dist = distance(matrix.getData(), curData);
if(dist < bestDistance) {
bestDistance = dist;
label = matrix.getClassCode();
}
}
return label;
}
public int size() {
return list.size(); //returns size of the list
}
public static void main(String[] argv) throws IOException {
ImageMatrixDB trainingSet = new ImageMatrixDB();
ImageMatrixDB validationSet = new ImageMatrixDB();
trainingSet.load("cw2DataSet1.csv");
validationSet.load("cw2DataSet2.csv");
int numCorrect = 0;
for(ImageMatrix matrix:validationSet) {
if(classify(trainingSet, matrix.getData()) == matrix.getClassCode()) numCorrect++;
} //285 correct
System.out.println("Accuracy: " + (double)numCorrect / validationSet.size() * 100 + "%");
System.out.println();
}
In the for loop of classify you are trying to find the training example that is closest to a test point. You need to switch that with a code that finds K of the training points that is the closest to the test data. Then you should call getClassCode for each of those K points and find the majority(i.e. the most frequent) of the class codes among them. classify will then return the major class code you found.
You may break the ties (i.e. having 2+ most frequent class codes assigned to equal number of training data) in any way that suits your need.
I am really inexperienced in Java, but just by looking around the language reference, I came up with the implementation below.
public static int classify(ImageMatrixDB trainingSet, int[] curData, int k) {
int label = 0, bestDistance = Integer.MAX_VALUE;
int[][] distances = new int[trainingSet.size()][2];
int i=0;
// Place distances in an array to be sorted
for(ImageMatrix matrix: trainingSet) {
distances[i][0] = distance(matrix.getData(), curData);
distances[i][1] = matrix.getClassCode();
i++;
}
Arrays.sort(distances, (int[] lhs, int[] rhs) -> lhs[0]-rhs[0]);
// Find frequencies of each class code
i = 0;
Map<Integer,Integer> majorityMap;
majorityMap = new HashMap<Integer,Integer>();
while(i < k) {
if( majorityMap.containsKey( distances[i][1] ) ) {
int currentValue = majorityMap.get(distances[i][1]);
majorityMap.put(distances[i][1], currentValue + 1);
}
else {
majorityMap.put(distances[i][1], 1);
}
++i;
}
// Find the class code with the highest frequency
int maxVal = -1;
for (Entry<Integer, Integer> entry: majorityMap.entrySet()) {
int entryVal = entry.getValue();
if(entryVal > maxVal) {
maxVal = entryVal;
label = entry.getKey();
}
}
return label;
}
All you need to do is adding K as a parameter. Keep in mind, however, that the code above does not handle ties in a particular way.

Categories