Dancing Links internal pyx code¶
EXAMPLES:
sage: from sage.combinat.matrices.dancing_links import dlx_solver
sage: rows = [[0,1,2], [3,4,5], [0,1], [2,3,4,5], [0], [1,2,3,4,5]]
sage: x = dlx_solver(rows)
sage: x
Dancing links solver for 6 columns and 6 rows
>>> from sage.all import *
>>> from sage.combinat.matrices.dancing_links import dlx_solver
>>> rows = [[Integer(0),Integer(1),Integer(2)], [Integer(3),Integer(4),Integer(5)], [Integer(0),Integer(1)], [Integer(2),Integer(3),Integer(4),Integer(5)], [Integer(0)], [Integer(1),Integer(2),Integer(3),Integer(4),Integer(5)]]
>>> x = dlx_solver(rows)
>>> x
Dancing links solver for 6 columns and 6 rows
The number of solutions:
sage: x.number_of_solutions()
3
>>> from sage.all import *
>>> x.number_of_solutions()
3
Iterate over the solutions:
sage: sorted(map(sorted, x.solutions_iterator()))
[[0, 1], [2, 3], [4, 5]]
>>> from sage.all import *
>>> sorted(map(sorted, x.solutions_iterator()))
[[0, 1], [2, 3], [4, 5]]
All solutions (computed in parallel):
sage: sorted(map(sorted, x.all_solutions()))
[[0, 1], [2, 3], [4, 5]]
>>> from sage.all import *
>>> sorted(map(sorted, x.all_solutions()))
[[0, 1], [2, 3], [4, 5]]
Return the first solution found when the computation is done in parallel:
sage: sorted(x.one_solution(ncpus=2)) # random
[0, 1]
>>> from sage.all import *
>>> sorted(x.one_solution(ncpus=Integer(2))) # random
[0, 1]
Find all solutions using some specific rows:
sage: x_using_row_2 = x.restrict([2])
sage: x_using_row_2
Dancing links solver for 7 columns and 6 rows
sage: sorted(map(sorted, x_using_row_2.solutions_iterator()))
[[2, 3]]
>>> from sage.all import *
>>> x_using_row_2 = x.restrict([Integer(2)])
>>> x_using_row_2
Dancing links solver for 7 columns and 6 rows
>>> sorted(map(sorted, x_using_row_2.solutions_iterator()))
[[2, 3]]
The two basic methods that are wrapped in this class are search which
returns 1 if a solution is found or 0 otherwise and get_solution
which return the current solution:
sage: x = dlx_solver(rows)
sage: x.search()
1
sage: x.get_solution()
[0, 1]
sage: x.search()
1
sage: x.get_solution()
[2, 3]
sage: x.search()
1
sage: x.get_solution()
[4, 5]
sage: x.search()
0
>>> from sage.all import *
>>> x = dlx_solver(rows)
>>> x.search()
1
>>> x.get_solution()
[0, 1]
>>> x.search()
1
>>> x.get_solution()
[2, 3]
>>> x.search()
1
>>> x.get_solution()
[4, 5]
>>> x.search()
0
There is also a method reinitialize to reinitialize the algorithm:
sage: x.reinitialize()
sage: x.search()
1
sage: x.get_solution()
[0, 1]
>>> from sage.all import *
>>> x.reinitialize()
>>> x.search()
1
>>> x.get_solution()
[0, 1]
- class sage.combinat.matrices.dancing_links.dancing_linksWrapper[source]¶
- Bases: - object- A simple class that implements dancing links. - The main methods to list the solutions are - search()and- get_solution(). You can also use- number_of_solutions()to count them.- This class simply wraps a C++ implementation of Carlo Hamalainen. - all_solutions(ncpus=None, column=None)[source]¶
- Return all solutions found after splitting the problem to allow parallel computation. - INPUT: - ncpus– integer (default:- None); maximal number of subprocesses to use at the same time. If- None, it detects the number of effective CPUs in the system using- sage.parallel.ncpus.ncpus().
- column– integer (default:- None); the column used to split the problem, if- Nonea random column is chosen
 - OUTPUT: list of solutions - EXAMPLES: - sage: from sage.combinat.matrices.dancing_links import dlx_solver sage: rows = [[0,1,2], [3,4,5], [0,1], [2,3,4,5], [0], [1,2,3,4,5]] sage: d = dlx_solver(rows) sage: S = d.all_solutions() sage: sorted(sorted(s) for s in S) [[0, 1], [2, 3], [4, 5]] - >>> from sage.all import * >>> from sage.combinat.matrices.dancing_links import dlx_solver >>> rows = [[Integer(0),Integer(1),Integer(2)], [Integer(3),Integer(4),Integer(5)], [Integer(0),Integer(1)], [Integer(2),Integer(3),Integer(4),Integer(5)], [Integer(0)], [Integer(1),Integer(2),Integer(3),Integer(4),Integer(5)]] >>> d = dlx_solver(rows) >>> S = d.all_solutions() >>> sorted(sorted(s) for s in S) [[0, 1], [2, 3], [4, 5]] - The number of CPUs can be specified as input: - sage: S = Subsets(range(4)) sage: rows = map(list, S) sage: dlx = dlx_solver(rows) sage: dlx Dancing links solver for 4 columns and 16 rows sage: dlx.number_of_solutions() 15 sage: sorted(sorted(s) for s in dlx.all_solutions(ncpus=2)) [[1, 2, 3, 4], [1, 2, 10], [1, 3, 9], [1, 4, 8], [1, 14], [2, 3, 7], [2, 4, 6], [2, 13], [3, 4, 5], [3, 12], [4, 11], [5, 10], [6, 9], [7, 8], [15]] - >>> from sage.all import * >>> S = Subsets(range(Integer(4))) >>> rows = map(list, S) >>> dlx = dlx_solver(rows) >>> dlx Dancing links solver for 4 columns and 16 rows >>> dlx.number_of_solutions() 15 >>> sorted(sorted(s) for s in dlx.all_solutions(ncpus=Integer(2))) [[1, 2, 3, 4], [1, 2, 10], [1, 3, 9], [1, 4, 8], [1, 14], [2, 3, 7], [2, 4, 6], [2, 13], [3, 4, 5], [3, 12], [4, 11], [5, 10], [6, 9], [7, 8], [15]] - If - ncpus=1, the computation is not done in parallel:- sage: sorted(sorted(s) for s in dlx.all_solutions(ncpus=1)) [[1, 2, 3, 4], [1, 2, 10], [1, 3, 9], [1, 4, 8], [1, 14], [2, 3, 7], [2, 4, 6], [2, 13], [3, 4, 5], [3, 12], [4, 11], [5, 10], [6, 9], [7, 8], [15]] - >>> from sage.all import * >>> sorted(sorted(s) for s in dlx.all_solutions(ncpus=Integer(1))) [[1, 2, 3, 4], [1, 2, 10], [1, 3, 9], [1, 4, 8], [1, 14], [2, 3, 7], [2, 4, 6], [2, 13], [3, 4, 5], [3, 12], [4, 11], [5, 10], [6, 9], [7, 8], [15]] 
 - get_solution()[source]¶
- Return the current solution. - After a new solution is found using the method - search()this method return the rows that make up the current solution.
 - ncols()[source]¶
- Return the number of columns. - EXAMPLES: - sage: from sage.combinat.matrices.dancing_links import dlx_solver sage: rows = [[0,1,2], [1,2], [0], [3,4,5]] sage: dlx = dlx_solver(rows) sage: dlx.ncols() 6 - >>> from sage.all import * >>> from sage.combinat.matrices.dancing_links import dlx_solver >>> rows = [[Integer(0),Integer(1),Integer(2)], [Integer(1),Integer(2)], [Integer(0)], [Integer(3),Integer(4),Integer(5)]] >>> dlx = dlx_solver(rows) >>> dlx.ncols() 6 
 - nrows()[source]¶
- Return the number of rows. - EXAMPLES: - sage: from sage.combinat.matrices.dancing_links import dlx_solver sage: rows = [[0,1,2], [1,2], [0], [3,4,5]] sage: dlx = dlx_solver(rows) sage: dlx.nrows() 4 - >>> from sage.all import * >>> from sage.combinat.matrices.dancing_links import dlx_solver >>> rows = [[Integer(0),Integer(1),Integer(2)], [Integer(1),Integer(2)], [Integer(0)], [Integer(3),Integer(4),Integer(5)]] >>> dlx = dlx_solver(rows) >>> dlx.nrows() 4 
 - number_of_solutions(ncpus=None, column=None)[source]¶
- Return the number of distinct solutions. - INPUT: - ncpus– integer (default:- None); maximal number of subprocesses to use at the same time. If- ncpus>1the dancing links problem is split into independent subproblems to allow parallel computation. If- None, it detects the number of effective CPUs in the system using- sage.parallel.ncpus.ncpus().
- column– integer (default:- None); the column used to split the problem, if- Nonea random column is chosen (this argument is ignored if- ncpusis- 1)
 - OUTPUT: integer - EXAMPLES: - sage: from sage.combinat.matrices.dancing_links import dlx_solver sage: rows = [[0,1,2]] sage: rows += [[0,2]] sage: rows += [[1]] sage: rows += [[3]] sage: x = dlx_solver(rows) sage: x.number_of_solutions() 2 - >>> from sage.all import * >>> from sage.combinat.matrices.dancing_links import dlx_solver >>> rows = [[Integer(0),Integer(1),Integer(2)]] >>> rows += [[Integer(0),Integer(2)]] >>> rows += [[Integer(1)]] >>> rows += [[Integer(3)]] >>> x = dlx_solver(rows) >>> x.number_of_solutions() 2 - The number of CPUs can be specified as input: - sage: rows = [[0,1,2], [3,4,5], [0,1], [2,3,4,5], [0], [1,2,3,4,5]] sage: x = dlx_solver(rows) sage: x.number_of_solutions(ncpus=2, column=3) 3 - >>> from sage.all import * >>> rows = [[Integer(0),Integer(1),Integer(2)], [Integer(3),Integer(4),Integer(5)], [Integer(0),Integer(1)], [Integer(2),Integer(3),Integer(4),Integer(5)], [Integer(0)], [Integer(1),Integer(2),Integer(3),Integer(4),Integer(5)]] >>> x = dlx_solver(rows) >>> x.number_of_solutions(ncpus=Integer(2), column=Integer(3)) 3 - sage: S = Subsets(range(5)) sage: rows = map(list, S) sage: d = dlx_solver(rows) sage: d.number_of_solutions() 52 - >>> from sage.all import * >>> S = Subsets(range(Integer(5))) >>> rows = map(list, S) >>> d = dlx_solver(rows) >>> d.number_of_solutions() 52 
 - one_solution(ncpus=None, column=None)[source]¶
- Return the first solution found. - This method allows parallel computations which might be useful for some kind of problems when it is very hard just to find one solution. - INPUT: - ncpus– integer (default:- None); maximal number of subprocesses to use at the same time. If- None, it detects the number of effective CPUs in the system using- sage.parallel.ncpus.ncpus(). If- ncpus=1, the first solution is searched serially.
- column– integer (default:- None); the column used to split the problem (see- restrict()). If- None, a random column is chosen. This argument is ignored if- ncpus=1.
 - OUTPUT: list of rows or - Noneif no solution is found- Note - For some case, increasing the number of cpus makes it faster. For other instances, - ncpus=1is faster. It all depends on problem which is considered.- EXAMPLES: - sage: from sage.combinat.matrices.dancing_links import dlx_solver sage: rows = [[0,1,2], [3,4,5], [0,1], [2,3,4,5], [0], [1,2,3,4,5]] sage: d = dlx_solver(rows) sage: solutions = [[0,1], [2,3], [4,5]] sage: sorted(d.one_solution()) in solutions True - >>> from sage.all import * >>> from sage.combinat.matrices.dancing_links import dlx_solver >>> rows = [[Integer(0),Integer(1),Integer(2)], [Integer(3),Integer(4),Integer(5)], [Integer(0),Integer(1)], [Integer(2),Integer(3),Integer(4),Integer(5)], [Integer(0)], [Integer(1),Integer(2),Integer(3),Integer(4),Integer(5)]] >>> d = dlx_solver(rows) >>> solutions = [[Integer(0),Integer(1)], [Integer(2),Integer(3)], [Integer(4),Integer(5)]] >>> sorted(d.one_solution()) in solutions True - The number of CPUs can be specified as input: - sage: sorted(d.one_solution(ncpus=2)) in solutions True - >>> from sage.all import * >>> sorted(d.one_solution(ncpus=Integer(2))) in solutions True - The column used to split the problem for parallel computations can be given: - sage: sorted(d.one_solution(ncpus=2, column=4)) in solutions True - >>> from sage.all import * >>> sorted(d.one_solution(ncpus=Integer(2), column=Integer(4))) in solutions True - When no solution is found: - sage: rows = [[0,1,2], [2,3,4,5], [0,1,2,3]] sage: d = dlx_solver(rows) sage: d.one_solution() is None True - >>> from sage.all import * >>> rows = [[Integer(0),Integer(1),Integer(2)], [Integer(2),Integer(3),Integer(4),Integer(5)], [Integer(0),Integer(1),Integer(2),Integer(3)]] >>> d = dlx_solver(rows) >>> d.one_solution() is None True 
 - one_solution_using_milp_solver(solver=None, integrality_tolerance=0.001)[source]¶
- Return a solution found using a MILP solver. - INPUT: - solver– string or- None(default:- None); possible values include- 'GLPK',- 'GLPK/exact',- 'Coin',- 'CPLEX',- 'Gurobi',- 'CVXOPT',- 'PPL',- 'InteractiveLP'
 - OUTPUT: list of rows or - Noneif no solution is found- Note - When comparing the time taken by method - one_solution, have in mind that- one_solution_using_milp_solverfirst creates (and caches) the MILP solver instance from the dancing links solver. This copy of data may take many seconds depending on the size of the problem.- EXAMPLES: - sage: from sage.combinat.matrices.dancing_links import dlx_solver sage: rows = [[0,1,2], [3,4,5], [0,1], [2,3,4,5], [0], [1,2,3,4,5]] sage: d = dlx_solver(rows) sage: solutions = [[0,1], [2,3], [4,5]] sage: d.one_solution_using_milp_solver() in solutions # needs sage.numerical.mip True - >>> from sage.all import * >>> from sage.combinat.matrices.dancing_links import dlx_solver >>> rows = [[Integer(0),Integer(1),Integer(2)], [Integer(3),Integer(4),Integer(5)], [Integer(0),Integer(1)], [Integer(2),Integer(3),Integer(4),Integer(5)], [Integer(0)], [Integer(1),Integer(2),Integer(3),Integer(4),Integer(5)]] >>> d = dlx_solver(rows) >>> solutions = [[Integer(0),Integer(1)], [Integer(2),Integer(3)], [Integer(4),Integer(5)]] >>> d.one_solution_using_milp_solver() in solutions # needs sage.numerical.mip True - Using optional solvers: - sage: # optional - gurobi sage_numerical_backends_gurobi, needs sage.numerical.mip sage: s = d.one_solution_using_milp_solver('gurobi') sage: s in solutions True - >>> from sage.all import * >>> # optional - gurobi sage_numerical_backends_gurobi, needs sage.numerical.mip >>> s = d.one_solution_using_milp_solver('gurobi') >>> s in solutions True - When no solution is found: - sage: rows = [[0,1,2], [2,3,4,5], [0,1,2,3]] sage: d = dlx_solver(rows) sage: d.one_solution_using_milp_solver() is None # needs sage.numerical.mip True - >>> from sage.all import * >>> rows = [[Integer(0),Integer(1),Integer(2)], [Integer(2),Integer(3),Integer(4),Integer(5)], [Integer(0),Integer(1),Integer(2),Integer(3)]] >>> d = dlx_solver(rows) >>> d.one_solution_using_milp_solver() is None # needs sage.numerical.mip True 
 - one_solution_using_sat_solver(solver=None)[source]¶
- Return a solution found using a SAT solver. - INPUT: - solver– string or- None(default:- None), possible values include- 'picosat',- 'cryptominisat',- 'LP',- 'glucose',- 'glucose-syrup'.
 - OUTPUT: list of rows or - Noneif no solution is found- Note - When comparing the time taken by method - one_solution, have in mind that- one_solution_using_sat_solverfirst creates the SAT solver instance from the dancing links solver. This copy of data may take many seconds depending on the size of the problem.- EXAMPLES: - sage: from sage.combinat.matrices.dancing_links import dlx_solver sage: rows = [[0,1,2], [3,4,5], [0,1], [2,3,4,5], [0], [1,2,3,4,5]] sage: d = dlx_solver(rows) sage: solutions = [[0,1], [2,3], [4,5]] sage: d.one_solution_using_sat_solver() in solutions # needs sage.sat True - >>> from sage.all import * >>> from sage.combinat.matrices.dancing_links import dlx_solver >>> rows = [[Integer(0),Integer(1),Integer(2)], [Integer(3),Integer(4),Integer(5)], [Integer(0),Integer(1)], [Integer(2),Integer(3),Integer(4),Integer(5)], [Integer(0)], [Integer(1),Integer(2),Integer(3),Integer(4),Integer(5)]] >>> d = dlx_solver(rows) >>> solutions = [[Integer(0),Integer(1)], [Integer(2),Integer(3)], [Integer(4),Integer(5)]] >>> d.one_solution_using_sat_solver() in solutions # needs sage.sat True - Using optional solvers: - sage: s = d.one_solution_using_sat_solver('glucose') # optional - glucose, needs sage.sat sage: s in solutions # optional - glucose, needs sage.sat True - >>> from sage.all import * >>> s = d.one_solution_using_sat_solver('glucose') # optional - glucose, needs sage.sat >>> s in solutions # optional - glucose, needs sage.sat True - When no solution is found: - sage: rows = [[0,1,2], [2,3,4,5], [0,1,2,3]] sage: d = dlx_solver(rows) sage: d.one_solution_using_sat_solver() is None # needs sage.sat True - >>> from sage.all import * >>> rows = [[Integer(0),Integer(1),Integer(2)], [Integer(2),Integer(3),Integer(4),Integer(5)], [Integer(0),Integer(1),Integer(2),Integer(3)]] >>> d = dlx_solver(rows) >>> d.one_solution_using_sat_solver() is None # needs sage.sat True 
 - reinitialize()[source]¶
- Reinitialization of the search algorithm. - This recreates an empty - dancing_linksobject and adds the rows to the instance of- dancing_links.- EXAMPLES: - sage: from sage.combinat.matrices.dancing_links import dlx_solver sage: rows = [[0,1,2], [3,4,5], [0,1], [2,3,4,5], [0], [1,2,3,4,5]] sage: x = dlx_solver(rows) sage: x.get_solution() if x.search() else None [0, 1] sage: x.get_solution() if x.search() else None [2, 3] - >>> from sage.all import * >>> from sage.combinat.matrices.dancing_links import dlx_solver >>> rows = [[Integer(0),Integer(1),Integer(2)], [Integer(3),Integer(4),Integer(5)], [Integer(0),Integer(1)], [Integer(2),Integer(3),Integer(4),Integer(5)], [Integer(0)], [Integer(1),Integer(2),Integer(3),Integer(4),Integer(5)]] >>> x = dlx_solver(rows) >>> x.get_solution() if x.search() else None [0, 1] >>> x.get_solution() if x.search() else None [2, 3] - Reinitialization of the algorithm: - sage: x.reinitialize() sage: x.get_solution() if x.search() else None [0, 1] sage: x.get_solution() if x.search() else None [2, 3] sage: x.get_solution() if x.search() else None [4, 5] sage: x.get_solution() if x.search() else None - >>> from sage.all import * >>> x.reinitialize() >>> x.get_solution() if x.search() else None [0, 1] >>> x.get_solution() if x.search() else None [2, 3] >>> x.get_solution() if x.search() else None [4, 5] >>> x.get_solution() if x.search() else None - Reinitialization works after solutions are exhausted: - sage: x.reinitialize() sage: x.get_solution() if x.search() else None [0, 1] sage: x.get_solution() if x.search() else None [2, 3] sage: x.get_solution() if x.search() else None [4, 5] sage: x.get_solution() if x.search() else None - >>> from sage.all import * >>> x.reinitialize() >>> x.get_solution() if x.search() else None [0, 1] >>> x.get_solution() if x.search() else None [2, 3] >>> x.get_solution() if x.search() else None [4, 5] >>> x.get_solution() if x.search() else None 
 - restrict(indices)[source]¶
- Return a dancing links solver solving the subcase which uses some given rows. - For every row that is wanted in the solution, we add a new column to the row to make sure it is in the solution. - INPUT: - indices– list; row indices to be found in the solution
 - OUTPUT: dancing links solver - EXAMPLES: - sage: from sage.combinat.matrices.dancing_links import dlx_solver sage: rows = [[0,1,2], [3,4,5], [0,1], [2,3,4,5], [0], [1,2,3,4,5]] sage: d = dlx_solver(rows) sage: d Dancing links solver for 6 columns and 6 rows sage: sorted(map(sorted, d.solutions_iterator())) [[0, 1], [2, 3], [4, 5]] - >>> from sage.all import * >>> from sage.combinat.matrices.dancing_links import dlx_solver >>> rows = [[Integer(0),Integer(1),Integer(2)], [Integer(3),Integer(4),Integer(5)], [Integer(0),Integer(1)], [Integer(2),Integer(3),Integer(4),Integer(5)], [Integer(0)], [Integer(1),Integer(2),Integer(3),Integer(4),Integer(5)]] >>> d = dlx_solver(rows) >>> d Dancing links solver for 6 columns and 6 rows >>> sorted(map(sorted, d.solutions_iterator())) [[0, 1], [2, 3], [4, 5]] - To impose that the \(0\)-th row is part of the solution, the rows of the new problem are: - sage: d_using_0 = d.restrict([0]) sage: d_using_0 Dancing links solver for 7 columns and 6 rows sage: d_using_0.rows() [[0, 1, 2, 6], [3, 4, 5], [0, 1], [2, 3, 4, 5], [0], [1, 2, 3, 4, 5]] - >>> from sage.all import * >>> d_using_0 = d.restrict([Integer(0)]) >>> d_using_0 Dancing links solver for 7 columns and 6 rows >>> d_using_0.rows() [[0, 1, 2, 6], [3, 4, 5], [0, 1], [2, 3, 4, 5], [0], [1, 2, 3, 4, 5]] - After restriction the subproblem has one more columns and the same number of rows as the original one: - sage: d.restrict([1]).rows() [[0, 1, 2], [3, 4, 5, 6], [0, 1], [2, 3, 4, 5], [0], [1, 2, 3, 4, 5]] sage: d.restrict([2]).rows() [[0, 1, 2], [3, 4, 5], [0, 1, 6], [2, 3, 4, 5], [0], [1, 2, 3, 4, 5]] - >>> from sage.all import * >>> d.restrict([Integer(1)]).rows() [[0, 1, 2], [3, 4, 5, 6], [0, 1], [2, 3, 4, 5], [0], [1, 2, 3, 4, 5]] >>> d.restrict([Integer(2)]).rows() [[0, 1, 2], [3, 4, 5], [0, 1, 6], [2, 3, 4, 5], [0], [1, 2, 3, 4, 5]] - This method allows to find solutions where the \(0\)-th row is part of a solution: - sage: sorted(map(sorted, d.restrict([0]).solutions_iterator())) [[0, 1]] - >>> from sage.all import * >>> sorted(map(sorted, d.restrict([Integer(0)]).solutions_iterator())) [[0, 1]] - Some other examples: - sage: sorted(map(sorted, d.restrict([1]).solutions_iterator())) [[0, 1]] sage: sorted(map(sorted, d.restrict([2]).solutions_iterator())) [[2, 3]] sage: sorted(map(sorted, d.restrict([3]).solutions_iterator())) [[2, 3]] - >>> from sage.all import * >>> sorted(map(sorted, d.restrict([Integer(1)]).solutions_iterator())) [[0, 1]] >>> sorted(map(sorted, d.restrict([Integer(2)]).solutions_iterator())) [[2, 3]] >>> sorted(map(sorted, d.restrict([Integer(3)]).solutions_iterator())) [[2, 3]] - Here there are no solutions using both 0th and 3rd row: - sage: list(d.restrict([0,3]).solutions_iterator()) [] - >>> from sage.all import * >>> list(d.restrict([Integer(0),Integer(3)]).solutions_iterator()) [] 
 - rows()[source]¶
- Return the list of rows. - EXAMPLES: - sage: from sage.combinat.matrices.dancing_links import dlx_solver sage: rows = [[0,1,2], [1,2], [0]] sage: x = dlx_solver(rows) sage: x.rows() [[0, 1, 2], [1, 2], [0]] - >>> from sage.all import * >>> from sage.combinat.matrices.dancing_links import dlx_solver >>> rows = [[Integer(0),Integer(1),Integer(2)], [Integer(1),Integer(2)], [Integer(0)]] >>> x = dlx_solver(rows) >>> x.rows() [[0, 1, 2], [1, 2], [0]] 
 - search()[source]¶
- Search for a new solution. - Return - 1if a new solution is found and- 0otherwise. To recover the solution, use the method- get_solution().- EXAMPLES: - sage: from sage.combinat.matrices.dancing_links import dlx_solver sage: rows = [[0,1,2]] sage: rows+= [[0,2]] sage: rows+= [[1]] sage: rows+= [[3]] sage: x = dlx_solver(rows) sage: print(x.search()) 1 sage: print(x.get_solution()) [3, 0] - >>> from sage.all import * >>> from sage.combinat.matrices.dancing_links import dlx_solver >>> rows = [[Integer(0),Integer(1),Integer(2)]] >>> rows+= [[Integer(0),Integer(2)]] >>> rows+= [[Integer(1)]] >>> rows+= [[Integer(3)]] >>> x = dlx_solver(rows) >>> print(x.search()) 1 >>> print(x.get_solution()) [3, 0] 
 - solutions_iterator()[source]¶
- Return an iterator of the solutions. - EXAMPLES: - sage: from sage.combinat.matrices.dancing_links import dlx_solver sage: rows = [[0,1,2], [3,4,5], [0,1], [2,3,4,5], [0], [1,2,3,4,5]] sage: d = dlx_solver(rows) sage: sorted(map(sorted, d.solutions_iterator())) [[0, 1], [2, 3], [4, 5]] - >>> from sage.all import * >>> from sage.combinat.matrices.dancing_links import dlx_solver >>> rows = [[Integer(0),Integer(1),Integer(2)], [Integer(3),Integer(4),Integer(5)], [Integer(0),Integer(1)], [Integer(2),Integer(3),Integer(4),Integer(5)], [Integer(0)], [Integer(1),Integer(2),Integer(3),Integer(4),Integer(5)]] >>> d = dlx_solver(rows) >>> sorted(map(sorted, d.solutions_iterator())) [[0, 1], [2, 3], [4, 5]] 
 - split(column)[source]¶
- Return a dict of independent solvers. - For each - i-th row containing a- 1in the- column, the dict associates the solver giving all solution using the- i-th row.- This is used for parallel computations. - INPUT: - column– integer; the column used to split the problem into independent subproblems
 - OUTPUT: dict where keys are row numbers and values are dlx solvers - EXAMPLES: - sage: from sage.combinat.matrices.dancing_links import dlx_solver sage: rows = [[0,1,2], [3,4,5], [0,1], [2,3,4,5], [0], [1,2,3,4,5]] sage: d = dlx_solver(rows) sage: d Dancing links solver for 6 columns and 6 rows sage: sorted(map(sorted, d.solutions_iterator())) [[0, 1], [2, 3], [4, 5]] - >>> from sage.all import * >>> from sage.combinat.matrices.dancing_links import dlx_solver >>> rows = [[Integer(0),Integer(1),Integer(2)], [Integer(3),Integer(4),Integer(5)], [Integer(0),Integer(1)], [Integer(2),Integer(3),Integer(4),Integer(5)], [Integer(0)], [Integer(1),Integer(2),Integer(3),Integer(4),Integer(5)]] >>> d = dlx_solver(rows) >>> d Dancing links solver for 6 columns and 6 rows >>> sorted(map(sorted, d.solutions_iterator())) [[0, 1], [2, 3], [4, 5]] - After the split each subproblem has one more column and the same number of rows as the original problem: - sage: D = d.split(0) sage: D {0: Dancing links solver for 7 columns and 6 rows, 2: Dancing links solver for 7 columns and 6 rows, 4: Dancing links solver for 7 columns and 6 rows} - >>> from sage.all import * >>> D = d.split(Integer(0)) >>> D {0: Dancing links solver for 7 columns and 6 rows, 2: Dancing links solver for 7 columns and 6 rows, 4: Dancing links solver for 7 columns and 6 rows} - The (disjoint) union of the solutions of the subproblems is equal to the set of solutions shown above: - sage: for x in D.values(): sorted(map(sorted, x.solutions_iterator())) [[0, 1]] [[2, 3]] [[4, 5]] - >>> from sage.all import * >>> for x in D.values(): sorted(map(sorted, x.solutions_iterator())) [[0, 1]] [[2, 3]] [[4, 5]] 
 - to_milp(solver=None)[source]¶
- Return the mixed integer linear program (MILP) representing an equivalent problem. - See also - sage.numerical.mip.MixedIntegerLinearProgram.- INPUT: - solver– string or- None(default:- None); possible values include- 'GLPK',- 'GLPK/exact',- 'Coin',- 'CPLEX',- 'Gurobi',- 'CVXOPT',- 'PPL',- 'InteractiveLP'
 - OUTPUT: - MixedIntegerLinearProgram instance 
- MIPVariable with binary components 
 - EXAMPLES: - sage: from sage.combinat.matrices.dancing_links import dlx_solver sage: rows = [[0,1,2], [0,2], [1], [3]] sage: d = dlx_solver(rows) sage: p,x = d.to_milp() # needs sage.numerical.mip sage: p # needs sage.numerical.mip Boolean Program (no objective, 4 variables, ... constraints) sage: x # needs sage.numerical.mip MIPVariable with 4 binary components - >>> from sage.all import * >>> from sage.combinat.matrices.dancing_links import dlx_solver >>> rows = [[Integer(0),Integer(1),Integer(2)], [Integer(0),Integer(2)], [Integer(1)], [Integer(3)]] >>> d = dlx_solver(rows) >>> p,x = d.to_milp() # needs sage.numerical.mip >>> p # needs sage.numerical.mip Boolean Program (no objective, 4 variables, ... constraints) >>> x # needs sage.numerical.mip MIPVariable with 4 binary components - In the reduction, the boolean variable \(x_i\) is - Trueif and only if the \(i\)-th row is in the solution:- sage: p.show() # needs sage.numerical.mip Maximization: Constraints:... one 1 in 0-th column: 1.0 <= x_0 + x_1 <= 1.0 one 1 in 1-th column: 1.0 <= x_0 + x_2 <= 1.0 one 1 in 2-th column: 1.0 <= x_0 + x_1 <= 1.0 one 1 in 3-th column: 1.0 <= x_3 <= 1.0 Variables: x_0 is a boolean variable (min=0.0, max=1.0) x_1 is a boolean variable (min=0.0, max=1.0) x_2 is a boolean variable (min=0.0, max=1.0) x_3 is a boolean variable (min=0.0, max=1.0) - >>> from sage.all import * >>> p.show() # needs sage.numerical.mip Maximization: <BLANKLINE> <BLANKLINE> Constraints:... one 1 in 0-th column: 1.0 <= x_0 + x_1 <= 1.0 one 1 in 1-th column: 1.0 <= x_0 + x_2 <= 1.0 one 1 in 2-th column: 1.0 <= x_0 + x_1 <= 1.0 one 1 in 3-th column: 1.0 <= x_3 <= 1.0 Variables: x_0 is a boolean variable (min=0.0, max=1.0) x_1 is a boolean variable (min=0.0, max=1.0) x_2 is a boolean variable (min=0.0, max=1.0) x_3 is a boolean variable (min=0.0, max=1.0) - Using some optional MILP solvers: - sage: d.to_milp('gurobi') # optional - gurobi sage_numerical_backends_gurobi, needs sage.numerical.mip (Boolean Program (no objective, 4 variables, 4 constraints), MIPVariable with 4 binary components) - >>> from sage.all import * >>> d.to_milp('gurobi') # optional - gurobi sage_numerical_backends_gurobi, needs sage.numerical.mip (Boolean Program (no objective, 4 variables, 4 constraints), MIPVariable with 4 binary components) 
 - to_sat_solver(solver=None)[source]¶
- Return the SAT solver solving an equivalent problem. - Note that row index \(i\) in the dancing links solver corresponds to the boolean variable index \(ì+1\) for the SAT solver to avoid the variable index \(0\). - See also - sage.sat.solvers.satsolver.- INPUT: - solver– string or- None(default:- None), possible values include- 'picosat',- 'cryptominisat',- 'LP',- 'glucose',- 'glucose-syrup'.
 - OUTPUT: SAT solver instance - EXAMPLES: - sage: from sage.combinat.matrices.dancing_links import dlx_solver sage: rows = [[0,1,2], [0,2], [1], [3]] sage: x = dlx_solver(rows) sage: s = x.to_sat_solver() # needs sage.sat - >>> from sage.all import * >>> from sage.combinat.matrices.dancing_links import dlx_solver >>> rows = [[Integer(0),Integer(1),Integer(2)], [Integer(0),Integer(2)], [Integer(1)], [Integer(3)]] >>> x = dlx_solver(rows) >>> s = x.to_sat_solver() # needs sage.sat - Using some optional SAT solvers: - sage: x.to_sat_solver('cryptominisat') # optional - pycryptosat # needs sage.sat CryptoMiniSat solver: 4 variables, 7 clauses. - >>> from sage.all import * >>> x.to_sat_solver('cryptominisat') # optional - pycryptosat # needs sage.sat CryptoMiniSat solver: 4 variables, 7 clauses. 
 
- sage.combinat.matrices.dancing_links.dlx_solver(rows)[source]¶
- Internal-use wrapper for the dancing links C++ code. - EXAMPLES: - sage: from sage.combinat.matrices.dancing_links import dlx_solver sage: rows = [[0,1,2]] sage: rows+= [[0,2]] sage: rows+= [[1]] sage: rows+= [[3]] sage: x = dlx_solver(rows) sage: print(x.search()) 1 sage: print(x.get_solution()) [3, 0] sage: print(x.search()) 1 sage: print(x.get_solution()) [3, 1, 2] sage: print(x.search()) 0 - >>> from sage.all import * >>> from sage.combinat.matrices.dancing_links import dlx_solver >>> rows = [[Integer(0),Integer(1),Integer(2)]] >>> rows+= [[Integer(0),Integer(2)]] >>> rows+= [[Integer(1)]] >>> rows+= [[Integer(3)]] >>> x = dlx_solver(rows) >>> print(x.search()) 1 >>> print(x.get_solution()) [3, 0] >>> print(x.search()) 1 >>> print(x.get_solution()) [3, 1, 2] >>> print(x.search()) 0