I am currently working with a gaming code library and one of the parts uses a genetic algorithm for some of the AI. This concept is rather new to me and although I've looked up and read about how it works I am finding it hard how to link precisely what is being evolved, mutated etc. to the actual code.
The actions are basically each of the possible options that the AI has to move. So it is trying to evolve a state and find out which is the best action to take. Can anyone help me understand it a bit clearer than that?
private static double GAMMA = 0.90;
private static long BREAK_MS = 35;
private static int SIMULATION_DEPTH = 7;
private static int POPULATION_SIZE = 5;
private static double RECPROB = 0.1;
private double MUT = (1.0 / SIMULATION_DEPTH);
private final int N_ACTIONS;
private ElapsedCpuTimer timer;
private int genome[][][];
private final HashMap<Integer, Types.ACTIONS> action_mapping;
private final HashMap<Types.ACTIONS, Integer> r_action_mapping;
protected Random randomGenerator;
private int numSimulations;
/**
* Public constructor with state observation and time due.
*
* #param stateObs state observation of the current game.
* #param elapsedTimer Timer for the controller creation.
*/
public Agent(StateObservation stateObs, ElapsedCpuTimer elapsedTimer) {
randomGenerator = new Random();
action_mapping = new HashMap<Integer, Types.ACTIONS>();
r_action_mapping = new HashMap<Types.ACTIONS, Integer>();
int i = 0;
for (Types.ACTIONS action : stateObs.getAvailableActions()) {
action_mapping.put(i, action);
r_action_mapping.put(action, i);
i++;
}
N_ACTIONS = stateObs.getAvailableActions().size();
initGenome(stateObs);
}
double microbial_tournament(int[][] actionGenome, StateObservation stateObs, StateHeuristic heuristic) throws TimeoutException {
int a, b, c, W, L;
int i;
a = (int) ((POPULATION_SIZE - 1) * randomGenerator.nextDouble());
do {
b = (int) ((POPULATION_SIZE - 1) * randomGenerator.nextDouble());
} while (a == b);
double score_a = simulate(stateObs, heuristic, actionGenome[a]);
double score_b = simulate(stateObs, heuristic, actionGenome[b]);
if (score_a > score_b) {
W = a;
L = b;
} else {
W = b;
L = a;
}
int LEN = actionGenome[0].length;
for (i = 0; i < LEN; i++) {
if (randomGenerator.nextDouble() < RECPROB) {
actionGenome[L][i] = actionGenome[W][i];
}
}
for (i = 0; i < LEN; i++) {
if (randomGenerator.nextDouble() < MUT) actionGenome[L][i] = randomGenerator.nextInt(N_ACTIONS);
}
return Math.max(score_a, score_b);
}
private void initGenome(StateObservation stateObs) {
genome = new int[N_ACTIONS][POPULATION_SIZE][SIMULATION_DEPTH];
// Randomize initial genome
for (int i = 0; i < genome.length; i++) {
for (int j = 0; j < genome[i].length; j++) {
for (int k = 0; k < genome[i][j].length; k++) {
genome[i][j][k] = randomGenerator.nextInt(N_ACTIONS);
}
}
}
}
private double simulate(StateObservation stateObs, StateHeuristic heuristic, int[] policy) throws TimeoutException {
//System.out.println("depth" + depth);
long remaining = timer.remainingTimeMillis();
if (remaining < BREAK_MS) {
//System.out.println(remaining);
throw new TimeoutException("Timeout");
}
int depth = 0;
stateObs = stateObs.copy();
for (; depth < policy.length; depth++) {
Types.ACTIONS action = action_mapping.get(policy[depth]);
stateObs.advance(action);
if (stateObs.isGameOver()) {
break;
}
}
numSimulations++;
double score = Math.pow(GAMMA, depth) * heuristic.evaluateState(stateObs);
return score;
}
private Types.ACTIONS microbial(StateObservation stateObs, int maxdepth, StateHeuristic heuristic, int iterations) {
double[] maxScores = new double[stateObs.getAvailableActions().size()];
for (int i = 0; i < maxScores.length; i++) {
maxScores[i] = Double.NEGATIVE_INFINITY;
}
outerloop:
for (int i = 0; i < iterations; i++) {
for (Types.ACTIONS action : stateObs.getAvailableActions()) {
StateObservation stCopy = stateObs.copy();
stCopy.advance(action);
double score = 0;
try {
score = microbial_tournament(genome[r_action_mapping.get(action)], stCopy, heuristic) + randomGenerator.nextDouble()*0.00001;
} catch (TimeoutException e) {
break outerloop;
}
int int_act = this.r_action_mapping.get(action);
if (score > maxScores[int_act]) {
maxScores[int_act] = score;
}
}
}
Types.ACTIONS maxAction = this.action_mapping.get(Utils.argmax(maxScores));
return maxAction;
}
/**
* Picks an action. This function is called every game step to request an
* action from the player.
*
* #param stateObs Observation of the current state.
* #param elapsedTimer Timer when the action returned is due.
* #return An action for the current state
*/
public Types.ACTIONS act(StateObservation stateObs, ElapsedCpuTimer elapsedTimer) {
this.timer = elapsedTimer;
numSimulations = 0;
Types.ACTIONS lastGoodAction = microbial(stateObs, SIMULATION_DEPTH, new WinScoreHeuristic(stateObs), 100);
return lastGoodAction;
}
#Override
public void draw(Graphics2D g)
{
//g.drawString("Num Simulations: " + numSimulations, 10, 20);
}
}
genome is the encoding of the solution (genotype) which is translated by simulate into the actual problem space (phenotype). In addition a fitness score is returned as part of the evaluation. The other methods initialise or perturbate the genotype to obtain a different solution.
Please ask more specific questions, if you need more rather than dumping a whole lot of code asking 'please explain'!
Related
Given the game http://mypuzzle.org/sliding, which starts with square grid containing tiles with numbers
from 1 to N and one empty block represented with X.The goal is to put the tiles according to their numbers.The
moving is done by moving a tile from left,right,top,bottom to the position of the empty tile.I have to solve this problem using IDA* and Manhattan approach
My goal is to output
1.On the first row output the length of the "optimal" path from the start to the destination state
2.The steps which solve the problem in order to reach our final state. The steps are left,right,up,down
Here is my current code working on solution for 3x3 :
/**
*
* Problem Name: Eight Algorithm: IDA* (Iterative deepening A*) using Manhattan Distance Heuristic
* Source: AI: A Modern Approach
*
*/
// Beware my messy code follows!
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
*
*
*
*
* #class used to keep State Machine of Eight Puzzle with f,g,h along with board
*
*/
class StateEightPuzzle {
private int f, g, h;
private StringBuilder stateofBoard;
private int xEmptyTile, yEmptyTile;
private int pre;
public void setStateofBoard(StringBuilder stateofBoard) {
this.stateofBoard = stateofBoard;
}
public void setPre(int pre) {
this.pre = pre;
}
public void setXEmptyTile(int xEmptyTile) {
this.xEmptyTile = xEmptyTile;
}
public void setYEmptyTile(int yEmptyTile) {
this.yEmptyTile = yEmptyTile;
}
public void setF(int f) {
this.f = f;
}
public void setG(int g) {
this.g = g;
}
public void setH(int h) {
this.h = h;
}
public int getPre() {
return pre;
}
public int getXEmptyTile() {
return xEmptyTile;
}
public int getYEmptyTile() {
return yEmptyTile;
}
public StringBuilder getStateofBoard() {
return stateofBoard;
}
public int getF() {
return f;
}
public int getG() {
return g;
}
public int getH() {
return h;
}
}
/**
*
* #class used as return type where flimit is used as current flimit and sol indicates whether
* solution is found
*
*/
class ReturnResult {
int flimit;
StateEightPuzzle sol;
}
public class Main {
/**
* #param args
*/
static int flag;
static int[] tracePath;
static private int ROWSIZE = 3;
static private int BOARDSIZE = 9;
/*
*
* function used to see whether the current Eight puzzle can be solvable that is can we subjugate
* our beloved using inversion permutation
*/
public static boolean isSolvable(String dpState) {
int inversion = 0;
for (int i = 0; i < BOARDSIZE; i++)
for (int j = i + 1; j < BOARDSIZE; j++)
if (dpState.charAt(i) > '0' && dpState.charAt(j) > '0'
&& dpState.charAt(i) > dpState.charAt(j))
inversion++;
if (inversion % 2 == 1)
return false;
else
return true;
}
/*
*
* getManhattanDistance returns Manhattan distance between current Node of Eight puzzle State
* Machine and Goal State(Final Destination)
*/
public static int getManhattanDistance(StringBuilder knightBoard) {
int manhattanVal = 0;
for (int i = 0; i < ROWSIZE; i++)
for (int j = 0; j < ROWSIZE; j++) {
int pos = i * ROWSIZE + j;
int val = (knightBoard.charAt(pos) - '0') - 1;
if (val == -1)
continue;
manhattanVal = manhattanVal + Math.abs((val / ROWSIZE) - i) + Math.abs((val % ROWSIZE) - j);
}
return manhattanVal;
}
/**
*
*
*
* #param stat
* #param x
* #param y
* #return
*
* function used to generate next State Machine of Eight Puzzle aka Successor Node(Child
* Node) of Current State(Father Node)
*
*/
public static StateEightPuzzle findSuccessor(StateEightPuzzle fatherNode, int x, int y, int pre) {
int nextXCordiante, nextYCordiante;
nextXCordiante = fatherNode.getXEmptyTile();
nextYCordiante = fatherNode.getYEmptyTile();
StateEightPuzzle childNode = new StateEightPuzzle();
if ((nextXCordiante + x) < 0 || (nextYCordiante + y) < 0 || (nextXCordiante + x) > (ROWSIZE - 1)
|| (nextYCordiante + y) > (ROWSIZE - 1)) {
flag = 0;
return childNode;
}
int nextEmptyTile = (nextXCordiante + x) * ROWSIZE + (nextYCordiante + y);
StringBuilder s1 = new StringBuilder(fatherNode.getStateofBoard());
char ch = s1.charAt(nextEmptyTile);
s1.setCharAt(nextEmptyTile, '0');
s1.setCharAt(ROWSIZE * nextXCordiante + nextYCordiante, ch);
childNode.setStateofBoard(s1);
childNode.setXEmptyTile(nextXCordiante + x);
childNode.setYEmptyTile(nextYCordiante + y);
childNode.setG(fatherNode.getG() + 1);
childNode.setH(getManhattanDistance(s1));
childNode.setPre(pre);
int maxfValue = (fatherNode.getF()) > (childNode.getG() + childNode.getH()) ? fatherNode.getF()
: (childNode.getG() + childNode.getH());
childNode.setF(maxfValue);
flag = 1;
return childNode;
}
/**
*
* #param init
* #param flimit
* #param res
* #return function known as Iterative Deepening DFS for A* which uses f-cost for limiting it
* search depth. Once the search inside a given contour has been completed , a new
* iteration is started with new f-cost for the next DFS-CONTOUR.pls consult Artificial
* Intelligence A Modern Approach, 1st edition by Approach By Russell
*
*/
public static ReturnResult DFS_CONTOUR(StateEightPuzzle Node, int flimit, ReturnResult res) {
int newf = Integer.MAX_VALUE;
ReturnResult resTemp = new ReturnResult();
StateEightPuzzle stat;
tracePath[Node.getG()] = Node.getPre();
// distance matrix for Eight Puzzle which helps to get successor
int dist[][] = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}};
// if current node exceeds flimit return it as flimit
if (Node.getF() > flimit) {
resTemp.flimit = Node.getF();
resTemp.sol = null;
return resTemp;
}
// I see : IDA* is going to give me juicy cool!
if (Node.getH() == 0) {
resTemp.flimit = flimit;
resTemp.sol = Node;
String sol = "uldr";
for (int i = 1; i <= Node.getG(); i++)
System.out.print(sol.charAt(tracePath[i]));
System.out.println("");
return resTemp;
}
// create next valid successor
for (int i = 0; i < 4; i++) {
if (Math.abs(i - Node.getPre()) == 2)
continue;
stat = findSuccessor(Node, dist[i][0], dist[i][1], i);
if (flag == 0)
continue;
resTemp = DFS_CONTOUR(stat, flimit, res);
if (resTemp.sol != null) {
resTemp.flimit = res.flimit;
return resTemp;
}
newf = resTemp.flimit < newf ? resTemp.flimit : newf;
}
resTemp.flimit = newf;
resTemp.sol = null;
return resTemp;
}
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String s_2;
while ((s_2 = in.readLine()) != null) {
String str = "";
tracePath = new int[1000];
int emptySquare = 0;
String[] s2 = s_2.split("\\s+");
for (int i = 0; i < s2.length; i++) {
if (s2[i].equals("x") == false)
str += s2[i];
else
str += "0";
}
if (isSolvable(str) == false) {
System.out.println("unsolvable");
} else {
StringBuilder str_bld = new StringBuilder(str);
for (int i = 0; i < str_bld.length(); i++)
if (str_bld.charAt(i) == '0') {
emptySquare += i;
break;
}
// Create Initial Eight puzzle State Machine and let him dance
// with
// prima donna :-)
StateEightPuzzle init = new StateEightPuzzle();
init.setStateofBoard(str_bld);
init.setG(0);
init.setH(getManhattanDistance(str_bld));
init.setF(init.getH() + init.getG());
init.setXEmptyTile(emptySquare / ROWSIZE);
init.setYEmptyTile(emptySquare % ROWSIZE);
init.setPre(5);
int flimit = init.getF();
ReturnResult result = new ReturnResult();
result.flimit = flimit;
result.sol = init;
// loop loop i m a strange loop living a mundane life with hopes
for (;;) {
ReturnResult resTemp = DFS_CONTOUR(init, flimit, result);
if (resTemp.sol != null) {
break;
}
flimit = resTemp.flimit;
}
}
}
}
}
The problem I find is for example for the puzzle when inputed 1 2 3 4 5 6 x 7 8 , it
should input just "ll" moving the "x" tile to the right two times however it inputs "urdlurdlurdr"
any ideas where the problem can be?
I need to create a program that can calculate approximation to the constant PI, using Java multi-thread.
I'm intent to use Gregory-Leibniz Series to calculate the result for PI / 4, and then multiply by 4 to get the PI approximation.
But I have some concern about the program:
How can I seperate the calculation process so that I can implement a multi-thread processing for the program? Because the formula is for the total sum, I don't know how to split them into parts and then in the end I will collect them all.
I'm thinking about the fact that the program will execute the formula to infinite so user will need to provide some means of configuring the execution in order to determine when it should stop and return a result. Is it possible and how can I do that?
This is so far the most I can do by now.
public class PICalculate {
public static void main(String[] args) {
System.out.println(calculatePI(5000000) * 4);
}
static double calculatePI(int n) {
double result = 0.0;
if (n < 0) {
return 0.0;
}
for (int i = 0; i <= n; i++) {
result += Math.pow(-1, i) / ((2 * i) + 1);
}
return result;
}
}
The most straightforward, but not the most optimal, approach is to distribute the sequence elements between threads you have. Ie, if you have 4 threads, thread one will work with n%4 == 0 elements, thread2 with n%4 == 1 elements and so on
public static void main(String ... args) throws InterruptedException {
int threadCount = 4;
int N = 100_000;
PiThread[] threads = new PiThread[threadCount];
for (int i = 0; i < threadCount; i++) {
threads[i] = new PiThread(threadCount, i, N);
threads[i].start();
}
for (int i = 0; i < threadCount; i++) {
threads[i].join();
}
double pi = 0;
for (int i = 0; i < threadCount; i++) {
pi += threads[i].getSum();
}
System.out.print("PI/4 = " + pi);
}
static class PiThread extends Thread {
private final int threadCount;
private final int threadRemainder;
private final int N;
private double sum = 0;
public PiThread(int threadCount, int threadRemainder, int n) {
this.threadCount = threadCount;
this.threadRemainder = threadRemainder;
N = n;
}
#Override
public void run() {
for (int i = 0; i <= N; i++) {
if (i % threadCount == threadRemainder) {
sum += Math.pow(-1, i) / (2 * i + 1);
}
}
}
public double getSum() {
return sum;
}
}
PiThread is more efficient, but arguably harder to read, if the loop is shorter:
public void run() {
for (int i = threadRemainder; i <= N; i += threadCount) {
sum += Math.pow(-1, i) / (2 * i + 1);
}
}
In case you don't want to limit yourself with number of elements in sequence and just by time, you may follow an approach below. But note, that it is still limited with Long.MAX_VALUE and you'll have to use BigIntegers, BigDecimals or any other reasonable approach to improve it
public static volatile boolean running = true;
public static void main(String ... args) throws InterruptedException {
int threadCount = 4;
long timeoutMs = 5_000;
final AtomicLong counter = new AtomicLong(0);
PiThread[] threads = new PiThread[threadCount];
for (int i = 0; i < threadCount; i++) {
threads[i] = new PiThread(counter);
threads[i].start();
}
Thread.sleep(timeoutMs);
running = false;
for (int i = 0; i < threadCount; i++) {
threads[i].join();
}
double sum = 0;
for (int i = 0; i < threadCount; i++) {
sum += threads[i].getSum();
}
System.out.print("counter = " + counter.get());
System.out.print("PI = " + 4*sum);
}
static class PiThread extends Thread {
private AtomicLong counter;
private double sum = 0;
public PiThread(AtomicLong counter) {
this.counter = counter;
}
#Override
public void run() {
long i;
while (running && isValidCounter(i = counter.getAndAdd(1))) {
sum += Math.pow(-1, i) / (2 * i + 1);
}
}
private boolean isValidCounter(long value) {
return value >= 0 && value < Long.MAX_VALUE;
}
public double getSum() {
return sum;
}
}
I have implemented serial and parallel algorithm for solving linear systems using jacobi method. Both implementations converge and give correct solutions.
I am having trouble with understanding:
How can parallel implementation converge after so low number of iterations compared to serial (same method is used in both). Am I facing some concurrency issues that I am not aware of?
How can number of iterations vary from run to run in parallel implementation (6,7)?
Thanks!
Program output:
Mathematica solution: {{-1.12756}, {4.70371}, {-1.89272}, {1.56218}}
Serial: iterations=7194 , error=false, solution=[-1.1270591, 4.7042074, -1.8922218, 1.5626835]
Parallel: iterations=6 , error=false, solution=[-1.1274619, 4.7035804, -1.8927546, 1.5621948]
Code:
Main
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
Serial s = new Serial();
Parallel p = new Parallel(2);
s.solve();
p.solve();
System.out.println("Mathematica solution: {{-1.12756}, {4.70371}, {-1.89272}, {1.56218}}");
System.out.println(String.format("Serial: iterations=%d , error=%s, solution=%s", s.iter, s.errorFlag, Arrays.toString(s.data.solution)));
System.out.println(String.format("Parallel: iterations=%d , error=%s, solution=%s", p.iter, p.errorFlag, Arrays.toString(p.data.solution)));
}
}
Data
public class Data {
public float A[][] = {{2.886139567217389f, 0.9778259187352214f, 0.9432146432722157f, 0.9622157488990459f}
,{0.3023479007910952f,0.7503803506938734f,0.06163831478699766f,0.3856445043958068f}
,{0.4298384105199724f, 0.7787439716945019f, 1.838686110345417f, 0.6282668788698587f}
,{0.27798718418255075f, 0.09021764079496353f, 0.8765867330141233f, 1.246036349549629f}};
public float b[] = {1.0630309381779384f,3.674438173599066f,0.6796639099285651f,0.39831385324794155f};
public int size = A.length;
public float x[] = new float[size];
public float solution[] = new float[size];
}
Parallel
import java.util.Arrays;
public class Parallel {
private final int workers;
private float[] globalNorm;
public int iter;
public int maxIter = 1000000;
public double epsilon = 1.0e-3;
public boolean errorFlag = false;
public Data data = new Data();
public Parallel(int workers) {
this.workers = workers;
this.globalNorm = new float[workers];
Arrays.fill(globalNorm, 0);
}
public void solve() {
JacobiWorker[] threads = new JacobiWorker[workers];
int batchSize = data.size / workers;
float norm;
do {
for(int i=0;i<workers;i++) {
threads[i] = new JacobiWorker(i,batchSize);
threads[i].start();
}
for(int i=0;i<workers;i++)
try {
threads[i].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
// At this point all worker calculations are done!
norm = 0;
for (float d : globalNorm) if (d > norm) norm = d;
if (norm < epsilon)
errorFlag = false; // Converged
else
errorFlag = true; // No desired convergence
} while (norm >= epsilon && ++iter <= maxIter);
}
class JacobiWorker extends Thread {
private final int idx;
private final int batchSize;
JacobiWorker(int idx, int batchSize) {
this.idx = idx;
this.batchSize = batchSize;
}
#Override
public void run() {
int upper = idx == workers - 1 ? data.size : (idx + 1) * batchSize;
float localNorm = 0, diff = 0;
for (int j = idx * batchSize; j < upper; j++) { // For every
// equation in batch
float s = 0;
for (int i = 0; i < data.size; i++) { // For every variable in
// equation
if (i != j)
s += data.A[j][i] * data.x[i];
data.solution[j] = (data.b[j] - s) / data.A[j][j];
}
diff = Math.abs(data.solution[j] - data.x[j]);
if (diff > localNorm) localNorm = diff;
data.x[j] = data.solution[j];
}
globalNorm[idx] = localNorm;
}
}
}
Serial
public class Serial {
public int iter;
public int maxIter = 1000000;
public double epsilon = 1.0e-3;
public boolean errorFlag = false;
public Data data = new Data();
public void solve() {
float norm,diff=0;
do {
for(int i=0;i<data.size;i++) {
float s=0;
for (int j = 0; j < data.size; j++) {
if (i != j)
s += data.A[i][j] * data.x[j];
data.solution[i] = (data.b[i] - s) / data.A[i][i];
}
}
norm = 0;
for (int i=0;i<data.size;i++) {
diff = Math.abs(data.solution[i]-data.x[i]); // Calculate convergence
if (diff > norm) norm = diff;
data.x[i] = data.solution[i];
}
if (norm < epsilon)
errorFlag = false; // Converged
else
errorFlag = true; // No desired convergence
} while (norm >= epsilon && ++iter <= maxIter);
}
}
I think its a matter of implementation and not parallelization. Look at what happens with Parallel p = new Parallel(1);
Mathematica solution: {{-1.12756}, {4.70371}, {-1.89272}, {1.56218}}
Serial: iterations=7194 , error=false, solution=[-1.1270591, 4.7042074, -1.8922218, 1.5626835]
Parallel: iterations=6 , error=false, solution=[-1.1274619, 4.7035804, -1.8927546, 1.5621948]
As it turns out - your second implementation is not doing exactly the same thing as your first one.
I added this into your parallel version and it ran in the same number of iterations.
for (int i = idx * batchSize; i < upper; i++) {
diff = Math.abs(data.solution[i] - data.x[i]); // Calculate
// convergence
if (diff > localNorm)
localNorm = diff;
data.x[i] = data.solution[i];
}
}
Could any help me start?
Using a class that I created before, I need to make a new class that specifically deals with QuadPoly. I think I have the constructors made correctly but i'm not a hundred percent sure.
public class Poly {
private float[] coefficients;
public static void main (String[] args){
float[] fa = {3, 2, 4};
Poly test = new Poly(fa);
}
public Poly() {
coefficients = new float[1];
coefficients[0] = 0;
}
public Poly(int degree) {
coefficients = new float[degree+1];
for (int i = 0; i <= degree; i++)
coefficients[i] = 0;
}
public Poly(float[] a) {
coefficients = new float[a.length];
for (int i = 0; i < a.length; i++)
coefficients[i] = a[i];
}
public int getDegree() {
return coefficients.length-1;
}
public float getCoefficient(int i) {
return coefficients[i];
}
public void setCoefficient(int i, float value) {
coefficients[i] = value;
}
public Poly add(Poly p) {
int n = getDegree();
int m = p.getDegree();
Poly result = new Poly(Poly.max(n, m));
int i;
for (i = 0; i <= Poly.min(n, m); i++)
result.setCoefficient(i, coefficients[i] + p.getCoefficient(i));
if (i <= n) {
//we have to copy the remaining coefficients from this object
for ( ; i <= n; i++)
result.setCoefficient(i, coefficients[i]);
} else {
// we have to copy the remaining coefficients from p
for ( ; i <= m; i++)
result.setCoefficient(i, p.getCoefficient(i));
}
return result;
}
public void displayPoly () {
for (int i=0; i < coefficients.length; i++)
System.out.print(" "+coefficients[i]);
System.out.println();
}
private static int max (int n, int m) {
if (n > m)
return n;
return m;
}
private static int min (int n, int m) {
if (n > m)
return m;
return n;
}
public Poly multiplyCon (double c){
int n = getDegree();
Poly results = new Poly(n);
for (int i =0; i <= n; i++){ // can work when multiplying only 1 coefficient
results.setCoefficient(i, (float)(coefficients[i] * c)); // errors ArrayIndexOutOfBounds for setCoefficient
}
return results;
}
public Poly multiplyPoly (Poly p){
int n = getDegree();
int m = p.getDegree();
Poly result = null;
for (int i = 0; i <= n; i++){
Poly tmpResult = p.multiByConstantWithDegree(coefficients[i], i); //Calls new method
if (result == null){
result = tmpResult;
} else {
result = result.add(tmpResult);
}
}
return result;
}
public void leadingZero() {
int degree = getDegree();
if ( degree == 0 ) return;
if ( coefficients[degree] != 0 ) return;
// find the last highest degree with non-zero cofficient
int highestDegree = degree;
for ( int i = degree; i <= 0; i--) {
if ( coefficients[i] == 0 ) {
highestDegree = i -1;
} else {
// if the value is non-zero
break;
}
}
float[] newCoefficients = new float[highestDegree + 1];
for ( int i=0; i<= highestDegree; i++ ) {
newCoefficients[i] = coefficients[i];
}
coefficients = newCoefficients;
}
public Poly differentiate(){
int n = getDegree();
Poly newResult = new Poly(n);
if (n>0){ //checking if it has a degree
for (int i = 1; i<= n; i++){
newResult.coefficients[i-1]= coefficients[i] * (i); // shift degree by 1 and multiplies
}
return newResult;
} else {
return new Poly(); //empty
}
}
public Poly multiByConstantWithDegree(double c, int degree){ //used specifically for multiply poly
int oldPolyDegree = this.getDegree();
int newPolyDegree = oldPolyDegree + degree;
Poly newResult = new Poly(newPolyDegree);
//set all coeff to zero
for (int i = 0; i<= newPolyDegree; i++){
newResult.coefficients[i] = 0;
}
//shift by n degree
for (int j = 0; j <= oldPolyDegree; j++){
newResult.coefficients[j+degree] = coefficients[j] * (float)c;
}
return newResult;
}
}
Out of this, I need to create a method that factors a Quadratic in two factors (if it has real roots), or in a constant ”1” polynomial factor and itself, if there are no real roots. The method should return an array of two QuadPoly objects, containing each factor.
public class QuadPoly extends Poly
{
private float [] quadcoefficients;
public QuadPoly() {
super(2);
}
public QuadPoly(float [] a) {
quadcoefficients = new float[a.length];
for (int i = 0; i <a.length; i ++){
quadcoefficients[i] = a[i];
if (quadcoefficients.length > 2){
throw new IllegalArgumentException ("Must be Quadratic");
}
}
}
public QuadPoly(Poly p){
if (quadcoefficients.length > 2){
throw new IllegalArgumentException ("Must be Quadratic");
}
}
public QuadPoly addQuad (QuadPoly p){
return new QuadPoly(super.add(p));
}
public Poly multiplyQuadPoly (Poly p){
if (quadcoefficients.length > 2){
throw new IllegalArgumentException ("Must be Quadratic");
}
Poly newResult = null;
new Result = multiplyPoly(p);
}
}
}
Edit:
Sorry. This is what I have going on for the factoring so far. The big problem with it is that I'm not too sure how to get the inheritance to work properly.
This is my New Factoring. It doesn't work. Can anyone give me some hints to get on the right path? I understand that I need to return Poly so i'm replacing the arrays there as you can tell by the first if statement but it won't let me progress as its says it requires (int, float). I've casted it but it still won't allow me. Thanks
public QuadPoly factor(){
double a = (double) getCoefficient(0);
double b = (double) getCoefficient(1);
double c = (double) getCoefficient(2);
QuadPoly newCoefficients = new QuadPoly(4);
double equa = Math.sqrt((b*b) - (4*a*c));
if (equa > 0){
newCoefficients.setCoefficient(0, (float) (-b + equa)/(2*a));
newCoefficients.setCoefficient(1, (float) (-b - equa)/(2*a));
}
if (equa ==0){
newCoefficients[0] = 1;
newCoefficients[1] = (-b + equa)/(2*a);
}
if (equa < 0){
newCoefficients[0] = 0;
newCoefficients[1] = 1;
}
return (QuadPoly) newCoefficients;
}
OK you have made a reasonable attempt. Inheritance is simple here, all you need is the constructors:
class QuadPoly extends Poly{
public QuadPoly(){ super(2); }
public QuadPoly(float[] f){
super(f);
if(coefficients.length!=2) throw new IllegalArgumentException("not quad");
}
}
and that's pretty much all! I hope you can see, that the same code as Poly is used for everything else, and the same field coefficients does all the same work as it did before.
Now, in the factorisation
you have dimmed your double[] newCoefficients as size 1. too small!
you have tried to square-root your discriminant without knowing that it is positive!
you are returning an array of 2 doubles as your answer. you need two Polys. You haven't provided a method return type for factor
I suggest you use
public QuadPoly[] factor(){
}
as the signature. The rest is just maths!
The idea of subclassing Poly into QuadPoly is so that you can reuse as many of the old Poly methods as possible. Now, all your old methods use the array float[] coefficients, and your new QuadPoly inherits this field.
Why have you created a new field quadcoefficients[] ? It suffices to check in any constructor that there are only 3 members in the array, but to still harness the existing field coefficients[].
If you do this, all your old methods will still work! Only, they will return generic Poly. Since the QuadPoly must conform to the contract of a Poly, this is probably OK. The method multiplyCon is the only one that could be guaranteed to return another QuadPoly anyway.
You don't seem to have attempted a factorisation yet. Do you have any ideas? Well, here's a clue: you'll need to use something like
if (DISCRIMINANT >= 0) {
} else{
}
I'm trying to compute Pi, but what I really want to achieve is efficiency when using more than one thread. The algorithm is simple: I randomly generate points in the unit square and after that count how many of them are in the circle inscribed within the square. (more here: http://math.fullerton.edu/mathews/n2003/montecarlopimod.html)
My idea is to split the square horizontally and to run a different thread for each part of it.
But instead of speed up, all I get is a delay. Any ideas why? Here is the code:
public class TaskManager {
public static void main(String[] args) {
int threadsCount = 3;
int size = 10000000;
boolean isQuiet = false;
PiCalculator pi = new PiCalculator(size);
Thread tr[] = new Thread[threadsCount];
long time = -System.currentTimeMillis();
int i;
double s = 1.0/threadsCount;
int p = size/threadsCount;
for(i = 0; i < threadsCount; i++) {
PiRunnable r = new PiRunnable(pi, s*i, s*(1.0+i), p, isQuiet);
tr[i] = new Thread(r);
}
for(i = 0; i < threadsCount; i++) {
tr[i].start();
}
for(i = 0; i < threadsCount; i++) {
try {
tr[i].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
double myPi = 4.0*pi.getPointsInCircle()/pi.getPointsInSquare();
System.out.println(myPi + " time = " + (System.currentTimeMillis()+time));
}
}
public class PiRunnable implements Runnable {
PiCalculator pi;
private double minX;
private double maxX;
private int pointsToSpread;
public PiRunnable(PiCalculator pi, double minX, double maxX, int pointsToSpread, boolean isQuiet) {
super();
this.pi = pi;
this.minX = minX;
this.maxX = maxX;
this.pointsToSpread = pointsToSpread;
}
#Override
public void run() {
int n = countPointsInAreaInCircle(minX, maxX, pointsToSpread);
pi.addToPointsInCircle(n);
}
public int countPointsInAreaInCircle (double minX, double maxX, int pointsCount) {
double x;
double y;
int inCircle = 0;
for (int i = 0; i < pointsCount; i++) {
x = Math.random() * (maxX - minX) + minX;
y = Math.random();
if (x*x + y*y <= 1) {
inCircle++;
}
}
return inCircle;
}
}
public class PiCalculator {
private int pointsInSquare;
private int pointsInCircle;
public PiCalculator(int pointsInSquare) {
super();
this.pointsInSquare = pointsInSquare;
}
public synchronized void addToPointsInCircle (int pointsCount) {
this.pointsInCircle += pointsCount;
}
public synchronized int getPointsInCircle () {
return this.pointsInCircle;
}
public synchronized void setPointsInSquare (int pointsInSquare) {
this.pointsInSquare = pointsInSquare;
}
public synchronized int getPointsInSquare () {
return this.pointsInSquare;
}
}
Some results:
-for 3 threads: "3.1424696 time = 2803"
-for 1 thread: "3.1416192 time = 2337"
Your threads could be fighting/waiting for Math.random() which is synchronized, you should create an instance of java.util.Random for each thread. Also in this case speedup with multiple threads will only happen if you have more than one core/cpu.
From the javadoc of Math.random():
This method is properly synchronized
to allow correct use by more than one
thread. However, if many threads need
to generate pseudorandom numbers at a
great rate, it may reduce contention
for each thread to have its own
pseudorandom-number generator.
Here is an alternate main method that uses the java.util.concurrency package instead of manually managing the threads and waiting for them to finish.
public static void main(final String[] args) throws InterruptedException
{
final int threadsCount = Runtime.getRuntime().availableProcessors();
final int size = 10000000;
boolean isQuiet = false;
final PiCalculator pi = new PiCalculator(size);
final ExecutorService es = Executors.newFixedThreadPool(threadsCount);
long time = -System.currentTimeMillis();
int i;
double s = 1.0 / threadsCount;
int p = size / threadsCount;
for (i = 0; i < threadsCount; i++)
{
es.submit(new PiRunnable(pi, s * i, s * (1.0 + i), p, isQuiet));
}
es.shutdown();
while (!es.isTerminated()) { /* do nothing waiting for threads to complete */ }
double myPi = 4.0 * pi.getPointsInCircle() / pi.getPointsInSquare();
System.out.println(myPi + " time = " + (System.currentTimeMillis() + time));
}
I also changed the Math.random() to use local instances of Random for each Runnable.
final private Random rnd;
...
x = this.rnd.nextDouble() * (maxX - minX) + minX;
y = this.rnd.nextDouble();
this is the new output I get ...
3.1419284 time = 235
I think you could probably drop the time some more using Futures and not having to synchronized so much on the PiCalculator.