伪无限循环(从矩阵中最佳地删除'缺失数据')

时间:2014-11-16 05:36:39

标签: java combinatorics

当我使用随机矩阵(类确定)时,我的程序在1700毫秒内成功运行。但是,当我通过缓冲读取器(类Construct)读取文件来创建矩阵时,我的程序会遇到逻辑错误并进入无限循环。

同样,它适用于随机矩阵,但不适用于真实的'相同大小的矩阵。我检查了我的工作,在阅读文件时找不到错误。有谁知道可能导致这个逻辑错误的原因是什么?如果有帮助,我会在评论中附上我的代码!


更新:好的问题来自我自己的愚蠢疏忽(见下面的答案)。随着我的“拥有”数据随机数据不会发生这种情况。方法和丢失数据的概率。因此,我的代码已更新以反映此逻辑错误,我很乐意详细解释如果有人询问此代码如何工作:

import java.util.Random;
import java.util.List;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.*;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.BufferedReader;


class ValMax {
    public static int valMax;
}

class Construct {
    private static int colEnd;
    private static int colStart;
    private static int[] colSkip;

    public static List<List<Integer>> rFile(String[] args){     
        if (args.length != 4) {
            System.out.println("Format: FileName colStart colEnd colSkipped");
            System.exit(0);
        }

        BufferedReader reader = null;

        try {
            List<List<Integer>> matrix = new ArrayList<List<Integer>>();

            Construct.colEnd = Integer.parseInt(args[2]);
            Construct.colStart = Integer.parseInt(args[1]);     
            String[] colSkipped = args[3].split(",");
            Construct.colSkip = new int[colSkipped.length];
            for (int x = 0; x < colSkipped.length; x++) {
                Construct.colSkip[x] = Integer.parseInt(colSkipped[x]);
            }

            String line;
            reader = new BufferedReader(new FileReader(new File(args[0])));

            while ((line = reader.readLine()) != null) {
                String[] tokens = line.split(",");
                List<Integer> rows = new ArrayList<Integer>(colEnd - colStart + 1 - colSkip.length);

                for (int x = 1; x <= tokens.length; x++) {
                    if (x >= colStart && x <= colEnd && contains(x, colSkip) == false) {        
                        try {
                            Double.parseDouble(tokens[x - 1]);
                        } catch (NumberFormatException e3) {
                            break;
                        }

                        if (tokens[x - 1].equals("-999")) { //
                            rows.add(2);
                        } else {
                            rows.add(1);
                        }
                    }
                }

                if (rows.size() == colEnd - colStart + 1 - colSkip.length) {
                    matrix.add(rows);
                }
            }

            System.out.println(matrix.size() + "\t" + matrix.get(0).size());
            return matrix;

        } catch (IOException e1) {
            System.out.println("IOEXCEPTION!!");
            System.exit(0);
        } catch (NumberFormatException e2) {
            System.out.println("NumberFormatException!!");
            System.exit(0);
        } finally {
            try {
                reader.close();
            } catch (IOException e5) {
                e5.printStackTrace();
            }
        }

        return null;
    }

    private static boolean contains(int a, int[] colSkip) {
        boolean bluejay = false;
        for (int skip : colSkip) {
            if (a == skip) {
                bluejay = true;
            }
        }

        return bluejay;
    }
}

class Determine {
    private static Integer gen(int a, int b, Random r) {
        Integer rand = r.nextInt(a) + b;

        return rand;
    }

    public static List<List<Integer>> rando() {
        Random r = new Random();
        int k = gen(1, 24, r), l = gen(1, 33, r); //userinput

        List<List<Integer>> matrix = new ArrayList<List<Integer>>(k);           
        for (int x = 1; x <= k; x++) {
            List<Integer> row = new ArrayList<Integer>(l);
            for (int y = 1; y <= l; y++) {
                double bias = Math.random();
                if (bias > 0.7) {
                    row.add(2);
                } else {
                    row.add(1);
                }
            }

            matrix.add(row);
        }

        return matrix;
    }
}

class Search {
    public static void finalize(List<List<Integer>> matTan, boolean gumDrop, int minimum) {
        final int A = matTan.size();
        final int B = matTan.get(0).size();
        boolean judge = true;

        if (minimum > A && gumDrop == false || minimum > B && gumDrop == true) {
            System.out.print("\nMinimum too high\n\n");
            System.exit(0);
        }

        ValMax.valMax = 1;  //userinput
        int[] rows  = new int[2 + A + B];
        List<int[]> combination = new ArrayList<int[]>(100);            

        int threads = Runtime.getRuntime().availableProcessors();
        ExecutorService service = Executors.newFixedThreadPool(threads);

        List<List<int[]>> ranTime = new ArrayList<List<int[]>>(2 * threads);            
        for (int x = 0; x < 2 * threads; x++) {
            List<int[]> jobs = new ArrayList<int[]>(90);
            ranTime.add(jobs);
        }

        if (gumDrop == false) {
            for (int x = 1; x <= minimum; x++) {
                rows[x] = 1;
            }
        } else {
            rows[1] = 1;
        }
        rows[A + 1] = 999;

        int y = 0, z = 0;
        System.out.println(threads);
        while (rows[A + 1] == 999) {                
            y++;
            int[] copy = Arrays.copyOf(rows, rows.length);


            if (y == 91) {
                z++;
                y = 1;
                if (z < 2* threads) {
                    ranTime.get(z).clear();
                }
            }

            if (z == 2 * threads) {
                processInputs(ranTime, combination, matTan, minimum, gumDrop, service);
                z = 0;
                ranTime.get(0).clear();
                ranTime.get(0).add(copy);
            } else {
                ranTime.get(z).add(copy);
            }

            nextComb(A, rows);
        }

        if (ranTime.get(0).size() > 0) {
            for (int x = 0; x < 2 * threads; x++) {
                if (judge == false) {
                    ranTime.remove(x);
                    threads--;
                    x--;
                }

                if (ranTime.get(x).size() != 90 && judge == true) {
                    judge = false;                      
                }
            }

            processInputs(ranTime, combination, matTan, minimum, gumDrop, service);
        }

        service.shutdown();

        try {
            service.awaitTermination(60, TimeUnit.SECONDS);
        } catch (InterruptedException e6) {
            System.out.print("Termination Error!");
        }

        developed(matTan, combination, gumDrop);
    }

    private static void processInputs(List<List<int[]>> ranTime, List<int[]> combination, List<List<Integer>> matTan, int minimum, boolean gumDrop, ExecutorService service) {
        Collection<StringTask> collection = new ArrayList<StringTask>(ranTime.size());      
        for (List<int[]> jobs : ranTime) {
            StringTask analysis = new StringTask(jobs, combination, matTan, minimum, gumDrop);
            collection.add(analysis);
        }

        try {
            List<Future<Integer>> futures = service.invokeAll(collection);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void developed(List<List<Integer>> matTan, List<int[]> combination, boolean gumDrop) {
        System.out.print("\n\n\n");
        for (int[] e : combination) {
            if (e[0] == ValMax.valMax) { // == ValMax.valMax
                Optimize10.prin(e);
                List<List<Integer>> complete = Multi.reduct1(e, matTan);
                if (gumDrop == true) {
                    System.out.println("Solution Matrix, transposed [above data works on column]"); 
                    Optimize10.prin(Multi.transpose(complete)); //The solution matrix, reorientated
                } else {                
                    System.out.println("Solution Matrix");  
                    Optimize10.prin(complete); //The solution matrix, reorientated
                }
            }
        }
    }

    private static void nextComb(int bounds, int[] rows) {
        int kappas = findMax(rows);
        if (rows[bounds] == 0) {
            rows[kappas + 1] = 1;
            rows[kappas] = 0;
        } else {
            int y = 1;
            int x = bounds;
            while (rows[x] == 1) {
                rows[x] = 0;
                y++;
                x--;                        
            }
            kappas = findMax(rows);
            if (kappas != -1) {
                rows[kappas] = 0;
            }
            int z = kappas + 1;
            while (y > 0) {
                rows[z] = 1;
                z++;
                y--;
            }
        }
    }

    private static int findMax(int[] rows) {
        int y = 0;
        for (int x = rows.length - 1; x >= 0; x--) {
            if (rows[x] == 1) {
                return x;
            }
        }

        return y;
    }
}

class StringTask implements Callable<Integer> {
    private List<List<Integer>> matTan;
    private List<int[]> combination;
    private List<int[]> jobs;
    private boolean gumDrop;
    private int minimum;

    StringTask(List<int[]> a, List<int[]> b, List<List<Integer>> c, int d, boolean e) {
        this.combination = b;
        this.minimum = d;
        this.gumDrop = e;
        this.matTan = c;
        this.jobs = a;
    }

    public Integer call() {
        for (int[] e : jobs) {
            int temp = Multi.reduct2(e, matTan, minimum, gumDrop);
            if (temp > ValMax.valMax) { //ValMax.valMax //userinput
                ValMax.valMax = e[0]; //userinput
                combination.add(e);
                System.out.print(ValMax.valMax + " ");
            }
        }

        return null;
    }
}

class Multi {
    public static int[] inverse;

    public static void halveIt(int[] col, List<List<Integer>> matCop) {
        int size = matCop.size(), a = 0;
        inverse = new int[size];
        for (int x = 0; x < size; x++) {
            for (int y = 0; y < matCop.get(0).size(); y++) {
                if (col[y] == 1 && matCop.get(x).get(y) == 2) {
                    inverse[x + a] = 1;
                    matCop.remove(x);
                    size--;
                    x--;
                    a++;
                    break;
                }
            }
        }
    }

    public static List<List<Integer>> reduct1(int[] row, List<List<Integer>> matCan) {
        List<List<Integer>> matTan = new ArrayList<List<Integer>>(matCan);

        int with = matTan.size(), high = inverse.length, a = 0;
        final int B = matCan.get(0).size() - 1;
        final int A = matCan.size();

        for (int x = 0; x < A; x++) {
            List<Integer> value = new ArrayList<Integer>(matCan.get(x));
            matTan.set(x, value);
        }

        int y = 0, size = 0;
        for (int x = 0; x < high; x++) {                        
            if (x < with) {
                if (row[x + a + 1] > 0) {
                    size = matTan.get(0).size();
                    for (y = 0; y < size; y++) {
                        if (matTan.get(x).get(y) == 2) {
                            for (int z = 0; z < with ; z++) {                                                                                   
                                matTan.get(z).remove(y);
                            }                               
                            size--;
                            y--;
                        }
                    }

                } else {
                    matTan.remove(x);
                    with--;
                    high--;
                    x--;
                    a++;
                }
            }
        }

        return matTan;
    }

    public static int reduct2(int[] row, List<List<Integer>> matCan, int minimum, boolean gumDrop) {
        int b = 0, c = 0, d = 0, e = 0, g = 0, high = inverse.length;
        final int B = matCan.get(0).size() - 1;
        final int A = matCan.size();
        for (int x = 0; x < high; x++) {                            
            if (x < A) {
                if (row[x + 1] > 0) {
                    b++;
                    for (int y = 0; y < B + 1; y++) {                           
                        if (matCan.get(x).get(y) == 2 && row[2 + A + y] == 0) {                                                                                                                                                                                                                                     
                            row[2 + A + y] = 1; // 1s mean that a column was deleted, 0 is kept.                            
                            d -= e;                             
                        } else if (row[2 + A + y] == 0) {
                            d++;
                        }
                    }
                    e++;
                }
            }

            if (inverse[x] == 0 && x < high || gumDrop == true && x < high) {
                if (row[x - c + 1] == 1) {
                    row[x - c + 1] = 1 + c + g;
                    g++;
                } else {
                    g++;
                }
            } else {
                c++;
            }
        }

        if (d / b < minimum && gumDrop == true) {
            row[0] = 0;
            d = 0;
        } else {
            row[0] = d;
        }

        return d;
    }

    public static List<List<Integer>> transpose(List<List<Integer>> matTan) {
        int d = matTan.get(0).size();

        List<List<Integer>> matFlip = new ArrayList<List<Integer>>(d);
        for (int y = 0; y < d; y++) {
            List<Integer> row = new ArrayList<Integer>();
            for (int x = 0; x < matTan.size(); x++) {
                row.add(matTan.get(x).get(y));
            }
            matFlip.add(row);
        }

        return matFlip;
    }
}

// ##########主要方法开始##########

public class Optimize10 {
    public static void main(String[] args) {
        double startTime = System.nanoTime() / 1000000;
        List<List<Integer>> matrix = Determine.rando();

    //  List<List<Integer>> matrix = Construct.rFile(args);
        List<List<Integer>> matTan = contract(new int[matrix.get(0).size()], matrix);
        int a = matTan.size(), b = matTan.get(0).size();

        System.out.println(a + "\t" + b);

        boolean gumDrop = false;
        int minimum = 40; //userinput

        BigInteger aNew = new BigInteger("2");
        BigInteger bNew = new BigInteger("2");                      
        aNew = aNew.pow(a);
        bNew = bNew.pow(b);

        for (int x = 1; x < minimum; x++) {
            aNew = aNew.subtract(binomial(a, x));           
        }

        if (aNew.compareTo(bNew) > 0) {
            gumDrop = true;
            matTan = Multi.transpose(matTan);
        }

        System.out.println(gumDrop);
        prin(matrix);
        prin(matTan);

        Search.finalize(matTan, gumDrop, minimum);
        double endTime = System.nanoTime() / 1000000;
        double duration = (endTime - startTime);
        System.out.println(duration);   
    }

// ########## MAIN METHOD END ############      

    private static BigInteger binomial(final int N, final int K) {
        BigInteger ret = BigInteger.ONE;
        for (int k = 0; k < K; k++) {
            ret = ret.multiply(BigInteger.valueOf(N-k)).divide(BigInteger.valueOf(k+1));
        }

        return ret;
    }

    private static List<List<Integer>> contract(int[] col, List<List<Integer>> matrix) {
        List<List<Integer>> matCop = new ArrayList<List<Integer>>(matrix);
        col[0] = 1; //userinput 1 means don't delete!
        col[1] = 1; //userinput
        col[2] = 1;
        col[12] = 1;
        col[14] = 1;
        col[22] = 1;
        col[28] = 1;
        col[29] = 1;
        Multi.halveIt(col, matCop);

        return matCop;
    }

    public static void prin(List<List<Integer>> matrix) {
        for (int x = 0; x < matrix.size(); x ++) {
            System.out.print("[" + matrix.get(x).get(0));
            for (int y = 1; y < matrix.get(0).size(); y++) {
                System.out.print(" " + matrix.get(x).get(y));
            }
            System.out.print("]\n");
        }   
        System.out.print("\n\n");
    }

    public static void prin(int[] a) {
        System.out.print("[" + a[0]);       
        for (int x = 1; x < a.length; x ++) {
            System.out.print(" " + a[x]);
        }
        System.out.print("]\n\n");  
    }

    public static void prin(String[] a) {
        System.out.print("[" + a[0]);       
        for (int x = 1; x < a.length; x ++) {
            System.out.print(" " + a[x]);
        }
        System.out.print("]\n\n");  
    }

    public static void prin2(List<Integer> a) {
        System.out.print("[" + a.get(0));       
        for (int x = 1; x < a.size(); x ++) {
            System.out.print(" " + a.get(x));
        }
        System.out.print("]\n\n");  
    }
}

1 个答案:

答案 0 :(得分:0)

好的,所以在这段代码中实际上没有无限循环。问题在于我的代码第466行;具体来说,我是基于在原始矩阵上截断并减去最小值之后我是否分析了原始矩阵或其转置的行数。这是错误的,例如,

sum_ {i = 40)^ {54}(54选择i)&gt;&gt; 2 ^ 32

我的计划正在进行中,因为它被告知要遍历超过一万亿的组合,而不仅仅是&#39;几十亿。当然,它可以在大约2小时内完成100亿次,而且我可以通过反转一些嵌套for循环来节省更多时间(另一次)。

我猜是时候学习分析以查看我的代码放慢的位置。