Инструменты Google OR: получение java .lang.UnsatisfiedLinkError: com.google.ortools.util.mainJNI.new_Domain__SWIG_2 (JJ) J для проблемы JobShop - PullRequest
0 голосов
/ 22 февраля 2020

Я пытаюсь запустить задачу JobShop в Java. Пример для этого не существует в папке examples / java, но он существует в примерах C ++, C# и Python. Поэтому я взял пример C# и преобразовал его в Java. Компилируется нормально, но выдает ошибку компоновщика SWIG. Где я ошибаюсь?

Вот исходный код, который прекрасно компилируется на моей машине:

import com.google.ortools.sat.CpModel;
import com.google.ortools.sat.CpSolver;
import com.google.ortools.sat.CpSolverStatus;
import com.google.ortools.sat.IntVar;
import com.google.ortools.sat.IntervalVar;

import java.util.ArrayList;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * JobShop example.
 *
 */

public class JobshopSat {
    static class Task {
        public Task(int taskId, int jobId, int duration, int machine)
        {
            TaskId = taskId;
            JobId = jobId;
            Duration = duration;
            Machine = machine;
            Name = "T" + taskId + "J" + jobId + "M" + machine + "D" + duration;
        }
        public int TaskId;
        public int JobId;
        public int Machine;
        public int Duration;
        public String Name;
    }

    //Number of machines.
    public final int machinesCount = 3;
    //horizon is the upper bound of the start time of all tasks.
    public final int horizon = 300;
    //this will be set to the size of myJobList variable.
    public int jobsCount;

    /* Search time limit in milliseconds. if it's equal to 0, then no time limit will be used. */

    public final int timeLimitInSeconds = 0;
    public static List<List<Task>> myJobList = new ArrayList<List<Task>>();

    public void initTaskList() {
        List<Task> taskList = new ArrayList<Task>();
        taskList.add(new Task(0, 0, 65, 0));
        taskList.add(new Task(1, 0, 5, 1));
        taskList.add(new Task(2, 0, 15, 2));
        myJobList.add(taskList);

        taskList = new ArrayList<Task>();
        taskList.add(new Task(0, 1, 15, 0));
        taskList.add(new Task(1, 1, 25, 1));
        taskList.add(new Task(2, 1, 10, 2));
        myJobList.add(taskList);

        taskList = new ArrayList<Task>();
        taskList.add(new Task(0, 2, 25, 0));
        taskList.add(new Task(1, 2, 30, 1));
        taskList.add(new Task(2, 2, 40, 2));
        myJobList.add(taskList);

        taskList = new ArrayList<Task>();
        taskList.add(new Task(0, 3, 20, 0));
        taskList.add(new Task(1, 3, 35, 1));
        taskList.add(new Task(2, 3, 10, 2));
        myJobList.add(taskList);

        taskList = new ArrayList<Task>();
        taskList.add(new Task(0, 4, 15, 0));
        taskList.add(new Task(1, 4, 25, 1));
        taskList.add(new Task(2, 4, 10, 2));
        myJobList.add(taskList);

        taskList = new ArrayList<Task>();
        taskList.add(new Task(0, 5, 25, 0));
        taskList.add(new Task(1, 5, 30, 1));
        taskList.add(new Task(2, 5, 40, 2));
        myJobList.add(taskList);

        taskList = new ArrayList<Task>();
        taskList.add(new Task(0, 6, 20, 0));
        taskList.add(new Task(1, 6, 35, 1));
        taskList.add(new Task(2, 6, 10, 2));
        myJobList.add(taskList);

        taskList = new ArrayList<Task>();
        taskList.add(new Task(0, 7, 10, 0));
        taskList.add(new Task(1, 7, 15, 1));
        taskList.add(new Task(2, 7, 50, 2));
        myJobList.add(taskList);

        taskList = new ArrayList<Task>();
        taskList.add(new Task(0, 8, 50, 0));
        taskList.add(new Task(1, 8, 10, 1));
        taskList.add(new Task(2, 8, 20, 2));
        myJobList.add(taskList);

        jobsCount = myJobList.size();  // Count
    }

    public static void main(String[] args) {
        JobshopSat jobshopSat = new JobshopSat();
        jobshopSat.initTaskList();
        CpModel model = new CpModel();

        // ----- Creates all intervals and integer variables -----

        // Stores all tasks attached interval variables per job.
        List<List<IntervalVar>> jobsToTasks = new ArrayList<List<IntervalVar>>(jobshopSat.jobsCount);
        List<List<IntVar>> jobsToStarts = new ArrayList<List<IntVar>>(jobshopSat.jobsCount);
        List<List<IntVar>> jobsToEnds = new ArrayList<List<IntVar>>(jobshopSat.jobsCount);

        // machinesToTasks stores the same interval variables as above, but
        // grouped my machines instead of grouped by jobs.
        List<List<IntervalVar>> machinesToTasks = new ArrayList<List<IntervalVar>>(jobshopSat.machinesCount);
        List<List<IntVar>> machinesToStarts = new ArrayList<List<IntVar>>(jobshopSat.machinesCount);

        for (int i = 0; i < jobshopSat.machinesCount; i++) {
            machinesToTasks.add(new ArrayList<IntervalVar>());
            machinesToStarts.add(new ArrayList<IntVar>());
        }

        // Creates all individual interval variables.
        for (List<Task> job: myJobList) {
            jobsToTasks.add(new ArrayList<IntervalVar>());
            jobsToStarts.add(new ArrayList<IntVar>());
            jobsToEnds.add(new ArrayList<IntVar>());
            for (Task task : job) {
                IntVar start = model.newIntVar(0, jobshopSat.horizon, task.Name);
                IntVar end = model.newIntVar(0, jobshopSat.horizon, task.Name);
                IntervalVar oneTask = model.newIntervalVar(start, task.Duration, end, task.Name);

                jobsToTasks.get(task.JobId).add(oneTask);
                jobsToStarts.get(task.JobId).add(start);
                jobsToEnds.get(task.JobId).add(end);
                machinesToTasks.get(task.Machine).add(oneTask);
                machinesToStarts.get(task.Machine).add(start);
            }
        }

        // ----- Creates model -----

        // Creates precedences inside jobs.
        for (int j = 0; j < jobsToTasks.size(); ++j) {
            for (int t = 0; t < jobsToTasks.get(j).size() - 1; ++t) {
                model.addLessOrEqual(jobsToEnds.get(j).get(t), jobsToStarts.get(j).get(t + 1));
                // model.Add(jobsToEnds.get(j).get(t) <= jobsToStarts.get(j).get(t + 1));
            }
        }

        // Adds no_overkap constraints on unary resources.
        for (int machineId = 0; machineId < jobshopSat.machinesCount; ++machineId) {
            IntervalVar[] myArray = new IntervalVar[machinesToTasks.get(machineId).size()];
            machinesToTasks.get(machineId).toArray(myArray);
            model.addNoOverlap(myArray);
        }

        // Creates array of end_times of jobs.
        IntVar[] allEnds = new IntVar[jobshopSat.jobsCount];
        for (int i = 0; i < jobshopSat.jobsCount; i++) {
            int sz = jobsToEnds.get(i).size();
            allEnds[i] = jobsToEnds.get(i).get(sz-1);
        }

        // Objective: minimize the makespan (maximum end times of all tasks) of the problem.
        IntVar makespan = model.newIntVar(0, jobshopSat.horizon, "makespan");
        model.addMaxEquality(makespan, allEnds);
        model.minimize(makespan);

        // Create the solver.
        CpSolver solver = new CpSolver();
        // Set the time limit.
        if (jobshopSat.timeLimitInSeconds > 0) {
            // solver.StringParameters = "max_time_in_seconds:" + jobshopSat.timeLimitInSeconds;
            solver.getParameters().setMaxTimeInSeconds(jobshopSat.timeLimitInSeconds);
        }
        // Solve the problem.
        CpSolverStatus status = solver.solve(model);

        if (status == CpSolverStatus.OPTIMAL) {
            System.out.println("Makespan = " + solver.objectiveValue());
            for (int m = 0; m < jobshopSat.machinesCount; ++m)
            {
                System.out.println("Machine {" + m + "}:");
                SortedMap<Long, String> starts = new TreeMap<Long, String>();
                for(IntVar var: machinesToStarts.get(m)) {
                    starts.put(solver.value(var), var.getName());
                }
                for (long key: starts.keySet()) {
                    System.out.println("  Task {" + starts.get(key) + "} starts at {" + key + "}");
                }
            }
        }
        else
        {
            System.out.println("No solution found!");
        }
    }
}

Я собираю и запускаю его из самой верхней папки следующим образом (обратите внимание на это точно так же, как и другие примеры):

anupambagchi:202[or-tools-binary] make build SOURCE=examples/java/JobshopSat.java
mkdir classes/JobshopSat
"/Library/Java/JavaVirtualMachines/openjdk-12.0.1.jdk/Contents/Home/bin/javac" -d classes/JobshopSat \
 -cp lib/com.google.ortools.jar:lib/protobuf.jar \
 examples/java/JobshopSat.java
rm -f lib/JobshopSat.jar
"/Library/Java/JavaVirtualMachines/openjdk-12.0.1.jdk/Contents/Home/bin/jar" cvf lib/JobshopSat.jar -C classes/JobshopSat .
added manifest
adding: JobshopSat$Task.class(in = 918) (out= 532)(deflated 42%)
adding: JobshopSat.class(in = 6212) (out= 2877)(deflated 53%)

anupambagchi:203[or-tools-binary] make run SOURCE=examples/java/JobshopSat.java
"/Library/Java/JavaVirtualMachines/openjdk-12.0.1.jdk/Contents/Home/bin/java" -Xss2048k -Djava.library.path=lib \
 -cp lib/JobshopSat.jar:lib/com.google.ortools.jar:lib/protobuf.jar \
 JobshopSat
Exception in thread "main" java.lang.UnsatisfiedLinkError: com.google.ortools.util.mainJNI.new_Domain__SWIG_2(JJ)J
    at com.google.ortools.util.mainJNI.new_Domain__SWIG_2(Native Method)
    at com.google.ortools.util.Domain.<init>(Domain.java:68)
    at com.google.ortools.sat.CpModel.newIntVar(CpModel.java:70)
    at JobshopSat.main(JobshopSat.java:132)
make: *** [run] Error 1

Пожалуйста, помогите мне определить проблему. Спасибо.

...