Java 卡在递归Fork/Join上
我有一个返回一组点的方法,我确信这个方法的for循环部分可以分解成一个递归任务,为每个线程返回一组点 我试了很多次,但都失败了。有java天才吗 我现有的方法:Java 卡在递归Fork/Join上,java,join,recursion,fork,fork-join,Java,Join,Recursion,Fork,Fork Join,我有一个返回一组点的方法,我确信这个方法的for循环部分可以分解成一个递归任务,为每个线程返回一组点 我试了很多次,但都失败了。有java天才吗 我现有的方法: private Set<Point3D> getCordinatesAroundCenterPoint(Point3D point, int width) { Set<Point3D> points = new LinkedHashSet<>(); double
private Set<Point3D> getCordinatesAroundCenterPoint(Point3D point, int width) {
Set<Point3D> points = new LinkedHashSet<>();
double maxValue = width;
double minValue = maxValue * -1;
double minX = point.getX() + minValue;
double maxX = point.getX() + maxValue;
double minY = point.getY() + minValue;
double maxY = point.getY() + maxValue;
double minZ = point.getY() + minValue;
double maxZ = point.getZ() + maxValue;
double x = point.getX();
double y = point.getY();
double z = point.getZ();
double numberOfPoints = Math.pow((double) (maxValue * 2) + 1, Double.parseDouble("3"));
for (int i = 1; i <= numberOfPoints; i++) {
if (x > maxX) {
x = minX;
y++;
}
if (y > maxY) {
y = minY;
z++;
}
if (z > maxZ) {
z = minZ;
}
Point3D ppoint = new Point3D();
ppoint.setX(x);
ppoint.setY(y);
ppoint.setZ(z);
points.add(ppoint);
x++;
}
return points;
}
私有集GetCordinatesRoundCenterPoint(点3D点,整数宽度){
设置点=新LinkedHashSet();
双最大值=宽度;
双最小值=最大值*-1;
double minX=point.getX()+minValue;
double maxX=point.getX()+maxValue;
double minY=point.getY()+minValue;
double maxY=point.getY()+maxValue;
double minZ=point.getY()+minValue;
double maxZ=point.getZ()+maxValue;
double x=point.getX();
双y=point.getY();
double z=point.getZ();
double numberOfPoints=Math.pow((double)(maxValue*2)+1,double.parseDouble(“3”);
对于(int i=1;i maxX){
x=minX;
y++;
}
如果(y>maxY){
y=minY;
z++;
}
如果(z>maxZ){
z=minZ;
}
Point3D ppoint=新的Point3D();
p点集x(x);
ppoint.setY(y);
p点setZ(z);
加分(ppoint);
x++;
}
返回点;
}
更新#1:
这是我试图将其拆分为递归任务的尝试,它似乎可以很好地工作,范围为1(应该等于27点)-1,0,+1,=3点,3立方=27。任何更高的区段数都会失败,例如区段2应返回125点-2,-1,0,+1,+2=5分,5立方=125分
Main.java:
public static void main(String[] args) {
System.out.println("Enter system extent: ");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
try {
String string = bufferedReader.readLine();
LinkedHashSet<Point3D> set = getStarSystemCordinatesAroundCenterSystem(Integer.parseInt(string));
System.out.println(set.size() + " systems generated.");
} catch (IOException e) {
e.printStackTrace();
}
}
private static LinkedHashSet<Point3D> getStarSystemCordinatesAroundCenterSystem(int extent) {
ForkJoinPool pool = new ForkJoinPool();
double maxValue = extent;
double minValue = maxValue * -1;
ForkPoints task = new ForkPoints(minValue, maxValue);
LinkedHashSet<Point3D> linkedHashSet = (LinkedHashSet<Point3D>) pool.invoke(task);
return linkedHashSet;
}
publicstaticvoidmain(字符串[]args){
System.out.println(“输入系统范围:”);
BufferedReader BufferedReader=新的BufferedReader(新的InputStreamReader(System.in));
试一试{
String String=bufferedReader.readLine();
LinkedHashSet set=GetStarSystemCordinatesRoundCenterSystem(Integer.parseInt(字符串));
System.out.println(set.size()+“系统生成”);
}捕获(IOE异常){
e、 printStackTrace();
}
}
专用静态链接设置GetStarSystemCordinatesRoundCenterSystem(int区段){
ForkJoinPool池=新的ForkJoinPool();
双最大值=范围;
双最小值=最大值*-1;
ForkPoints任务=新的ForkPoints(最小值、最大值);
LinkedHashSet LinkedHashSet=(LinkedHashSet)池。调用(任务);
返回linkedHashSet;
}
ForkPoints.java:
public class ForkPoints extends RecursiveTask<Set<Point3D>> {
private static final long serialVersionUID = -5450450150370659468L;
private double minValue;
private double maxValue;
static final double SEQUENTIAL_THRESHHOLD = 2;
public ForkPoints(double minValue, double maxValue) {
this.minValue = minValue;
this.maxValue = maxValue;
}
@Override
protected Set<Point3D> compute() {
if (maxValue - minValue <= SEQUENTIAL_THRESHHOLD) {
return computeValue(minValue, maxValue);
} else {
double midValue = minValue + SEQUENTIAL_THRESHHOLD;
ForkPoints left = new ForkPoints(minValue, midValue);
ForkPoints right = new ForkPoints(midValue, maxValue);
left.fork();
Set<Point3D> rightPoints = right.compute();
Set<Point3D> leftPoints = left.join();
leftPoints.addAll(rightPoints);
return leftPoints;
}
}
private Set<Point3D> computeValue(double minv, double maxv) {
//Assume starting point of 0,0,0
double minX = 0 + minv;
double maxX = 0 + maxv;
double minY = 0 + minv;
double maxY = 0 + maxv;
double minZ = 0 + minv;
double maxZ = 0 + maxv;
double x = minv;
double y = minv;
double z = minv;
Set<Point3D> points = new LinkedHashSet<>();
boolean notFinished = true;
while (notFinished) {
if (x > maxX) {
x = minX;
y++;
}
if (y > maxY) {
y = minY;
z++;
}
if (z > maxZ) {
z = minZ;
}
Point3D ppoint = new Point3D();
ppoint.setX(x);
ppoint.setY(y);
ppoint.setZ(z);
points.add(ppoint);
if (x == maxX && y == maxY && z == maxZ) {
notFinished = false;
}
x++;
}
return points;
}
}
public类ForkPoints扩展递归任务{
私有静态最终长serialVersionUID=-5450450370659468L;
私人双重价值;
私有双最大值;
静态最终双顺序_阈值=2;
公共分叉点(双最小值、双最大值){
this.minValue=minValue;
this.maxValue=maxValue;
}
@凌驾
受保护集计算(){
if(最大值-最小值最大值){
x=minX;
y++;
}
如果(y>maxY){
y=minY;
z++;
}
如果(z>maxZ){
z=minZ;
}
Point3D ppoint=新的Point3D();
p点集x(x);
ppoint.setY(y);
p点setZ(z);
加分(ppoint);
如果(x==maxX&&y==maxY&&z==maxZ){
未完成=错误;
}
x++;
}
返回点;
}
}
这里的主要问题是您试图分割三维对象,但仅在一个方向上分割。也就是说,ForkPoints.compute()
实际上不应该生成2个子任务,而是至少生成8个子任务,以防它自己无法执行计算
下面是一个示例,展示了它的外观-代码的最小更改:
public class ForkPoints extends RecursiveTask<Set<Point3D>> {
private static final long serialVersionUID = -5450450150370659468L;
private final Point3D origin;
private final double radius;
static final double SEQUENTIAL_THRESHHOLD = 5;
public ForkPoints(final Point3D origin, final double radius) {
this.origin = origin;
this.radius = radius;
}
@Override
protected Set<Point3D> compute() {
if (radius <= SEQUENTIAL_THRESHHOLD) {
return computeValue();
} else {
final ForkPoints subCubes[] = new ForkPoints[8];
final double newRadius = radius / 2;
Point3D newOrigin = new Point3D();
newOrigin.setX(origin.getX() + newRadius);
newOrigin.setY(origin.getY() + newRadius);
newOrigin.setZ(origin.getZ() + newRadius);
subCubes[0] = new ForkPoints(newOrigin, newRadius);
subCubes[0].fork();
newOrigin = new Point3D();
newOrigin.setX(origin.getX() + newRadius);
newOrigin.setY(origin.getY() + newRadius);
newOrigin.setZ(origin.getZ() - newRadius);
subCubes[1] = new ForkPoints(newOrigin, newRadius);
subCubes[1].fork();
newOrigin = new Point3D();
newOrigin.setX(origin.getX() + newRadius);
newOrigin.setY(origin.getY() - newRadius);
newOrigin.setZ(origin.getZ() + newRadius);
subCubes[2] = new ForkPoints(newOrigin, newRadius);
subCubes[2].fork();
newOrigin = new Point3D();
newOrigin.setX(origin.getX() + newRadius);
newOrigin.setY(origin.getY() - newRadius);
newOrigin.setZ(origin.getZ() - newRadius);
subCubes[3] = new ForkPoints(newOrigin, newRadius);
subCubes[3].fork();
newOrigin = new Point3D();
newOrigin.setX(origin.getX() - newRadius);
newOrigin.setY(origin.getY() + newRadius);
newOrigin.setZ(origin.getZ() + newRadius);
subCubes[4] = new ForkPoints(newOrigin, newRadius);
subCubes[4].fork();
newOrigin = new Point3D();
newOrigin.setX(origin.getX() - newRadius);
newOrigin.setY(origin.getY() + newRadius);
newOrigin.setZ(origin.getZ() - newRadius);
subCubes[5] = new ForkPoints(newOrigin, newRadius);
subCubes[5].fork();
newOrigin = new Point3D();
newOrigin.setX(origin.getX() - newRadius);
newOrigin.setY(origin.getY() - newRadius);
newOrigin.setZ(origin.getZ() + newRadius);
subCubes[6] = new ForkPoints(newOrigin, newRadius);
subCubes[6].fork();
newOrigin = new Point3D();
newOrigin.setX(origin.getX() - newRadius);
newOrigin.setY(origin.getY() - newRadius);
newOrigin.setZ(origin.getZ() - newRadius);
subCubes[7] = new ForkPoints(newOrigin, newRadius);
subCubes[7].fork();
final Set<Point3D> results = new LinkedHashSet<Point3D>();
for(final ForkPoints singleSubCube : subCubes) {
results.addAll(singleSubCube.join());
}
return results;
}
}
private Set<Point3D> computeValue() {
double minX = origin.getX() - radius;
double maxX = origin.getX() + radius;
double minY = origin.getY() - radius;
double maxY = origin.getY() + radius;
double maxZ = origin.getZ() + radius;
double x = minX;
double y = minY;
double z = origin.getZ() - radius;
Set<Point3D> points = new LinkedHashSet<>();
boolean notFinished = true;
while (notFinished) {
if (x > maxX) {
x = minX;
y++;
}
if (y > maxY) {
y = minY;
z++;
}
if (z > maxZ) {
break;
}
Point3D ppoint = new Point3D();
ppoint.setX(x);
ppoint.setY(y);
ppoint.setZ(z);
points.add(ppoint);
x++;
}
return points;
}
}
public类ForkPoints扩展递归任务{
私有静态最终长serialVersionUID=-5450450370659468L;
私人终点3D原点;
私人最终双半径;
静态最终双顺序_阈值=5;
公共分叉点(最终点3D原点,最终双半径){
this.origin=origin;
这个半径=半径;
}
@凌驾
受保护集计算(){
if(半径最大值){
x=minX;
y++;
}
如果(y>maxY){
y=minY;
z++;
}
如果(z>maxZ){
打破
}
Point3D ppoint=新的Point3D();
p点集x(x);
ppoint.setY(y);
p点setZ(z);
加分(ppoint);
x++;
}
返回点;
}
}
但是请注意,这段代码还有很多工作要做。例如,为相邻空间执行计算的两个子任务都会生成位于“相互”窗格上的点;当前代码通过
Set.addAll(…)
调用的Point3D.equals(…)
排除这些重复项。在现实生活中,算法甚至不应该生成它们,因为这些重复的点占据了整个生成点的很大一部分,特别是对于顺序_threshold
的低值,您正试图将任务分成几个部分,但您忘记了数据是3D的:对所有三个坐标应用相同的约束将解决方案限制为沿“主对角线”的立方体链,而不处理所有其他空间。这就是为什么你只得到54分(一倍)而不是一倍
public class ForkPoints extends RecursiveTask<Set<Point3D>> {
private static final long serialVersionUID = -5450450150370659468L;
private double minX;
private double minY;
private double minZ;
private double maxX;
private double maxY;
private double maxZ;
// max number of points allowed for a task
static final double PTS_THRESHOLD = 25;
// cube case
public ForkPoints(double minValue, double maxValue) {
this.minX = minValue;
this.minY = minValue;
this.minZ = minValue;
this.maxX = maxValue;
this.maxY = maxValue;
this.maxZ = maxValue;
}
// rectangular cuboid case
public ForkPoints(double minx, double maxx, double miny, double maxy, double minz, double maxz) {
this.minX = minx;
this.minY = miny;
this.minZ = minz;
this.maxX = maxx;
this.maxY = maxy;
this.maxZ = maxz;
}
@Override
protected Set<Point3D> compute() {
double dx = maxX - minX + 1; // no of points
double dy = maxY - minY + 1; // in every
double dz = maxZ - minZ + 1; // direction
if (dx*dy*dz <= PTS_THRESHOLD) { // no of points to make
return computeValue(); // cuboid small enough
} else {
bool splitx = (dx >= dy) && (dx >= dz); // choose axis
bool splity = !splitx && (dy >= dz); // for split
ForkPoints left;
ForkPoints right;
if (splitx) {
double midx = Math.floor( (minx + maxx)/2);
left = new ForkPoints(minx, midx, miny, maxy, minz, maxz);
right = new ForkPoints(midx+1, maxx, miny, maxy, minz, maxz);
} else if (splity) {
double midy = Math.floor( (miny + maxy)/2);
left = new ForkPoints(minx, maxx, miny, midy, minz, maxz);
right = new ForkPoints(minx, maxx, midy+1, maxy, minz, maxz);
} else {
double midz = Math.floor( (minz + maxz)/2);
left = new ForkPoints(minx, maxx, miny, maxy, minz, midz);
right = new ForkPoints(minx, maxx, miny, maxy, midz+1, maxz);
}
left.fork();
Set<Point3D> rightPoints = right.compute();
Set<Point3D> leftPoints = left.join();
leftPoints.addAll(rightPoints);
return leftPoints;
}
}
private Set<Point3D> computeValue() {
Set<Point3D> points = new LinkedHashSet<>();
for (double z = minZ; z < maxZ + 0.01; z += 1)
for (double y = minY; y < maxY + 0.01; y += 1)
for (double x = minX; x < maxX + 0.01; x += 1)
{
Point3D ppoint = new Point3D();
ppoint.setX(x);
ppoint.setY(y);
ppoint.setZ(z);
points.add(ppoint);
}
return points;
}
}