I have writen a program in Processing to implement the Bentley-Ottmann algorithm for the line segment intersection problem.
The program returns a set of points but it does not find all the intersections. Can anyone tell me please what have I done wrong?
An ArrayList holds the active line segments that intersect the sweep line.
For each endpoint I store its x position and the Line2D it belongs to, at an TreeMap(Double, List(Line2D)) structure.
I am holding a List of Lines2D (TreeMap(Double, List(Line2D) ) because if I find an intersection I report its x position and the two lines that intersect.
I think I followed all the steps required by the algorithm. I've studied from the "Computational Geometry - Algorithms and Applications", and also a pdf named "Computing intersections in a set of line segments: the Bentley-Ottmann algorithm" from Michiel Smid.
Although, I am not taking into account the restrictions about the vertical lines, intersection with three segments etc. most of the times the requirements are met but still the results are not the expected ones.
This is an example
This is my code
import java.util.*;
import java.awt.*;
import java.awt.geom.*;
import java.util.List;
import java.util.concurrent.TimeUnit;
Algorithm algorithm = new Algorithm();
List<Line2D> initialList = new ArrayList<Line2D>();
List<Double> xStructure = new ArrayList<Double>();
Set<Point2D> intersections = new HashSet<Point2D>();
void setup() {
size(640, 480);
initialList = algorithm.createListOfRandomLines(5);
long start = System.currentTimeMillis();
intersections = algorithm.runBentleyOttmann(initialList);
long stop = System.currentTimeMillis() - start;
System.out.println(String.format("Execution Time: %f sec", (float)TimeUnit.MILLISECONDS.toSeconds(stop)));
}
void draw() {
background(255);
strokeWeight(1);
stroke(0);
for(Line2D l : initialList)
line((float)l.getX1(), (float)l.getY1(), (float)l.getX2(), (float)l.getY2());
strokeWeight(5);
stroke(255,0,0);
for(Point2D p : intersections)
point((float)p.getX(), (float)p.getY());
}
class Algorithm {
TreeMap<Double, List<Line2D>> xStructure;
Double slPosition;
List<Line2D> slStatus; // Y-structure
Set<Point2D> intersectionPoints;
public Algorithm() {
intersectionPoints = new HashSet<Point2D>();
slPosition = Double.MIN_VALUE;
slStatus = new ArrayList<Line2D>();
xStructure = new TreeMap<Double, List<Line2D>>();
}
public Set<Point2D> runBentleyOttmann(List<Line2D> list) {
//System.out.println("DEBUG INFO: runBentleyOttmann got input a list of " + list.size() + " line segments.");
xStructure = createMapOfSortedEndpointsAndCorespondingLineSegment(list);
//System.out.println("DEBUG INFO: runBentleyOttmann x-structure now contains the " + xStructure.size() + " endpoints.");
//System.out.println("DEBUG INTO: runBentleyOttmann sweep line is at position " + slPosition);
//System.out.println("DEBUG INFO: runBentleyOttmann begins while loop");
while (!xStructure.isEmpty()) {
Map.Entry<Double, List<Line2D>> entry = xStructure.pollFirstEntry();
Double min = entry.getKey();
slPosition = min;
List<Line2D> lines = entry.getValue();
//System.out.println("-----DEBUG INFO: runBentleyOttmann let min be the minimum element of x-structure " + min);
//System.out.println("-----DEBUG INFO: runBentleyOttmann delete min from the x-structure");
//System.out.println("-----DEBUG INFO: runBentleyOttmann checks endpoint type");
if (checkEndpointType(lines) == EndpointType.LEFT) {
//System.out.println("----------DEBUG INFO: Endpoint Type LEFT");
handleLeftEndpoint(lines);
}
else if (checkEndpointType(lines) == EndpointType.RIGHT) {
//System.out.println("----------DEBUG INFO: Endpoint Type RIGHT");
handleRightEndpoint(lines);
}
else if (checkEndpointType(lines) == EndpointType.INTERSECTION) {
//System.out.println("----------DEBUG INFO: Endpoint Type INTERSECTION");
handleIntersectionEndpoint(lines);
}
}
//System.out.println("DEBUG INFO: runBentleyOttmann ends while loop");
return intersectionPoints;
}
public void handleIntersectionEndpoint(List<Line2D> lines) {
Line2D l1 = slStatus.get(slStatus.indexOf(lines.get(0)));
Line2D l2 = slStatus.get(slStatus.indexOf(lines.get(1)));
if (slStatus.indexOf(l1) > slStatus.indexOf(l2)) {
Line2D ltemp = slStatus.get(slStatus.indexOf(lines.get(0)));
l1 = l2;
l2 = ltemp;
}
Line2D prev;
Line2D next;
if (slStatus.indexOf(l1) > 0) {
prev = getAboveLine(l1);
if (prev != null)
if (l2.intersectsLine(prev)) {
Point2D ip = findIntersectionPoint(l2, prev);
if (ip.getX() > slPosition) {
intersectionPoints.add(findIntersectionPoint(l2, prev));
List<Line2D> tempList = new ArrayList<Line2D>();
tempList.add(l2);
tempList.add(prev);
xStructure.put(ip.getX(), tempList);
}
}
}
if (slStatus.indexOf(l2) < slStatus.size()-1) {
next = getBelowLine(l2);
if (next != null)
if (l1.intersectsLine(next)) {
Point2D ip = findIntersectionPoint(l1, next);
if (ip.getX() > slPosition) {
intersectionPoints.add(findIntersectionPoint(l1, next));
List<Line2D> tempList = new ArrayList<Line2D>();
tempList.add(l1);
tempList.add(next);
xStructure.put(ip.getX(), tempList);
}
}
}
System.out.println(slStatus.indexOf(l1) + " " + slStatus.indexOf(l2));
}
public void handleLeftEndpoint(List<Line2D> lines) {
//System.out.println("HANDLE LEFT ENDPOINT started");
slStatus.add(lines.get(0));
//System.out.println("Line [X1=" + lines.get(0).getX1() + ", Y1=" + lines.get(0).getY1() + ", X2=" + lines.get(0).getX2() + ", Y2=" + lines.get(0).getY2() + "] added to Y-Structure.");
Collections.sort(slStatus, new YComparator());
//System.out.println("Y-Structure is sorted by Y endpoint");
Line2D above = getAboveLine(lines.get(0));
if (above != null)
if (lines.get(0).intersectsLine(above)) {
Point2D ip = findIntersectionPoint(lines.get(0), above);
if (ip.getX() > slPosition) {
intersectionPoints.add(findIntersectionPoint(lines.get(0), above));
List<Line2D> tempList = new ArrayList<Line2D>();
tempList.add(lines.get(0));
tempList.add(above);
xStructure.put(ip.getX(), tempList);
}
}
Line2D below = getBelowLine(lines.get(0));
if (below != null)
if (lines.get(0).intersectsLine(below)) {
Point2D ip = findIntersectionPoint(lines.get(0), below);
if (ip.getX() > slPosition) {
intersectionPoints.add(findIntersectionPoint(lines.get(0), below));
List<Line2D> tempList = new ArrayList<Line2D>();
tempList.add(lines.get(0));
tempList.add(below);
xStructure.put(ip.getX(), tempList);
}
}
//System.out.println("HANDLE LEFT ENDPOINT finished");
}
public void handleRightEndpoint(List<Line2D> lines) {
//System.out.println("HANDLE RIGHT ENDPOINT started");
Line2D above = getAboveLine(lines.get(0));
Line2D below = getBelowLine(lines.get(0));
if (above != null && below != null)
if (above.intersectsLine(below)){
Point2D ip = findIntersectionPoint(lines.get(0), below);
if (ip.getX() > slPosition)
intersectionPoints.add(findIntersectionPoint(lines.get(0), below));
}
slStatus.remove(lines.get(0));
//System.out.println("Line [X1=" + lines.get(0).getX1() + ", Y1=" + lines.get(0).getY1() + ", X2=" + lines.get(0).getX2() + ", Y2=" + lines.get(0).getY2() + "] deleted from Y-Structure.");
}
public Line2D getAboveLine(Line2D line) {
if (slStatus.indexOf(line) > 0) {
Line2D a = slStatus.get(slStatus.indexOf(line)-1);
//System.out.println("getAboveLine returns line [X1=" + a.getX1() + ", Y1=" + a.getY1() + ", X2=" + a.getX2() + ", Y2=" + a.getY2() + "]");
return a;
}
//System.out.println("getAboveLine returns no line");
return null;
}
public Line2D getBelowLine(Line2D line) {
if (slStatus.indexOf(line) < slStatus.size()-1) {
Line2D b = slStatus.get(slStatus.indexOf(line)+1);
//System.out.println("getBelowLine returns line [X1=" + b.getX1() + ", Y1=" + b.getY1() + ", X2=" + b.getX2() + ", Y2=" + b.getY2() + "]");
//System.out.println("getAboveLine returns no line");
return b;
}
return null;
}
public EndpointType checkEndpointType(List<Line2D> lines) {
if (lines.size() == 2)
return EndpointType.INTERSECTION;
if (slStatus.contains(lines.get(0)))
return EndpointType.RIGHT;
if (!slStatus.contains(lines.get(0)))
return EndpointType.LEFT;
return null;
}
public List<Line2D> sortEndpointsByXCoordinate(List<Line2D> inputList) {
List<Line2D> returnList = new ArrayList(inputList);
Collections.sort(returnList, new XComparator());
return returnList;
}
public TreeMap<Double, List<Line2D>> createMapOfSortedEndpointsAndCorespondingLineSegment(List<Line2D> inputList) {
TreeMap returnTreeMap = new TreeMap<Double, Line2D>();
for (Line2D l : inputList) {
List<Line2D> tempList = new ArrayList<Line2D>();
tempList.add(l);
returnTreeMap.put(l.getX1(), tempList);
returnTreeMap.put(l.getX2(), tempList);
}
return returnTreeMap;
}
public List<Double> createListOfSortedEndpoints(List<Line2D> inputList) {
List<Double> returnList = new ArrayList<Double>();
for (Line2D l : inputList) {
returnList.add(l.getBounds().getX());
returnList.add(l.getBounds().getY());
}
Collections.sort(returnList);
//System.out.println("DEBUG INFO: createListOfSortedEndpoints returns " + returnList.size() + " endpoints");
return returnList;
}
public List<Line2D> createListOfRandomLines(int size) {
Set<Line2D> hashset = new HashSet<Line2D>();
Random random = new Random();
while (hashset.size() != size) {
Line2D line = new Line2D.Double();
line.setLine(random.nextInt(width-1)+1, random.nextInt(height-1)+1, random.nextInt(width-1)+1, random.nextInt(height-1)+1);
hashset.add(line);
}
List<Line2D> returnList = new ArrayList(hashset);
return returnList;
}
public Point2D findIntersectionPoint(Line2D l1, Line2D l2) {
Double p0_x = l1.getX1();
Double p0_y = l1.getY1();
Double p1_x = l1.getX2();
Double p1_y = l1.getY2();
Double p2_x = l2.getX1();
Double p2_y = l2.getY1();
Double p3_x = l2.getX2();
Double p3_y = l2.getY2();
Double s1_x = p1_x - p0_x;
Double s1_y = p1_y - p0_y;
Double s2_x = p3_x - p2_x;
Double s2_y = p3_y - p2_y;
Double s, t;
s = (-s1_y * (p0_x - p2_x) + s1_x * (p0_y - p2_y)) / (-s2_x * s1_y + s1_x * s2_y);
t = ( s2_x * (p0_y - p2_y) - s2_y * (p0_x - p2_x)) / (-s2_x * s1_y + s1_x * s2_y);
Double i_x, i_y;
i_x = p0_x + (t * s1_x);
i_y = p0_y + (t * s1_y);
Point2D p = new Point2D.Double(i_x, i_y);
return p;
}
}
class XComparator implements Comparator<Line2D>{
public int compare(Line2D l1, Line2D l2){
return new Double(l1.getBounds().getX()).compareTo(l2.getBounds().getX());
}
}
class YComparator implements Comparator<Line2D>{
public int compare(Line2D l1, Line2D l2){
return new Double(l1.getBounds().getY()).compareTo(l2.getBounds().getY());
}
}
enum EndpointType {
LEFT, RIGHT, INTERSECTION
};
I would recommend considering the following Java implementation: https://github.com/stanislav-antonov/bentley-ottmann
It's clean and minimalistic enough, but still handles all the major edge cases.
Related
I am trying to create a simulation of Traveling Salesman Problem and for this I am using GraphStream library. I have a class CreateGraph which is responsible for creating and maintaining graph. As a part of simulation I have to swap two cities (nodes in graph term) and for this what I am doing is
Get edges associated with node1 and store them in array named edge_1
Get edges associated with node2 and store them in array named edge_2
Remove duplicate edges from both the arrays and store them in array named common
Now remove both the nodes (this will also remove edges associated with them)
Create two nodes again with the same id's as previous ones
now iterate through edge_1 and add it with node2 and do same for node1 and edge_2
Now add common edges between them
Mostly everything is working fine but sometimes I am not getting all the edges associated with the node. See images below (give attention on blue nodes)
you can see the nodes and edges associated with them on bottom-left side in IDE.
Here is the CreateGraph class
package graph;
/**
* Created by deepanshu on 6/1/16.
*/
import org.graphstream.ui.view.Viewer;
import sa.City;
import sa.Tour;
import sa.TourManager;
import org.graphstream.graph.*;
import org.graphstream.graph.implementations.SingleGraph;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Scanner;
import java.util.stream.Collectors;
public class CreateGraph {
protected String stylesheet =
"node { " +
"fill-color: green; text-color: blue; text-alignment: under;" +
"}" +
"edge { " +
"fill-color: red;" +
"}" +
"graph { "+
"fill-color: black;" +
" }";
private Graph graph;
public CreateGraph() {
graph = new SingleGraph("Simulated Annealing");
Viewer viewer = graph.display();
viewer.disableAutoLayout();
graph.addAttribute("ui.stylesheet", stylesheet);
graph.addAttribute("ui.quality");
graph.addAttribute("ui.antialias");
}
public void init() {
int totalNumberOfCities = TourManager.numberOfCities();
for (int i = 0; i < totalNumberOfCities; ++i) {
City city = TourManager.getCity(i);
int x = city.getX(), y = city.getY();
graph.addNode("" + x + ", " + y);
Node node = graph.getNode("" + x + ", " + y);
node.addAttribute("ui.label", node.getId());
node.setAttribute("x", x);
node.setAttribute("y", y);
// sleep();
}
}
public void set(Tour tour) {
ArrayList tour_real = tour.getTour();
int length = tour_real.size();
for (int i = 0; i < length - 1; ++i) {
City city_1 = (City)tour_real.get(i);
City city_2 = (City)tour_real.get(i + 1);
Node node_1 = graph.getNode("" + city_1.getX() + ", " + city_1.getY());
Node node_2 = graph.getNode("" + city_2.getX() + ", " + city_2.getY());
node_1.setAttribute("x", city_1.getX());
node_2.setAttribute("x", city_2.getX());
node_1.setAttribute("y", city_1.getY());
node_2.setAttribute("y", city_2.getY());
graph.addEdge(i + "", node_1, node_2, false);
// sleep();
}
}
private void addEdge(Iterator iterator, ArrayList<Edge> edges) {
while (iterator.hasNext()) {
edges.add((Edge)iterator.next());
}
}
private void addEdge(ArrayList<Edge> edges, Node node_1, Node node_2, ArrayList<Edge> changeEdge) {
for (Edge edge : edges) {
Node node0 = edge.getNode0();
Node node1 = edge.getNode1();
if (node_2.getId().equals(node1.getId())) {
graph.addEdge(edge.getId(), node_1, node0, false);
changeEdge.add(graph.getEdge(edge.getId()));
} else {
graph.addEdge(edge.getId(), node_1, node1, false);
changeEdge.add(graph.getEdge(edge.getId()));
}
}
}
private Node addNode(int x, int y) {
graph.addNode("" + x + ", " + y);
Node node_1 = graph.getNode("" + x + ", " + y);
node_1.setAttribute("x", x);
node_1.setAttribute("y", y);
node_1.addAttribute("ui.label", node_1.getId());
node_1.addAttribute("ui.style", "fill-color: blue; text-color: blue; text-alignment: under;");
return node_1;
}
private void removeCommon(ArrayList<Edge> edges_1, ArrayList<Edge> edges_2, ArrayList<Edge> common) {
for (Edge edge_1 : edges_1) {
common.addAll(edges_2.stream().filter(edge_2 -> edge_1.getId().equals(edge_2.getId())).map(edge_2 -> edge_1).collect(Collectors.toList()));
}
edges_1.removeAll(common);
edges_2.removeAll(common);
for (Edge edge : edges_1)
edge.addAttribute("ui.style", "fill-color: Green;");
for (Edge edge : edges_2)
edge.addAttribute("ui.style", "fill-color: Green;");
for (Edge edge : common)
edge.addAttribute("ui.style", "fill-color: Green;");
}
public void updateColor(ArrayList<Edge> changeEdge, Node node_1, Node node_2) {
for (Edge edge : changeEdge)
edge.addAttribute("ui.style", "fill-color: Red;");
node_1.addAttribute("ui.style", "fill-color: green; text-color: blue; text-alignment: under;");
node_2.addAttribute("ui.style", "fill-color: green; text-color: blue; text-alignment: under;");
}
public void update(City city_1, City city_2) {
ArrayList<Edge> changeEdge = new ArrayList<>();
int x_1 = city_1.getX(), y_1 = city_1.getY();
int x_2 = city_2.getX(), y_2 = city_2.getY();
Node node_1 = graph.getNode("" + x_1 + ", " + y_1);
Node node_2 = graph.getNode("" + x_2 + ", " + y_2);
ArrayList<Edge> edge_1 = new ArrayList<>();
ArrayList<Edge> edge_2 = new ArrayList<>();
ArrayList<Edge> common = new ArrayList<>();
addEdge(node_1.getEdgeIterator(), edge_1);
addEdge(node_2.getEdgeIterator(), edge_2);
removeCommon(edge_1, edge_2, common);
graph.removeNode(node_1);
graph.removeNode(node_2);
node_1 = addNode(x_2, y_2);
node_2 = addNode(x_1, y_1);
System.out.println("Node_1: " + node_1.toString());
System.out.println("Node_2: " + node_2.toString());
System.out.println("edge_1: " + edge_1.toString());
System.out.println("edge_2: " + edge_2.toString());
System.out.println("common: " + common.toString());
addEdge(edge_1, node_1, node_2, changeEdge);
addEdge(edge_2, node_2, node_1, changeEdge);
for (Edge edge : common) {
Node node1 = edge.getNode0();
Node node2 = edge.getNode1();
graph.addEdge(edge.getId(), node1, node2, false);
changeEdge.add(graph.getEdge(edge.getId()));
}
sleep();
updateColor(changeEdge, node_1, node_2);
sleep();
}
protected void sleep() {
try {
Thread.sleep(500);
Scanner scanner = new Scanner(System.in);
// scanner.nextLine();
} catch (Exception e) {
e.printStackTrace();
}
}
}
update method is where the swap of two nodes will occur.
Okay I found the bug myself. The bug was here
for (Edge edge : common) {
Node node1 = edge.getNode0();
Node node2 = edge.getNode1();
graph.addEdge(edge.getId(), node1, node2, false); <--- Replace it with
graph.addEdge(edge.getId(), node_1, node_2, false);
changeEdge.add(graph.getEdge(edge.getId()));
}
Actually I was assigning the local variable instead of real instance of nodes.
I am leaving this question here for future reference to anyone who wants to swap two nodes in GraphStream library.
Thank you for your time.
I have a problem to increase frequency that the word occurs in each file,
I tested into 3 equal files and obtained different results in each.
Example: Each file the word "program" occurs 13 times
but the output I have is:
*the word in the search field as this "programa" and not program because of stemming function
[program]
----------------
Doc: site1.html Freq: 21
Doc: site2.html Freq: 11
Doc: site3.html Freq: 1
none of the outputs are correct.
The output had to be:
[program]
----------------
Doc: site1.html Freq: 13
Doc: site2.html Freq: 13
Doc: site3.html Freq: 13
Document class:
public class Documento {
private String docid;
private int frequencia;
public Documento(String docid, int frequencia) {
this.docid = docid;
this.frequencia = frequencia;
}
public String getDocid() {
return docid;
}
public int getFrequencia() {
return frequencia;
}
public void setFrequencia(int frequencia) {
this.frequencia = frequencia;
}
#Override
public boolean equals(Object o) {
if ((o instanceof Documento) && docid == ((Documento) o).docid && frequencia == ((Documento) o).frequencia) {
return true;
}
return false;
}
Function to insert and find document:
public class Dicionario {
public Map<String, List<Documento>> indice = new HashMap<>();
public void InsereDicionario(String palavra, String docid) {
if (!indice.containsKey(palavra)) {
indice.put(palavra, new ArrayList<Documento>());
indice.get(palavra).add(new Documento(docid, 1));
} else {
boolean inserido = false;
List<Documento> lista = indice.get(palavra);
for (int i = 0; i < lista.size(); i++) {
Documento d = lista.get(i);
if (d.getDocid().equals(docid)) {
// indice.get(palavra).add(new Documento(docid, 1));
inserido = true;
} else {
d.setFrequencia(d.getFrequencia() + 1);
}
System.out.println("");
}
if (!inserido) {
indice.get(palavra).add(new Documento(docid, 1));
}
}
}
public String Busca(String palavra) {
String saida = "";
System.out.println("Buscando [" + palavra + "]");
List<Documento> list = new ArrayList();
for (String p : indice.keySet()) {
if (p.equals(palavra)) {
list.addAll(indice.get(p));
for (Documento d : indice.get(p)) {
System.out.println("Doc: " + d.getDocid() + " Freq: " + d.getFrequencia());
saida += "Doc: " + d.getDocid() + " Freq: " + d.getFrequencia() + "".trim() + "\n";
}
}
}
return saida;
}
Function to call Buscar(Search function) in all words.
for (String palavra : query.split(" ")) {
resultado += ("\n[" + palavra + "]\n----------------\n");
resultado += dic.Busca(palavra.trim());
}
Look at this:
if (d.getDocid().equals(docid)) {
// indice.get(palavra).add(new Documento(docid, 1));
inserido = true;
} else {
d.setFrequencia(d.getFrequencia() + 1);
}
If dociid is found in the list -> then do nothning.
Otherwise (a current doc retrieved from the list is not equal to docid) -> then increment the counter.
Swap these operations, or use a negation in the condition.
I made this code for extracting Polynomial coefficients and also evaluating equation in a point,and it is work.
but i want to modify that so the user can enter any shape of polynomial equation.
in my code you have to enter equation like this:
2*x^2+3*x^1+4
but i want :
2*x^5+1*x+6
also if there any term with same power , their coeffs must be added together.
Here is my code in java:
package Priest;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
public class Equation {
private String Eq;
private final String[] C;
private int Deg;
private final String EqHolder;
public Equation(String Equation) {
this.Eq = Equation;
EqHolder = Equation;
Eq = Eq.replaceAll("[^0-9\\-\\.]+", " ");
Eq = Eq.replaceAll("-", " -");
this.C = Eq.split(" ");
}
public String SourceEquation() {
return EqHolder.toUpperCase().replaceAll("\\*", "").replaceAll("[a-zA-Z]", "\\*(X)").replaceAll("\\+", "\\ + ").replaceAll("\\-", "\\ - ");
}
public List<BigDecimal> CaptureCoeff() {
getDegree();
List<BigDecimal> Temp = new ArrayList<>();
for (String S : C) {
Temp.add(new BigDecimal(S));
}
int Location = Temp.indexOf(BigDecimal.valueOf(Deg));
List<BigDecimal> Coeffs = new ArrayList<>();
for (int Counter = Location - 1; Counter < Temp.size(); Counter += 2) {
Coeffs.add(Temp.get(Counter));
}
return Coeffs;
}
public int getDegree() {
int Degree = 0;
for (int Counter = 0; Counter < C.length; Counter += 2) {
if ((new Double(C[Counter])) != 0) {
Degree = new Integer(C[Counter + 1]);
this.Deg = Degree;
break;
}
}
return Degree;
}
public BigDecimal Evaluate(List<BigDecimal> Coefficients, double EvalPoint) {
BigDecimal Output = BigDecimal.ZERO;
for (int Index = 0; Index < Coefficients.size(); Index++) {
Output = Output.add(Coefficients.get(Index).multiply(BigDecimal.valueOf(EvalPoint).pow(Deg--)));
}
return Output;
}
}
and main class:
package Priest;
import java.math.RoundingMode;
public class MainClass {
public static void main(String[] args) {
long Start = System.nanoTime();
String Str = "3.1415x^5-12.6x^4+6x^3+12*x^2-6*x^1-0";
Equation E = new Equation(Str);
System.out.println("Equation is: " + E.SourceEquation());
System.out.println("Coefficients :" + E.CaptureCoeff());
System.out.println("Polynomial Degree: " + E.getDegree());
double Target = 47.784;
System.out.println("Equation # (X:" + Target + ")= " + E.Evaluate(E.CaptureCoeff(), Target).setScale(15, RoundingMode.HALF_UP));
System.out.println("Elapsed Time: " + String.format("%.20G", (System.nanoTime() - Start) / 1.0e6) + " ms.");
}
}
the output:
run:
Equation is: 3.1415*(X)^5 - 12.6*(X)^4 + 6*(X)^3 + 12*(X)^2 - 6*(X)^1 - 0
Coefficients :[3.1415, -12.6, 6, 12, -6, 0]
Polynomial Degree: 5
Equation # (X:47.784)= 717609084.382589022327914
Elapsed Time: 32.306242000000000000 ms.
BUILD SUCCESSFUL (total time: 0 seconds)
Let's go with the following equation String Str2 = "3.1415x^5+6x^2+12*x-5";
Here is the code that I have added upon your code in order to preprocess this equation and made it compatible to your actual logic so that It will treat it without any major change to your code.
To be totally accurate I had to change the following in your equation class:
public List<BigDecimal> CaptureCoeff() {
getDegree();
List<BigDecimal> Temp = new ArrayList<BigDecimal>();
for (String S : C) {
if (! "".equals(S.trim())) {
Temp.add(new BigDecimal(S));
}
}
So I have added the control to check that none of these S strings is trim - empty.
Here is my preprocessing code.
I have added a method called powerSplitt that allows to splitt the equation on the basis of the '^' char.
Then I created another method called generateNullCoeffPolynomeWithDegree that generate a monome in the form 0*X^k. And a similar one that generate all the similar intermediate monomes between the greater power and the lesser power
Example:
String str3 = generateAllNullCoeffPolynomesWithDegreeExclusiveBetween(5, 2);
System.out.println("all poly = " + str3);
will generate: all poly = 0*x^4+0*x^3
Then I created a buildPreProcessedPolynome that takes the initial equation and pre process it to produce one with the null monomes inside of it. And then I just gave it to your equation program and it could process it fine!!!
Here is the code and a call example all done in the MainClass
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
public class MainClass {
private static List<String> workList = new ArrayList<String>();
public static void powerSplitt(String equationText) {
char[] charsList = equationText.toCharArray();
boolean foundTargetChar = false;
int index = 0;
for (int i = 0; i < charsList.length; i++) {
index = i;
if (charsList[i] == '^') {
foundTargetChar = true;
break;
}
}
if (foundTargetChar) {
workList.add(equationText.substring(0, index));
if (index +1 < equationText.length()) {
powerSplitt(equationText.substring(index+1));
} else {
workList.add(equationText);
return;
}
} else {
workList.add(equationText);
}
}
public static String generateNullCoeffPolynomeWithDegree(int degree) {
return "0*x^" + degree;
}
public static String generateAllNullCoeffPolynomesWithDegreeExclusiveBetween(int startDegree, int endDegree) {
if (startDegree-endDegree <= 1) {
return "";
}
int index = 0;
StringBuilder builder = new StringBuilder();
for (int i = startDegree -1; i > endDegree; i--) {
if (index > 0) {
builder.append("+");
}
builder.append(generateNullCoeffPolynomeWithDegree(i));
index++;
}
return builder.toString();
}
public static String buildPreProcessedPolynome(String initialEquationText) {
workList.clear();
powerSplitt(initialEquationText);
StringBuilder resultBuilder = new StringBuilder();
assert workList.size() >= 3;
resultBuilder.append(workList.get(0));
for (int i = 1; i <= workList.size()-2; i++) {
int actualPower = Integer.parseInt( workList.get(i).substring(0,1));
int nextFoundPower = Integer.parseInt( workList.get(i+1).substring(0,1));
System.out.print("actual power = " + actualPower + " and next power = " + nextFoundPower);
System.out.println();
String additionalPolyParts = generateAllNullCoeffPolynomesWithDegreeExclusiveBetween(actualPower, nextFoundPower);
resultBuilder.append("^" + actualPower);
resultBuilder.append("+");
resultBuilder.append(additionalPolyParts);
resultBuilder.append(workList.get(i).substring(1));
}
resultBuilder.append("^" + workList.get(workList.size()-1));
return resultBuilder.toString();
}
public static void main(String[] args) {
workList.clear();
String Str2 = "3.1415x^5+6x^2+12*x-5";
powerSplitt(Str2);
for (String part: workList) {
System.out.println("PART:" + part);
}
System.out.println("-----------------");
long Start = System.nanoTime();
String str3 = generateAllNullCoeffPolynomesWithDegreeExclusiveBetween(5, 2);
System.out.println("all poly = " + str3);
String preprocessed = buildPreProcessedPolynome(Str2);
System.out.println("preprocessed = " + preprocessed);
System.out.println();
Equation E = new Equation(preprocessed);
System.out.println("Equation is: " + E.SourceEquation());
System.out.println("Coefficients :" + E.CaptureCoeff());
System.out.println("Polynomial Degree: " + E.getDegree());
double Target = 47.784;
System.out.println("Equation # (X:" + Target + ")= " + E.Evaluate(E.CaptureCoeff(), Target).setScale(15, RoundingMode.HALF_UP));
System.out.println("Elapsed Time: " + String.format("%.20G", (System.nanoTime() - Start) / 1.0e6) + " ms.");
}
}
And here is the produced results (I haved added some System.out.println to check the results of my methods calls. I just noticed I have to take into account the last constant as a monome of type K*X^0, but I will leave that to you):
PART:3.1415x
PART:5+6x
PART:2+12*x-5
all poly = 0*x^4+0*x^3
actual power = 5 and next power = 2
preprocessed = 3.1415x^5+0*x^4+0*x^3+6x^2+12*x-5
Equation is: 3.1415*(X)^5 + 0*(X)^4 + 0*(X)^3 + 6*(X)^2 + 12*(X) - 5
Coefficients :[3.1415, 0, 0, 6, 12]
Polynomial Degree: 5
Equation # (X:47.784)= 782631805.485054892561514
Elapsed Time: 18,441978000000000000 ms.
In my program, I have three variables: when one of these variables reaches 100, it must appear the words "variable came first to the finish line."
How do I organize the arrival of the second and third variable, so they come out like this:
variable1-arrived first
variable2-finished second
variable3 finished third
Help!
public Corsa(String name)
{
this.name = name;
System.out.println("Start: " + name);
System.out.println("---------------");
}
public void run()
{
while(finita == false)
{
try
{
avanza = (int) (Math.random()*20+1);
percorso = percorso + avanza;
System.out.println(name + " has path " + percorso + " meters");
if(percorso < 100)
{
System.out.println("---------------");
sleep = (int) (Math.random()*20+1);
Thread.sleep(sleep);
}
else
{
System.out.println("---------------");
System.out.println("---------------");
System.out.println(name + " came in first");
finita = true;
}
}
catch(InterruptedException e){}
Thread.yield();
}
}
}
I haven't tested this (so it might not even compile), but something like the following should work:
public class myRace
{
private int distance = 100;
private float offset = 20;
public int runners[3];
public void run()
{
// Set all runners to 0
for ( int i = 0; i < runners.length; i++ )
runners[i] = 0;
// Run the race and stop when at least 1 runner has reached the distance...
boolean finished = false;
while ( !finished )
{
for ( int i = 0; i < runners.length; i++ )
{
runners[i] += (int)((Math.random() * offset) + 1);
if ( runners[i] >= distance ) finished = true;
}
}
// Race finished now sort the runners
TreeMap<String, int> ranking = new TreeMap<String, int>();
for ( int i = 0; i < runners.length; i++ )
{
// A TreeMap is sorted on its key, not the value!
// The runners number is tagged on, just in case two runners have finished on the same distance.
String sortedKey = Integer.toString(runners[i]) + "." + Integer.toString(i);
ranking.put(sortedKey, i);
}
// Print the results
int pos = 1;
for ( Map.Entry entry : ranking.entrySet() )
{
String key = entry.getKey();
String distance = key.subString(0, key.indexOf(".")); // chop off the "." + runners number.
System.out.println("#" + pos + // position
"." + entry.getValue() + // who
", Distance = " + distance); // distance covered
pos++; // this does take in account whether multiple runners finished on the same distance.
}
}
}
I've got some problems with the topological sorting. It can find lops, but it counts some of the tasks (or "nodes" if you want to call it) several times. I think the problem is something with how I read or the Edge class, but I just can't see where it goes wrong. Any help would be really appreciated :)
enter code here
import java.util.*;
import java.io.*;
import java.lang.*;
class Task {
int id, time, staff;
int depA, depB;
String name;
int eStart, lStart;
Edge outEdge;
int cntPredecessors;
boolean visited;
Task(int id, String name, int time, int staff) {
this.id = id;
this.name = name;
this.time = time;
this.staff = staff;
visited = false;
}
public String getName() {
return name;
}
public String toString() {
return name;
}
}
class Edge {
Task id, name, time, staff;
Edge neste;
Task fra, til;
Edge(Task id) {
this.id = id;
}
}
class Input {
public static void main(String[] args) {
if (args.length == 0) {
System.out.println("enter a filename!");
System.exit(1);
} else if (args.length == 1) {
String fil = args[0]+".txt";
LesFraFil(fil);
// skrivUt();
topSort();
} else {
System.out.println("too many parameters, try again...");
}
}
static int antTask;
static Task[] ids;
static int tTid;
static void LesFraFil(String fil) {
int i = 0;
int j;
try {
String lest;
Scanner in = new Scanner(new FileReader(fil));
Edge til;
int counter = 0;
antTask = in.nextInt();
ids = new Task[antTask];
System.out.println(antTask);
while (in.hasNextLine()) {
lest = in.nextLine();
// hvis tom linje, så hopper den over
if(lest.trim().length() == 0) continue;
String split[] = lest.split("\\s+");
int id = Integer.parseInt(split[0]);
String act = split[1];
int tid = Integer.parseInt(split[2]);
int staff = Integer.parseInt(split[3]);
int depA = Integer.parseInt(split[4]);
tTid += tid;
ids[i] = new Task(id, act, tid, staff);
j = 4;
/*
* Lesingen av inputen skal avbrytes når den leser 0.
* j er den som holder på hvor langt vi er i split arrayet
* når den møter på 0
*/
while(split[j].compareTo("0") != 0) {
int tmp = Integer.parseInt(split[j])-1;
// System.out.println(tmp+1 + " Aktivitetens navn : " + act); //+ " tiden aktiviteten tar tid: " + tid + " avhengihet: " + split[j]);
j++;
if (ids[tmp] == null) {
ids[tmp] = new Task(id, act, tid, staff);
ids[tmp].visited = true;
}
ids[i].cntPredecessors++;
if(ids[tmp].outEdge == null) {
ids[tmp].outEdge = new Edge(ids[i]);
} else {
til = ids[tmp].outEdge;
while(til.neste != null) {
til = til.neste;
}
til.neste = new Edge(ids[i]);
}
}
counter++;
i++;
}
if (antTask == counter) {
System.out.println("Lesinga gikk som planlagt av fil: " + fil);
System.out.println("Total arbeidstid: " + tTid);// + antTask + " == " + counter );
} else {
System.out.println("Noe gikk galt avslutter!");
System.out.println(antTask + " || " + counter);
System.exit(2);
}
in.close();
} catch (Exception e) {
System.err.println("ERROR!" + e.getMessage());
}
}
static void skrivUt() {
for (Task sort : ids) {
System.out.print(sort.id + " " + sort.name);
Edge til = sort.outEdge;
while (til != null) {
System.out.print(" " + til.id.id);
til = til.neste;
}
System.out.println();
}
}
static void topSort() {
LinkedList<Task> list = new LinkedList<Task>();
ArrayList<Task> array = new ArrayList<Task>();
Task temp;
int count = 0;
int totalTime = 0;
// Legger taskene i lista
for (Task t : ids) {
if(t.cntPredecessors == 0) {
list.add(t);
totalTime += t.time;
// System.out.println(t);
t.visited = true;
}
}
for (Task t : ids) {
if(t.cntPredecessors == 1) {
list.add(t);
totalTime += t.time;
// System.out.println(t);
t.visited = true;
}
}
// går i evig løkke til lista er tom.
while (!list.isEmpty()) {
temp = list.pop(); // fjerner elementet fra lista
array.add(temp); // legger inn i arraylisten
count++;
// System.out.println(temp);
for(Edge til = temp.outEdge; til!=null;til=til.neste) {
til.id.cntPredecessors--;
if(til.id.cntPredecessors==0) {
list.add(til.id);
}
}
}
if(count < antTask) {
System.out.println("A loop has been found. Terminating...");
System.exit(0);
}
System.out.println("Topological sort: " + Arrays.toString(array.toArray()));// den sorterte "arraylisten"
System.out.println("Total time spend: " + totalTime);
}
} // End class Input
Here is an example of an input file
8
1 Build-walls 4 2 5 0
2 Build-roofs 6 4 1 0
3 Put-on-wallpapers 1 2 1 2 0
4 Put-on-tiles 1 3 2 0
5 Build-foundation 4 2 0
6 Make-floor 2 2 5 0
7 Put-carpet-floor 4 2 6 2 0
8 Move-in 4 4 3 7 0
The problem is with this loop (inside topSort()):
for (Task t : ids) {
if(t.cntPredecessors == 1) {
list.add(t);
totalTime += t.time;
// System.out.println(t);
t.visited = true;
}
}
You just need to remove it.
Reason: this loop adds to list nodes that have 1 incoming edge. Later (in the while loop), it is possible that for these nodes the cntPredecessors field will be decreased to 0 which will make them being pushed back onto list, thus counted twice.
In the future, please try to narrow down your code to something that contains less "noise", that is: the smallset (or nearly smallest) code that illustrates the problem. This will ease the understanding on potential answerers (not to mention that it may help you see the problem yourself).