Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
symmetry_util.h
Go to the documentation of this file.
1// Copyright 2010-2024 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14#ifndef OR_TOOLS_SAT_SYMMETRY_UTIL_H_
15#define OR_TOOLS_SAT_SYMMETRY_UTIL_H_
16
17#include <memory>
18#include <vector>
19
20#include "absl/types/span.h"
22
23namespace operations_research {
24namespace sat {
25
26// Given the generator for a permutation group of [0, n-1], tries to identify
27// a grouping of the variables in an p x q matrix such that any permutations
28// of the columns of this matrix is in the given group.
29//
30// The name comes from: "Packing and Partitioning Orbitopes", Volker Kaibel,
31// Marc E. Pfetsch, https://arxiv.org/abs/math/0603678 . Here we just detect it,
32// independently of the constraints on the variables in this matrix. We can also
33// detect non-Boolean orbitope.
34//
35// In order to detect orbitope, this basic algorithm requires that the
36// generators of the orbitope must only contain one or more 2-cyle (i.e
37// transpositions). Thus they must be involutions. The list of transpositions in
38// the SparsePermutation must also be listed in a canonical order.
39//
40// TODO(user): Detect more than one orbitope? Note that once detected, the
41// structure can be exploited efficiently, but for now, a more "generic"
42// algorithm based on stabilizator should achieve the same preprocessing power,
43// so I don't know how hard we need to invest in orbitope detection.
44//
45// TODO(user): The heuristic is quite limited for now, but this works on
46// graph20-20-1rand.mps.gz. I suspect the generators provided by the detection
47// code follow our preconditions.
48std::vector<std::vector<int>> BasicOrbitopeExtraction(
49 absl::Span<const std::unique_ptr<SparsePermutation>> generators);
50
51// Returns a vector of size n such that
52// - orbits[i] == -1 iff i is never touched by the generators (singleton orbit).
53// - orbits[i] = orbit_index, where orbits are numbered from 0 to num_orbits - 1
54//
55// TODO(user): We could reuse the internal memory if needed.
56std::vector<int> GetOrbits(
57 int n, absl::Span<const std::unique_ptr<SparsePermutation>> generators);
58
59// Returns the orbits under the given orbitope action.
60// Same results format as in GetOrbits(). Note that here, the orbit index
61// is simply the row index of an element in the orbitope matrix.
62std::vector<int> GetOrbitopeOrbits(int n,
63 absl::Span<const std::vector<int>> orbitope);
64
65// Given the generators for a permutation group of [0, n-1], update it to
66// a set of generators of the group stabilizing the given element.
67//
68// Note that one can add symmetry breaking constraints by repeatedly doing:
69// 1/ Call GetOrbits() using the current set of generators.
70// 2/ Choose an element x0 in a large orbit (x0, .. xi ..) , and add x0 >= xi
71// for all i.
72// 3/ Update the set of generators to the one stabilizing x0.
73//
74// This is more or less what is described in "Symmetry Breaking Inequalities
75// from the Schreier-Sims Table", Domenico Salvagnin,
76// https://link.springer.com/chapter/10.1007/978-3-319-93031-2_37
77//
78// TODO(user): Implement!
80 int to_stabilize,
81 std::vector<std::unique_ptr<SparsePermutation>>* generators) {}
82
83} // namespace sat
84} // namespace operations_research
85
86#endif // OR_TOOLS_SAT_SYMMETRY_UTIL_H_
std::vector< int > GetOrbitopeOrbits(int n, absl::Span< const std::vector< int > > orbitope)
void TransformToGeneratorOfStabilizer(int to_stabilize, std::vector< std::unique_ptr< SparsePermutation > > *generators)
std::vector< int > GetOrbits(int n, absl::Span< const std::unique_ptr< SparsePermutation > > generators)
std::vector< std::vector< int > > BasicOrbitopeExtraction(absl::Span< const std::unique_ptr< SparsePermutation > > generators)
In SWIG mode, we don't want anything besides these top-level includes.