在给定一组选项的情况下找到最小的三元组

时间:2015-12-01 23:20:15

标签: 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)}

因此,如果它是Dominant或Optimal,基本上应该考虑一个解决方案。我可以将它们定义如下

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小提琴

这是我实施的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.如果输入/选项变量(在所有三个维度中都较低),则是现有解决方案之一,即现有解决方案&#34;弹出,并替换为此输入,因为它更好地一致。 (例如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 个答案:

答案 0 :(得分:1)

实际上这可以简化很多 那么让我们来看看你的匹配规则:

  1. {Course1Score}很少
  2. {Course2Score} ...
  3. {Course3Score} ...
  4. {Course1Score,Course2Score}最佳或主导解决方案
  5. {Course1Score,Course3Score} ...
  6. {Course2Score,Course3Score} ...
  7. {Course1Score,Course2Score,Course3Score} ...
  8. 规则1,2和3只搜索最小化CourseNScore的值(用规则号替换N)。 4,5和6搜索对(a , b)ab替换为相应的CourseScore),这样就不存在具有较低a或{{{ 1}}。这些对也将在规则1-3中找到,无论它们是主导还是最优。规则7与规则4 - 6同样适用。

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

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

    结果的减少因此变得非常简单。

    审查:
    变量和方法名称在java中通常是小写的 从b生成String的部分与Option中使用的部分一样,应转移到Triplet.Print,因为这是通常的方法。但是用这段代码批评并不多。