-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Updated documentation with Real and Int, job shop example md and general
wording updates. Added an FAQ page.
- Loading branch information
Showing
11 changed files
with
225 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
|
||
# Job shop scheduling | ||
|
||
The job shop scheduling problem is a linear integer problem arising in operations research. | ||
|
||
Suppose you are managing a machine shop with several different jobs in progress. | ||
Each job consists of a series of tasks. Some of the tasks have ordering constraints: e.g. parts must be manufactured before they can be installed in a larger assembly. | ||
Due to equipment constraints, we cannot schedule two tasks requiring the same machine at the same time. Additionally, all tasks must have a worker assigned to complete them. | ||
|
||
In this problem ([from Microsoft's Z3 tutorial](https://microsoft.github.io/z3guide/docs/theories/Arithmetic/)) we have three jobs, each consisting of one task to be completed first by worker A and one to be completed second by worker B. Each task has an integer-valued duration. Workers cannot work on two tasks at once or take each others' tasks. | ||
|
||
We'd like to find a solution such that all three jobs can be completed in an 8-hour workday. | ||
|
||
* Define two vector-valued variables t1 and t2 such that tj[i] is the start time of job i for worker j. | ||
|
||
* Define two vector-valued variables d1 and d2 such that dj[i] is the duration of job i for worker j. | ||
|
||
```@example | ||
using BooleanSatisfiability | ||
n = 3 # number of jobs | ||
m = 2 # number of tasks per job | ||
t1 = Int(n,"t1") | ||
t2 = Int(n, "t2") | ||
d1 = [2; 3; 2] | ||
d2 = [1; 1; 3] | ||
``` | ||
A start time of 0 corresponds to the first hour of the workday, and an end time of 8 corresponds to the last hour of the workday. | ||
```@example | ||
working_hours = all(and.(t1 .>= 0, t2 .+ d2 .<= 8)) | ||
``` | ||
|
||
Sequencing constraint: For each job, A must complete the first task before B can start the second task | ||
```@example | ||
sequencing = and(t2 .>= t1 .+ d1) | ||
``` | ||
|
||
Overlap constraint between all permutations | ||
```@example | ||
overlaps = [(1,2), (1,3), (2,3)] | ||
overlap_1 = all([or( t1[i] >= t1[j] + d1[j], t1[j] >= t1[i] + d1[i]) for (i,j) in overlaps]) | ||
overlap_2 = all([or( t2[i] >= t2[j] + d2[j], t2[j] >= t2[i] + d2[i]) for (i,j) in overlaps]) | ||
``` | ||
|
||
Solve the problem | ||
```@example | ||
status = sat!(working_hours, sequencing, overlap_1, overlap_2) | ||
println("status = $status") | ||
if status == :SAT | ||
println("t1 = $(value(t1))") | ||
println("t2 = $(value(t2))") | ||
end | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
# FAQ | ||
```@contents | ||
Pages = ["faq.md"] | ||
Depth = 3 | ||
``` | ||
|
||
## Where can I get help? | ||
Please open a Github issue! This is a new package and we would love to hear your suggestions, bug reports, feature requests, and other commentary. | ||
|
||
## Isn't this functionality included in JuMP? | ||
[JuMP](https://jump.dev/) provides support for [integer and Boolean-valued variables](https://jump.dev/JuMP.jl/stable/manual/variables/#Binary-variables), however it is developed primarily to support mathematical optimization over real-valued or integer-valued variables and continuous functions. As such, JuMP interfaces with solvers such as ECOS, MOSEK, and Gurobi that are intended for continuous optimization problems. When you use JuMP to solve a problem with discrete variables, your solver will likely use a branch-and-bound style method. | ||
|
||
### Should I use JuMP or BooleanSatisfiability? | ||
If you have a problem with mixed real and discrete variables, you should probably use JuMP to call a branch-and-bound solver. | ||
|
||
If you have a problem with only discrete variables, especially a large one, you should consider using a SAT solver. | ||
|
||
## How do I solve SAT problems in other langugages? | ||
Z3 has [APIs](https://z3prover.github.io/api/html/index.html) for C, C++, .NET, Java, Python and ML/OCaml. Additionally, Microsoft Research provides [tutorials](https://microsoft.github.io/z3guide/programming/Z3%20JavaScript%20Examples) for using Z3 in Python and JavaScript. | ||
|
||
## What about other theories in the SMT standard? | ||
In the future support may be added for additional theories supported in the SMTLIB2 standard, such as bitvectors and arrays. | ||
|
||
## How can I extract an unsatisfiability proof? | ||
Instead of calling `sat!`, use `save` to write the SMT representation of your problem to a file. Then invoke the solver from your command line, feed it the file and issue `(get-proof)` in `unsat` mode. | ||
|
||
Yes, that was a long way of saying "we don't support this feature". (Unsatisfiability proofs are difficult to support because the SMT2 standard doesn't specify their format - it's solver-dependent.) However you can still specify your problem in BooleanSatisfiability.jl and use the generated SMT file any way you like. | ||
|
||
## What does BooleanSatisfiability.jl actually do? | ||
We provide a high-level interface to SAT solvers. SAT solvers can accept input in the [SMT2](http://www.smtlib.org/) format, which is very powerful but not easy to read. When you specify a SAT problem in BooleanSatisfiability.jl and call `sat!`, we generate an SMT2-formatted **representation** of the problem, feed it to a solver, then interpret the result. | ||
|
||
You can feed the solver yourself. Call `save` instead of SAT to write the SMT2 representation of your problem to a file, where you can inspect it or add additional commands. | ||
|
||
# LFAQ | ||
(Less frequently-asked questions.) | ||
|
||
## Where do all the long, ugly names in the SMT file come from? | ||
To prevent names from being duplicated, BooleanSatisfiability.jl names new expressions using the Julia `hash` of their child expressions. | ||
|
||
For example, suppose you have | ||
```@example | ||
a = Int("a") | ||
b = Int("b") | ||
expr = a <= b | ||
print(smt(expr)) | ||
``` | ||
The (long, ugly) name of the combined expression `a <= b` is generated by hashing the names `a` and `b`. | ||
|
||
**Q:** Why don't you just concatenate `a` and `b` and call it `LEQ_a_b`? | ||
|
||
**A:** Because what if we have `a = Int(10,"a"); expr = sum(a)`? Are we going to say `expr.name = ADD_a_1_a_2_a_3_a_4_a_5_a_6_a_7_a_8_a_9_a_10`? If not, where do we draw the line? What if we called it `ADD_a_1__a_10`, but then we defined `expr2 = a[1] + a[3:8] + a[10]`? Then both `expr` and `expr1` would share the name `ADD_a_1__a_10` and all heck would break loose. | ||
|
||
If you think of a nicer way to name expressions, please open an issue! | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.