java - 给定一组选项找到最小的三元组

标签 java algorithm optimization big-o

我正在研究这个问题,在给定一组三元组的情况下找到最小的三元组,这组三元组在所有三个维度上都是最小的。但是,如果存在一个三元组,其最小的是任何一个或两个维度,而不是所有三个维度中最小的一个,那也需要考虑。

示例

我举个例子。 说吧,我的三胞胎如下

(25, 30, 34), (15, 31, 21), (10, 40, 21), (50, 30, 34), (25, 30, 10), (9, 20, 15)

现在,(9,20,15) 看起来是所有三个维度中最小的。但是,还存在一个选项 (25,30,10) 在第三个维度中最小,因为它在第三个维度中的得分 (10) 比任何其他选项都最小,因此也需要包含在输出中也。所以最终输出将是 {(9,20,15) and (25,30,10)}

因此,基本上应该考虑一个解决方案,如果它是显性的或最优的。我可以如下定义这些

1. Dominant : If an outcome o is at least as good for another agent as another outcome o' and there is some
agent who strictly prefers o to o'. Then o pareto-dominates o'

2. Optimal : o* is pareto-optimal if it isn't pareto-dominated by anything else

我的算法

这是我的算法。请参阅随附的代码。假设这三个维度分别称为 Course1Score、Course2Score 和 Course3Score。

所以我遍历输入,并为以下每一个找到最小的

1.{Course1Score}
2.{Course2Score}
3.{Course3Score}
4.{Course1Score, Course2Score}
5.{Course1Score, Course3Score}
6.{Course2Score, Course3Score}
7.{Course1Score, Course2Score, Course3Score}

然后我在最小化上述目标的解决方案中找到了不同的解决方案。

假案

现在这适用于大多数情况,除了下面的情况。让输入为 (1,100,100), (100,1,100), (100,100,1), (1,1,1) 根据上述算法,最小化上述目标的分数如下

 1.Minimize {Course1Score} - (1,100,100) 
(remember this won't be over-written by say,(1,1,1) since Course1Score of (1,1,1) IS NOT LESS than Course1Score of (1,100,100) which comes first in the order of inputs) )
    2.Minimize {Course2Score} - (100,1,100)
    3.Minimize {Course3Score} - (100,100,1)
    4.Minimize {Course1Score, Course2Score} - (1,100,100)
    5.Minimize {Course1Score, Course3Score} - (1,100,100)
    6.Minimize {Course2Score, Course3Score} - (100,1,100)
    7.Minimize {Course1Score, Course2Score, Course3Score} - (1,1,1)

继续算法,我们找到不同的解决方案并将它们报告为 (1,100,100)、(100,1,100)、(100,100,1)、(1,1,1) 但是,这个解决方案是不正确的。由于 (1,1,1) 在所有三个维度上都击败了所有其他解决方案,并且 (1,100,100)、(100,1,100)、(100,100,1) 在任何方面都优于 (1,1,1)尺寸。所以,我添加了一个额外的条件来检查这个可以在函数中找到的末尾

在线 java fiddle

这是一个 online java fiddle我的实现

我的实现

请找到我的代码

import java.util.ArrayList;

/* Glossary
 * 1. Dominant : If an outcome o is at least as good for another agent as another outcome o' and there is some
 * agent who strictly prefers o to o'. Then o Triplet-dominates o'
 * 
 * 2. Optimal : o* is Triplet-optimal if it isn't Triplet-dominated by anything else
 * 
 *   */
public class HelloWorld
{
    public static void main(String[] args)
    {
        Triplet myTriplet = new Triplet();

        /* Populating input and printing them */
        System.out.println("Printing input");
        myTriplet.PopulateSampleInput();
        myTriplet.Print(myTriplet.options);

        /* Printing the Triplet-Optimal solutions */
        ArrayList<Option> TripletSolutions = myTriplet.FindTripletOptimalSolutions();
        System.out.println("Printing TripletSolutions : ");
        myTriplet.Print(TripletSolutions);
    }
}

class Triplet
{
    ArrayList<Option> options;

    public Triplet()
    {
        options = new ArrayList<Option>();
    }

    void PopulateSampleInput()
    {
        Option option1 = new Option(25, 30, 34);
        Option option2 = new Option(15, 31, 21);
        Option option3 = new Option(10, 40, 21);
        Option option4 = new Option(50, 30, 34);
        Option option5 = new Option(25, 30, 10);
        Option option6 = new Option(9, 20, 15);

        options.add(option1);
        options.add(option2);
        options.add(option3);
        options.add(option4);
        options.add(option5);
        options.add(option6);
    }

    void Print(ArrayList<Option> al)
    {
        for(int i = 0;i< al.size();i++)
        {
            System.out.println(al.get(i).Course1Score + "," + al.get(i).Course2Score + "," + al.get(i).Course3Score);
        }
    }

    ArrayList<Option> FindTripletOptimalSolutions()
    {
        Option[] map = new Option[7];

        /* Initialization : Initially the best solution for minimizing all objectives is the first solution */
        for(int i = 0;i<map.length;i++)
            map[i] = options.get(0);

        for(int i=1;i<options.size();i++)
        {
            /* Fixing {1} */
            if(options.get(i).Course1Score < map[0].Course1Score)
                map[0] = options.get(i);

            /* Fixing {2} */
            if(options.get(i).Course2Score < map[1].Course2Score)
                map[1] = options.get(i);

            /* Fixing {3} */
            if(options.get(i).Course3Score < map[2].Course3Score)
                map[2] = options.get(i);

            /* Fixing {1,2} */
            if(options.get(i).Course1Score <= map[3].Course1Score && options.get(i).Course2Score <= map[3].Course2Score)
                map[3] = options.get(i);

            /* Fixing {1,3} */
            if(options.get(i).Course1Score <= map[4].Course1Score && options.get(i).Course3Score <= map[4].Course3Score)
                map[4] = options.get(i);

            /* Fixing {2,3} */
            if(options.get(i).Course2Score <= map[5].Course2Score && options.get(i).Course3Score <= map[5].Course3Score)
                map[5] = options.get(i);

            /* Fixing {1,2,3} */
            if(options.get(i).Course1Score <= map[6].Course1Score && options.get(i).Course2Score <= map[6].Course2Score && options.get(i).Course3Score <= map[6].Course3Score)
                map[6] = options.get(i);
        }

        /* find unique solutions */
        ArrayList<Option> DistinctSolutions = new ArrayList<Option>();
        DistinctSolutions = findUnique(map); 

        /* keeping only solutions that add something new */
        ArrayList<Option> TripletSolutions = EliminateWeakSolutionInCaseOfTie(DistinctSolutions);
        return TripletSolutions;
    }

    /* This function returns the unique solutions, otherwise, they will cancel out each other inside the 
     * EliminateWeakSolutionInCaseOfTie function that comes next */
    ArrayList<Option> findUnique(Option[] map)
    {
        ArrayList<Option> TripletSolutions = new ArrayList<Option>();
        for(int i = 0;i<map.length;i++)
        {
            if(!TripletSolutions.contains(map[i]))
                TripletSolutions.add(map[i]);
        }
        return TripletSolutions;
    }

    /* This function in case of ties where map[0]'s Course1Score is only equal to, but not less than
     * map[6]'s Course1Score, which in addition to minimizing Course1Score, also minimizes
     * Course2Score and Course3Score */
    ArrayList<Option> EliminateWeakSolutionInCaseOfTie(ArrayList<Option> DistinctSolutions)
    {
        ArrayList<Option> TripletSolutions = new ArrayList<Option>();
        int Include = 1;
        for(int i = 0;i<DistinctSolutions.size();i++,Include=1)
        {
            for(int j = 0;j<DistinctSolutions.size();j++)
            {
                if(i!=j && DistinctSolutions.get(j).Course1Score <= DistinctSolutions.get(i).Course1Score && DistinctSolutions.get(j).Course2Score <= DistinctSolutions.get(i).Course2Score && DistinctSolutions.get(j).Course3Score <= DistinctSolutions.get(i).Course3Score)
                {
                    Include = 0;
                    break;
                }
            }
            if(Include == 1)
                TripletSolutions.add(DistinctSolutions.get(i));
        }
        return TripletSolutions;
    }
}

class Option
{
    int Course1Score;
    int Course2Score;
    int Course3Score;

    public Option(int Course1Score, int Course2Score, int Course3Score)
    {
        // TODO Auto-generated constructor stub
        this.Course1Score = Course1Score;
        this.Course2Score = Course2Score;
        this.Course3Score = Course3Score;
    }
}

您能否为上述建议一个算法,和/或查看我的算法和实现?

编辑:我认为这个解决方案有效

伪代码

ParetoSolutionPool[1] = input[1]

for(i in 2:input)
    boolean ParetoDominant = false;
    boolean ParetoOptimal = true;

    for(j in 1:ParetoSolutionPool)
        if(input[i] ParetoDominates ParetoSolutionPool[j])
            remove ParetoSolutionPool[j]
            ParetoDominant = true;

        if(input[i] IsParetoDominatedBy ParetoSolutionPool[j])//extra if(ParetoDominant == false && ParetoOptimal == true && above)
            ParetoOptimal = false;
    end of for loop over j

    if(ParetoDominant || ParetoOptimal == true)
        add input[i] to ParetoSolutionPool

end of for loop over i

伪代码

基本上,两次检查。 1.如果一个输入/选项占主导地位(在所有三个维度上都较低),则现有解决方案之一会弹出该“现有解决方案”,并由该输入替换,因为它一致更好。 (例如 25、30、10 优于 25、30、34)

2.如果一个输入(在所有三个维度上)不比任何现有解决方案差,那么它也必须被考虑到解决方案池中。

所以基本上在上述两种情况中的任何一种情况下,都会将输入添加到解决方案池中。两者之间的唯一区别在于,在第一种情况下,较弱的现有解决方案也会被弹出。

代码

package TripletOptimizationAlgorithms;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;

public class algo4
{
    public static void main(String[] args)
    {
        Triplet myTriplet = new Triplet();

        /* Populating input and printing them */
        System.out.println("Printing input");
        //myTriplet.PopulateSampleInput();
        myTriplet.PopulateSampleInputFromFile();
        myTriplet.Print(myTriplet.options);
        System.out.println("Number of inputs read=="+myTriplet.options.size());

        /* Printing the Triplet-Optimal solutions */
        final long startTime = System.currentTimeMillis();
        ArrayList<Option> TripletSolutions = myTriplet.FindTripletOptimalSolutions();
        final long endTime = System.currentTimeMillis();

        System.out.println("Printing TripletSolutions : ");
        myTriplet.Print(TripletSolutions);

        System.out.println("Total execution time: " + (endTime - startTime) + " milliseconds" );
    }
}

class Triplet
{
    ArrayList<Option> options;

    public Triplet()
    {
        options = new ArrayList<Option>();
    }

    void PopulateSampleInput()
    {
        Option option1 = new Option(25, 30, 34);
        Option option2 = new Option(15, 31, 21);
        Option option3 = new Option(10, 40, 21);
        Option option4 = new Option(30, 30, 34);
        Option option5 = new Option(25, 30, 10);
        Option option6 = new Option(9, 20, 15);

        options.add(option1);
        options.add(option2);
        options.add(option3);
        options.add(option4);
        options.add(option5);
        options.add(option6);
    }

    void PopulateSampleInputFromFile()
    {
        try
        {
            String pwd = Paths.get(".").toAbsolutePath().normalize().toString();
            String inputpath = pwd + "/src/TripletOptimizationAlgorithms/myinput.txt";

            FileInputStream fstream = new FileInputStream(inputpath);
            DataInputStream in = new DataInputStream(fstream);
            BufferedReader br = new BufferedReader(new InputStreamReader(in));
            String strLine;
            while ((strLine = br.readLine()) != null)
            {
                String[] tokens = strLine.split(" ");
                Option myoption = new Option(Integer.parseInt(tokens[0]),Integer.parseInt(tokens[1]),Integer.parseInt(tokens[2]));//process record , etc
                options.add(myoption);
            }
            in.close();
        }
        catch (Exception e)
        {
            System.err.println("Error: " + e.getMessage());
        }
    }

    void Print(ArrayList<Option> al)
    {
        for(int i = 0;i< al.size();i++)
        {
            System.out.println(al.get(i).Course1Score + "," + al.get(i).Course2Score + "," + al.get(i).Course3Score);
        }
    }

    ArrayList<Option> FindTripletOptimalSolutions()
    {
        /* Initialization : Initialize the TripletSolutions to be the first option */
        ArrayList<Option> TripletSolutions = new ArrayList<Option>();
        TripletSolutions.add(options.get(0));

        /* looping across input */
        for(int i = 1;i<options.size();i++)
        {
            boolean TripletDominant = false;
            boolean TripletOptimal = true;
            Option optionUnderCheck = options.get(i);
            ArrayList<Integer> IndicesToRemove = new ArrayList<Integer>();

            /* looping across TripletSolutions */
            for(int j = 0;j<TripletSolutions.size();j++)
            {
                if(isTripletDominant(optionUnderCheck, TripletSolutions.get(j)) == true)
                {
                    TripletDominant = true;
                    IndicesToRemove.add(j);
                }

                if(IsTripletDominatedBy(optionUnderCheck, TripletSolutions.get(j)) == true)
                {
                    TripletOptimal = false;
                }
            }

            /* the weaker solutions have to be removed */
            if(TripletDominant == true)
            {
                Collections.sort(IndicesToRemove, Collections.reverseOrder());
                for(int k = 0;k<IndicesToRemove.size();k++)
                {
                    TripletSolutions.remove(IndicesToRemove.get(k).intValue());
                }
            }

            if(TripletDominant == true || TripletOptimal == true)
                TripletSolutions.add(optionUnderCheck);
        }

        return TripletSolutions;
    }

    boolean isTripletDominant(Option optionUnderCheck, Option existingSolution)
    {
        if(optionUnderCheck.Course1Score <= existingSolution.Course1Score && optionUnderCheck.Course2Score <= existingSolution.Course2Score && optionUnderCheck.Course3Score <= existingSolution.Course3Score)
            return true;
        return false;
    }

    boolean IsTripletDominatedBy(Option optionUnderCheck, Option existingSolution)
    {
        if(optionUnderCheck.Course1Score >= existingSolution.Course1Score && optionUnderCheck.Course2Score >= existingSolution.Course2Score && optionUnderCheck.Course3Score >= existingSolution.Course3Score)
            return true;
        return false;
    }
}

class Option
{
    int Course1Score;
    int Course2Score;
    int Course3Score;

    public Option(int Course1Score, int Course2Score, int Course3Score)
    {
        // TODO Auto-generated constructor stub
        this.Course1Score = Course1Score;
        this.Course2Score = Course2Score;
        this.Course3Score = Course3Score;
    }
}

最佳答案

其实这个可以简化很多。
因此,让我们看一下您的匹配规则:

  1. {Course1Score} 最低
  2. {Course2Score} ...
  3. {Course3Score} ...
  4. {Course1Score, Course2Score} 最佳或主导解决方案
  5. {Course1Score, Course3Score} ...
  6. {Course2Score, Course3Score} ...
  7. {Course1Score, Course2Score, Course3Score} ...

规则 1、2 和 3 只是搜索最小化 CourseNScore 的值(将 N 替换为规则编号)。 4,5 和 6 搜索对 ​​(a , b)(用相应的 CourseScore 替换 ab),使得存在没有与较低的 ab 配对。这些对也可以通过规则 1 - 3 找到,无论它们是显性的还是最优的。同样适用于规则 7 和规则 4 - 6。

因此,我们可以轻松地将搜索减少到找到 1 个元素最少的元组,并减少匹配集。这将大大加快搜索速度。这将产生 3 组元组(一组用于搜索的元组的每个元素)。

下一步: 减少找到的元组集。这可以通过一种非常幼稚的方法来完成:
匹配规则 7 的解决方案必须在搜索生成的所有集中。符合规则 4 的解决方案必须在符合规则 1 和 2 的集合中。

因此,减少结果成为一项非常微不足道的任务。

评论:
Java 中的变量名和方法名通常是小写的。
Option 生成 String 的部分,就像在 Triplet.Print 中使用的那样,应该转移到 Option.toString(),因为这是通常的方式。但是这段代码没有什么可批评的。

关于java - 给定一组选项找到最小的三元组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34032097/

相关文章:

java - 用很少的信息在 java 中解密 Rijndael 256(来自 PhP)编码的文本

java - 产生随机输出 : 100 numbers from 901 to 999

大数据集(>19000 行)上的 Python All 与 All 比率比较不断崩溃

algorithm - 如何为回溯算法获得更严格的界限?

.net - 如何突破ASP.NET webservice的限制?

python - 随机过程的循环优化

java - Android - 使用两个 xml 文件显示单个 Activity

python - 求和最大路径算法给出了意想不到的解决方案

performance - 我应该更喜欢跨一次内存访问来读取还是写入?

java - 如何设置 Libgdx 位图字体大小?