Creating objects with random attributes - java

I'm building a railway simulator including the classes Passenger and Station (among others). The Passenger class has an attribute endLoc, which will be the desired end location for each passenger (i.e. a station object). I'm generating a random number of passengers at each station on my network into an ArrayList, and would like their attribute of endLoc to be randomly generated as well (out of a list of all the station objects), but I can't work out how to make the attribute be a random one from a list each time.
ArrayList<Passenger> passengers = new ArrayList<Passenger>();
for (int i = 0; i<p; i++){
passengers.add(new Passenger(statA));
i.e. Once I have my random number, and have it mapped to which station I want, what do I put in the code instead of statA, to mean the station that applies to my random number?
Can anyone tell me how to do this, or at least point me in the right direction? Thanks.

Write something like this:
List<String> stations = new ArrayList<String>();
//add stations..in the list
int numStations = stations.size();
int maxPassengersAtStation = 100;//assgin you number
for(int sCount=0; sCount<numStations; sCount++){
int passangersAtStation = (int)(Math.random() * maxPassengersAtStation);
for(int j=0; j<passangersAtStation; j++){
int passengerDestination = sCount + (int)(
Math.random() * ((numStations - sCount) + 1));
passengers.add(new Passenger(stations.get(passengerDestination)));
}
}

Well, some random ideea would be to generate a number from 1 to your_list.length and then take that object from the list and assing it to your endLoc.

Generate a random int x and then do x = x % allStations.size();
The x would be your random index of the list with all stations.

Related

exclude number from the Random picker list

i have a Random picker code that picks random number for ex from 1 to 6 ..
can u give me a method how to exclude the picked number from the list of random pick ..
import java.util.Random;
Random rand = new Random();
int n = rand.nextInt(6) + 1;
like that for ex :
1.2.3.4.5.6
random pick=5
1.2.3.4.6
random pick=2
1.3.4.6
.. etc
ty in advance guys
You can add the numbers that have already been picked to an ArrayList and pick a number until the number is not contained in the list.
// list of numbers that I already picked
ArrayList<Integer> randomNumbersPicked = new ArrayList<>();
// int to save the current random number
int myCurrentRandomNumber;
while(iNeedAnotherNumber){
do {
myCurrentRandomNumber = generateRandomNumber(a, b);
//repeat this until the number is not in the list
} while (randomNumbersPicked.contains(new Integer(myCurrentRandomNumber)));
//here there is a unique random number, do what you will
System.out.println("A new number has been picked: " + myCurrentRandomNumber);
//add the number to the list so it wont be picked again
randomNumbersPicked.add(new Integer(myCurrentRandomNumber));
}
Best Regards!
Dknacht.
Put all valid numbers into an ArrayList and instead select a random index from the list. Then remove that number from the list and repeat.
My Java is a little rusty, so hopefully the code I write makes sense:
ArrayList<int> validOptions = /**/; // make your list with all initial options
int firstIndex = random.Next(validOptions.count());
int firstPick = validOptions.get(firstIndex);
validOptions.removeAt(firstIndex);
int secondIndex = random.Next(validOptions.count());
int secondPick = validOptions.get(secondIndex);
validOptions.removeAt(firstIndex);

How to change an element in a list of lists Java

This is a peice of my code, i am making a grid of 5x5 with random colors set to each section. I need to set the specified y_loc and x_loc in the list to the color randomly picked except i have not been able to find out how. It should be the second last line that is not operating as id like. I understand that i could do this in much much longer code but it would be nice to do it in less.
//making the map
ArrayList<ArrayList<String>> fullmap = new ArrayList<ArrayList<String>>();
ArrayList<String> y_row_0 = new ArrayList<String>();
ArrayList<String> y_row_1 = new ArrayList<String>();
ArrayList<String> y_row_2 = new ArrayList<String>();
ArrayList<String> y_row_3 = new ArrayList<String>();
ArrayList<String> y_row_4 = new ArrayList<String>();
//adding each row
fullmap.add(y_row_0);
fullmap.add(y_row_1);
fullmap.add(y_row_2);
fullmap.add(y_row_3);
fullmap.add(y_row_4);
Random rn = new Random();
//loop to randomly pick colors then set them to their destined locations
for (int y_loc = 0; y_loc < 6; y_loc++){
for (int x_loc = 0; x_loc < 6; x_loc++){
colorPicked = false;
while (!colorPicked){
int ranNum = rn.nextInt();
if (ranNum ==0){
if (redTot < 5) {
redTot += 1;
fullmap.set(y_loc).set(x_loc, "Red"));
colorPicked = true;
Since you have lists in list here, to set something at a specific location, you'll have to get the inner list and then perform the set on it.
The following should work:
fullmap.get(y_loc).set(x_loc, "Red"));
Also, since you seem to always have a 5x5 matrix, I'd recommend using a double array instead. That'd make that line:
fullmap[x_loc][y_loc] = "Red";
You should have something like this:
fullmap.get(y_loc).set(x_loc, "Red"));
Notice the "get". You are "getting" the list at the y location, which returns an array list, then calling "set" against that array list to set the actual value in the index of the "x_loc" value.
You need to make a couple of changes:
While declaring the sub lists, you need to make sure they have 5 empty/null elements. Otherwise set will throw IndexOutOfBoundsException. E.g. you need to declare the lists like this:
ArrayList<String> y_row_0 = Arrays.asList(new String[5]);//Assuming it will have 5 elements
While setting the element, you first need to get the corresponding sub list, e.g. the following needs to be changed from:
fullmap.set(y_loc).set(x_loc, "Red"));
to
fullmap.get(y_loc).set(x_loc, "Red"));
Others have already discussed the indexing issue. Apart from that, I believe that your conditionals may not be executing as you expect. nextInt() will return a reasonable uniform random number in the range of -2147483648 to 2147483647. You have a 1/2^64 chance of getting a 0. Reduce the random number range to something more reasonable. For example, nextInt(10) will return a random number between 0 and 9.
Furthermore, if the probability is too low, you will not get 5 reds all the time. To guarantee 5 picks and for the sake of computational efficiency, it is better to randomly pick array indices and evaluate whether a color is set or not, such as the following pseudo-code
int redTot = 0;
while ( redTot < 5 ) {
int r = rn.nextInt( 5 );
int c = rn.nextInt( 5 );
String color = fullmap.get( r ).get( c );
if ( color == null ) {
fullmap.get( r ).set( c, "Red" );
redTot++;
}
}

How to prevent genetic algorithm from converging on local minima?

I am trying to build a 4 x 4 sudoku solver by using the genetic algorithm. I have some issues with values converging to local minima. I am using a ranked approach and removing the bottom two ranked answer possibilities and replacing them with a crossover between the two highest ranked answer possibilities. For additional help avoiding local mininma, I am also using mutation. If an answer is not determined within a specific amount of generation, my population is filled with completely new and random state values. However, my algorithm seems to get stuck in local minima. As a fitness function, I am using:
(Total Amount of Open Squares * 7 (possible violations at each square; row, column, and box)) - total Violations
population is an ArrayList of integer arrays in which each array is a possible end state for sudoku based on the input. Fitness is determined for each array in the population.
Would someone be able to assist me in determining why my algorithm converges on local minima or perhaps recommend a technique to use to avoid local minima. Any help is greatly appreciated.
Fitness Function:
public int[] fitnessFunction(ArrayList<int[]> population)
{
int emptySpaces = this.blankData.size();
int maxError = emptySpaces*7;
int[] fitness = new int[populationSize];
for(int i=0; i<population.size();i++)
{
int[] temp = population.get(i);
int value = evaluationFunc(temp);
fitness[i] = maxError - value;
System.out.println("Fitness(i)" + fitness[i]);
}
return fitness;
}
Crossover Function:
public void crossover(ArrayList<int[]> population, int indexWeakest, int indexStrong, int indexSecStrong, int indexSecWeak)
{
int[] tempWeak = new int[16];
int[] tempStrong = new int[16];
int[] tempSecStrong = new int[16];
int[] tempSecWeak = new int[16];
tempStrong = population.get(indexStrong);
tempSecStrong = population.get(indexSecStrong);
tempWeak = population.get(indexWeakest);
tempSecWeak = population.get(indexSecWeak);
population.remove(indexWeakest);
population.remove(indexSecWeak);
int crossoverSite = random.nextInt(14)+1;
for(int i=0;i<tempWeak.length;i++)
{
if(i<crossoverSite)
{
tempWeak[i] = tempStrong[i];
tempSecWeak[i] = tempSecStrong[i];
}
else
{
tempWeak[i] = tempSecStrong[i];
tempSecWeak[i] = tempStrong[i];
}
}
mutation(tempWeak);
mutation(tempSecWeak);
population.add(tempWeak);
population.add(tempSecWeak);
for(int j=0; j<tempWeak.length;j++)
{
System.out.print(tempWeak[j] + ", ");
}
for(int j=0; j<tempWeak.length;j++)
{
System.out.print(tempSecWeak[j] + ", ");
}
}
Mutation Function:
public void mutation(int[] mutate)
{
if(this.blankData.size() > 2)
{
Blank blank = this.blankData.get(0);
int x = blank.getPosition();
Blank blank2 = this.blankData.get(1);
int y = blank2.getPosition();
Blank blank3 = this.blankData.get(2);
int z = blank3.getPosition();
int rando = random.nextInt(4) + 1;
if(rando == 2)
{
int rando2 = random.nextInt(4) + 1;
mutate[x] = rando2;
}
if(rando == 3)
{
int rando2 = random.nextInt(4) + 1;
mutate[y] = rando2;
}
if(rando==4)
{
int rando3 = random.nextInt(4) + 1;
mutate[z] = rando3;
}
}
The reason you see rapid convergence is that your methodology for "mating" is not very good. You are always producing two offspring from "mating" of the top two scoring individuals. Imagine what happens when one of the new offspring is the same as your top individual (by chance, no crossover and no mutation, or at least none that have an effect on the fitness). Once this occurs, the top two individuals are identical which eliminates the effectiveness of crossover.
A more typical approach is to replace EVERY individual on every generation. There are lots of possible variations here, but you might do a random choice of two parents weighted fitness.
Regarding population size: I don't know how hard of a problem sudoku is given your genetic representation and fitness function, but I suggest that you think about millions of individuals, not dozens.
If you are working on really hard problems, genetic algorithms are much more effective when you place your population on a 2-D grid and choosing "parents" for each point in the grid from the nearby individuals. You will get local convergence, but each locality will have converged on different solutions; you get a huge amount of variation produced from the borders between the locally-converged areas of the grid.
Another technique you might think about is running to convergence from random populations many times and store the top individual from each run. After you build up a bunch of different local minima genomes, build a new random population from those top individuals.
I think the Sudoku is a permutation problem. therefore i suggest you to use random permutation numbers for initializing population and use the crossover method which Compatible to permutation problems.

How to randomly choose one of many objects to be added to an array list?

Say I have 4 objects and I am looking to populate an arraylist of 100 elements with these four objects. Basically each time we add an elements to the arraylist, there is a 1 in 4 chance each element will be chosen. I thought of one way to do it but I think there is a better, more "pretty" & effective way
just rough pseudo-code to help explain
for(int i = 0; i != 100; i++){
Random generator = new Random();
int i = generator.nextInt(4); // this will give us 0,1,2,or 3
if(i ==0){
arraylist.add(object1(param1, param2));
}
// etc.. continues with 3 other else if statments and objects
ideas? All the other objects I have also share the same interface, if that can help us
Start with an array containing the four objects:
Object[] objects = new Object[] {
object1(param1, param2),
object2(param1),
object3(param1, param2, param3, param4),
object4(param1, param2)
}
Then adjust your code:
Random generator = new Random();
for(int i = 0; i < 100; i++){
int j = generator.nextInt(4); // this will give us 0,1,2,or 3
arraylist.add(objects[j]);
// etc.. continues with 3 other else if statments and objects
}
Notice that you don't have to create a new generator on every iteration - you can create it just once and reuse the same instance.

Generating an array of random points in java with no duplicates

I am fairly new to Java, and I want to generate an array of random (x,y) coordinates of length 'number' that contains no duplicates. x or y values can be repeated, but there must be no repeated (x,y) coordinates. The output does not have to be Points, simply some way of holding x,y values for coordinates.
I can generate an array of random points, and have tried using a Set to ensure there are no duplicate values, but have run into problems. I tried using the condition "while (set.size)" and the 'add' method which should disallow duplicates, to create an output of the correct size which contains unique points.
This is the code:
Set<Point> set = new HashSet<Point>();
Random position = new Random();
Point test=new Point();
do{
test.x=position.nextInt(xx);
test.y=position.nextInt(yy);
//xx and yy are the random number limits called from another part of the code
set.add(test);
}
while (set.size()<number);
List<Object> list = new ArrayList<Object>(set);
Object[] coord = list.toArray();
This outputs an array of the correct length, but every element is the same. Can anyone offer any help?
Thanks
test points to the same variable in space everytime you loop, to fix that create a new instance inside the loop - not just once before it:
Set<Point> set = new HashSet<Point>();
Random position = new Random();
Point test;
do{
test = new Point();
test.x=position.nextInt(xx);
test.y=position.nextInt(yy);
//xx and yy are the random number limits called from another part of the code
set.add(test);
}
while (set.size()<number);
List<Object> list = new ArrayList<Object>(set);
Object[] coord = list.toArray();
You are modifying the same point object. However, since you change X and Y every time, you also changing hash code and equality of the point, so you end up placing the same object multiple times in the set. Interesting case.
try
do{
test = new Point();
test.x=position.nextInt(xx);
test.y=position.nextInt(yy);
//xx and yy are the random number limits called from another part of the code
set.add(test);
}
while (set.size()<number);
Value select Randomly but not repeated
Random rndm = new Random();
String[] selectedNumber = new String[15];
String[] sequanceNumber = {"1","2","3","4","5","6","7","8","9","10","11","12","13","14","15"};
//*****FIRST LOOP START*****//
for(byte a = 0; a < 15;){
int temp = rndm.nextInt(15)+1;
//*****SECOND LOOP START*****//
for(byte b = 0; b < 15; b++){
String s4 = temp+"";
//*****CHECKING CONDITION START*****//
if(s4.equals(sequanceNumber[b]) ){
selectedNumber[a] = s4;
String s1 = sequanceNumber[b];
s1 = s1.replace(s1, " ");
sequanceNumber[b] = s1;
a++;
}
//*****CHECKING CONDITION END*****//
}
//*****SECOND LOOP END*****//
}
//*****FIRST LOOP END*****//
//*****PRINT ALL RANDOM VALUES BUT NOT REPEATED VALUES*****//
System.out.println(Arrays.toString(selectedNumber));

Categories