-
Notifications
You must be signed in to change notification settings - Fork 252
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #173 from ramabile/master
XOR constraint + misc
- Loading branch information
Showing
6 changed files
with
292 additions
and
27 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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -118,3 +118,6 @@ venv.bak/ | |
|
||
# pytest | ||
.pytest_chache/ | ||
|
||
# model (for tests) | ||
model |
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,72 @@ | ||
from pyscipopt import Model | ||
|
||
################################################################################ | ||
# | ||
# EVEN OR ODD? | ||
# | ||
# If a positional argument is given: | ||
# prints if the argument is even/odd/neither | ||
# else: | ||
# prints if a value is even/odd/neither per each value in a example list | ||
# | ||
# This example is made for newcomers and motivated by: | ||
# - modulus is unsupported for pyscipopt.scip.Variable and int | ||
# - variables are non-integer by default | ||
# Based on this: | ||
# https://github.com/SCIP-Interfaces/PySCIPOpt/issues/172#issuecomment-394644046 | ||
# | ||
################################################################################ | ||
|
||
verbose = False | ||
sdic = {0:"even",1:"odd"} | ||
|
||
def parity(number): | ||
try: | ||
assert number == int(round(number)) | ||
m = Model() | ||
m.hideOutput() | ||
|
||
### variables are non-negative by default since 0 is the default lb. | ||
### To allow for negative values, give None as lower bound | ||
### (None means -infinity as lower bound and +infinity as upper bound) | ||
x = m.addVar("x", vtype="I", lb=None, ub=None) #ub=None is default | ||
n = m.addVar("n", vtype="I", lb=None) | ||
s = m.addVar("s", vtype="B") | ||
|
||
### CAVEAT: if number is negative, x's lb must be None | ||
### if x is set by default as non-negative and number is negative: | ||
### there is no feasible solution (trivial) but the program | ||
### does not highlight which constraints conflict. | ||
m.addCons(x==number) | ||
|
||
m.addCons(s == x-2*n) | ||
m.setObjective(s) | ||
m.optimize() | ||
|
||
assert m.getStatus() == "optimal" | ||
if verbose: | ||
for v in m.getVars(): | ||
print("%s %d" % (v,m.getVal(v))) | ||
print("%d%%2 == %d?" % (m.getVal(x), m.getVal(s))) | ||
print(m.getVal(s) == m.getVal(x)%2) | ||
|
||
xval = m.getVal(x) | ||
sval = m.getVal(s) | ||
sstr = sdic[sval] | ||
print("%d is %s" % (xval, sstr)) | ||
except (AssertionError, TypeError): | ||
print("%s is neither even nor odd!" % number.__repr__()) | ||
|
||
if __name__ == "__main__": | ||
import sys | ||
from ast import literal_eval as leval | ||
example_values = [0, 1, 1.5, "hallo welt", 20, 25, -101, -15., -10, -int(2**31), int(2**31-1), int(2**63)-1] | ||
try: | ||
try: | ||
n = leval(sys.argv[1]) | ||
except ValueError: | ||
n = sys.argv[1] | ||
parity(n) | ||
except IndexError: | ||
for n in example_values: | ||
parity(n) |
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,78 @@ | ||
from pyscipopt import Model | ||
from pyscipopt import quicksum | ||
|
||
################################################################################ | ||
# | ||
# AND/OR/XOR CONSTRAINTS | ||
# | ||
# Tutorial example on how to use AND/OR/XOR constraints. | ||
# | ||
# N.B.: standard SCIP XOR constraint works differently from AND/OR by design. | ||
# The constraint is set with a boolean rhs instead of an integer resultant. | ||
# cf. http://listserv.zib.de/pipermail/scip/2018-May/003392.html | ||
# A workaround to get the resultant as variable is here proposed. | ||
# | ||
################################################################################ | ||
|
||
def printFunc(name,m): | ||
print("* %s *" % name) | ||
objSet = bool(m.getObjective().terms.keys()) | ||
print("* Is objective set? %s" % objSet) | ||
if objSet: | ||
print("* Sense: %s" % m.getObjectiveSense()) | ||
for v in m.getVars(): | ||
if v.name != "n": | ||
print("%s: %d" % (v, round(m.getVal(v)))) | ||
print("\n") | ||
|
||
# AND # | ||
model = Model() | ||
model.hideOutput() | ||
x = model.addVar("x","B") | ||
y = model.addVar("y","B") | ||
z = model.addVar("z","B") | ||
r = model.addVar("r","B") | ||
model.addConsAnd([x,y,z],r) | ||
model.addCons(x==1) | ||
model.setObjective(r,sense="minimize") | ||
model.optimize() | ||
printFunc("AND",model) | ||
|
||
# OR # | ||
model = Model() | ||
model.hideOutput() | ||
x = model.addVar("x","B") | ||
y = model.addVar("y","B") | ||
z = model.addVar("z","B") | ||
r = model.addVar("r","B") | ||
model.addConsOr([x,y,z],r) | ||
model.addCons(x==0) | ||
model.setObjective(r,sense="maximize") | ||
model.optimize() | ||
printFunc("OR",model) | ||
|
||
# XOR (r as boolean, standard) # | ||
model = Model() | ||
model.hideOutput() | ||
x = model.addVar("x","B") | ||
y = model.addVar("y","B") | ||
z = model.addVar("z","B") | ||
r = True | ||
model.addConsXor([x,y,z],r) | ||
model.addCons(x==1) | ||
model.optimize() | ||
printFunc("Standard XOR (as boolean)",model) | ||
|
||
# XOR (r as variable, custom) # | ||
model = Model() | ||
model.hideOutput() | ||
x = model.addVar("x","B") | ||
y = model.addVar("y","B") | ||
z = model.addVar("z","B") | ||
r = model.addVar("r","B") | ||
n = model.addVar("n","I") #auxiliary | ||
model.addCons(r+quicksum([x,y,z]) == 2*n) | ||
model.addCons(x==0) | ||
model.setObjective(r,sense="maximize") | ||
model.optimize() | ||
printFunc("Custom XOR (as variable)",model) |
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.