Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flow Shop to Boolean satisfiability [Polynomial-time reduction]

I contact you in order to get an idea on "how to transform a flow shop scheduling problem" into a boolean satisfiability.

I already done such reduction for a N*N Sudoku, a N-queens and a Class scheduling problem, but I have some issue on how to transform the flow shop into SAT.

a SAT problem looks like this :

Illustration of a SAT problem

The goal is : with different boolean variables, to find an affectation of every variable in order to make the "sentence" true. (If finding a solution is possible).

I create my own solver with genetic algorithm able to find a solution and to prove when there is none. And now, I try it on different NP-problems, like Flow Shop.

Flow shop scheduling problems are a class of scheduling problems with a workshop or group shop in which the flow control shall enable an appropriate sequencing for each job and for processing on a set of machines or with other resources 1,2,...,m in compliance with given processing orders.

Especially the maintaining of a continuous flow of processing tasks is desired with a minimum of idle time and a minimum of waiting time.

Flow shop scheduling is a special case of job shop scheduling where there is strict order of all operations to be performed on all jobs.

Flow shop scheduling may apply as well to production facilities as to computing designs.

(http://en.wikipedia.org/wiki/Flow_shop_scheduling)

and the result is a sequence of jobs who will go through every workshop and the graphical result will look like this :

Graphical result of a Flow Shop

So to represent flow-shop instances, in input I have files like this :

2 4
4 26 65 62 
63 83 57 9 

This file means that I have 2 shops and 4 jobs, with all the duration time of each jobs on each machines.

The goal : to find the sequence who minimize the C_max, the end-date of the last job on the last machine if you prefer.

My Flow-Shop are really simple for now, but I have no idea how to formalize them in order to create a CNF file to execute my SAT solver after.

If one of you has some idea : article ? beginning of an idea ?

Next part of this question : Flow/Job Shop to Boolean satisfiability [Polynomial-time reduction] part 2

like image 617
Valentin Montmirail Avatar asked Mar 31 '15 10:03

Valentin Montmirail


People also ask

Is Boolean satisfiability problem unsolvable?

As a consequence, for each CNF formula, it is possible to solve the XOR-3-SAT problem defined by the formula, and based on the result infer either that the 3-SAT problem is solvable or that the 1-in-3-SAT problem is unsolvable.

What is satisfiability problem give an example?

Boolean Satisfiability Problem Boolean Satisfiability or simply SAT is the problem of determining if a Boolean formula is satisfiable or unsatisfiable. Satisfiable : If the Boolean variables can be assigned values such that the formula turns out to be TRUE, then we say that the formula is satisfiable.


2 Answers

I'd approach it like this:

You have a boolean variable for each resource usage start at each possible time at each machine (of course that requires that the time is limited and discrete, so I'd assume integers).

So you get variables like s_1_2_3 with the meaning resource one gets used at machine 2 starting from second 3.

Now you can formulate you various conditions in terms of these variables. Like:

  • each resource can be used only at one machine at a time
  • each machine can process only one resource at a time
  • machine steps have to happen in order (machine 1 needs to process resource x, before machine 2 can do it's job)

Warning: Even for small problems this will create a HUGE amount of boolean expressions.

As @gwilkins mentioned you need to transform the optimization problem into a boolean Problem. And I'd follow his approach: find a maximum time you are willing to accept and solve for that time limit (which actually limits the number of variables).

You can also start with something that should have a solution (like the time of all jobs added) and something that is a natural lower limit (the time needed for the longest job) and by splitting the interval find the optimal solution.

Once again: this will probably perform really awful, but it should provide the correct solution.

Example for a constraint formulated with this variables:

Machine 1 has to process resource x before Machine 2 can do its job (assuming the job has length 1):

(S_x_1_1 and ! S_x_2_1) 
or (S_x_1_2 and ! S_x_2_1 and ! S_x_2_2) 
or (S_x_1_3 and ! S_x_2_1 and ! S_x_2_2 and ! S_x_2_3)
or ...
like image 140
Jens Schauder Avatar answered Oct 26 '22 22:10

Jens Schauder


I'm using c#; I handle that result by these if statements:
( EndTime = StartTime + Duration)

// This is for handling start of M1J4 that starts after end of M2J2
// Bt I think this is out of 'Flow Shop Working'
if (i > 1)
    if (M[m].jobs[i].StartTime < M[m + 1].jobs[i - 2].EndTime)
        M[m].jobs[i].StartTime = M[m + 1].jobs[i - 2].EndTime;

if (i > 0)
    if (M[m].jobs[i].StartTime < M[m + 1].jobs[i - 1].StartTime)
        M[m].jobs[i].StartTime = M[m + 1].jobs[i - 1].StartTime;
if (M[m + 1].jobs[i].StartTime < M[m].jobs[i].EndTime)
    M[m + 1].jobs[i].StartTime = M[m].jobs[i].EndTime;

Code of my Console Application is :

class job
{
    public int Id { get; set; }
    public int Duration { get; set; }
    public int StartTime { get; set; }
    public int EndTime { get { return this.StartTime + this.Duration; } } 

    public job(int _Id) { this.Id = _Id; }

    public override string ToString()
    {
        if (this.Duration == 1)
            return "|";
        string result = "[";
        for (int i = 0; i < this.Duration - 2; i++)
            result += "#";
        return result + "]";
    } 
}

class machine
{
    public int Id { get; set; }
    public List<job> jobs = new List<job>();
    public int C_Max { get { return this.jobs[jobs.Count - 1].EndTime; } }

    public machine(int _Id) { this.Id = _Id; }

    public job AddJob(int _Duration)
    {
        int newId = 1;
        if (newId < jobs.Count + 1)
            newId = jobs.Count + 1;
        jobs.Add(new job(newId));
        jobs[newId - 1].Duration = _Duration;
        if (newId == 1)
            jobs[newId - 1].StartTime = 0;
        else
            jobs[newId - 1].StartTime = jobs[newId - 2].EndTime;
        return jobs[newId - 1];
    }

    public void LagJobs(job fromJob, int lagDuration)
    {
        for (int i = fromJob.Id; i <= jobs.Count; i++)
            jobs[i].StartTime += lagDuration;
    }

    public void AddJobs(int[] _Durations)
    {
        for (int i = 0; i < _Durations.Length; i++)
            this.AddJob(_Durations[i]);
    }

    public override string ToString()
    {
        return this.ToString(false);
    }

    public string ToString(bool withMax)
    {
        string result = string.Empty;
        for (int i = 0; i < jobs.Count; i++)
        {
            while (jobs[i].StartTime > result.Length)
                result += " ";
            result += jobs[i].ToString();
        }
        result = this.Id.ToString() + ". " + result;
        if (withMax) 
            result += " : " + this.C_Max;
        return result;
    }
}

class Program
{
    static void Main(string[] args)
    {
        int machinesCount = 4;
        List<machine> machines = new List<machine>();
        for (int i = 0; i < machinesCount; i++)
        {
            machines.Add(new machine(i + 1));
        }
        machines[0].AddJobs(new int[] { 5, 5, 3, 6, 3 });
        machines[1].AddJobs(new int[] { 4, 4, 2, 4, 4 });
        machines[2].AddJobs(new int[] { 4, 4, 3, 4, 1 });
        machines[3].AddJobs(new int[] { 3, 6, 3, 2, 6 });
        handelMachines(machines);
        for (int i = 0; i < machinesCount; i++)
            Console.WriteLine(machines[i].ToString(true));
        Console.ReadKey();
    }

    static void handelMachines(List<machine> M)
    {
        if (M.Count == 2)
        {
            for (int i = 0; i < M[0].jobs.Count; i++)
            {
                if (i > 1)
                    if (M[0].jobs[i].StartTime < M[1].jobs[i - 2].EndTime)
                        M[0].jobs[i].StartTime = M[1].jobs[i - 2].EndTime;
                if (i > 0)
                    if (M[0].jobs[i].StartTime < M[1].jobs[i - 1].StartTime)
                        M[0].jobs[i].StartTime = M[1].jobs[i - 1].StartTime;
                if (M[1].jobs[i].StartTime < M[0].jobs[i].EndTime)
                    M[1].jobs[i].StartTime = M[0].jobs[i].EndTime;
            }
        }
        else
        {
            for (int i = 0; i < M.Count - 1; i++)
            {
                List<machine> N = new List<machine>();
                N.Add(M[i]);
                N.Add(M[i + 1]);
                handelMachines(N);
            }
        }
    }
}

And result is:
enter image description here

like image 41
shA.t Avatar answered Oct 26 '22 22:10

shA.t