-
Notifications
You must be signed in to change notification settings - Fork 0
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 #46 from PermutaTriangle/req-placements
Req placements
- Loading branch information
Showing
8 changed files
with
114 additions
and
442 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
226 changes: 35 additions & 191 deletions
226
tilescopethree/strategies/batch_strategies/list_requirement_placements.py
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 |
---|---|---|
@@ -1,208 +1,52 @@ | ||
from itertools import chain | ||
from itertools import product | ||
|
||
from comb_spec_searcher import Rule | ||
from permuta import Perm | ||
from permuta.misc import DIR_EAST, DIR_NONE, DIR_NORTH, DIR_SOUTH, DIR_WEST | ||
from tilings import Obstruction, Requirement, Tiling | ||
from comb_spec_searcher import BatchRule | ||
from permuta.misc import DIR_EAST, DIR_NORTH, DIR_SOUTH, DIR_WEST | ||
from tilings.algorithms import RequirementPlacement | ||
|
||
|
||
def requirement_list_placement(tiling, **kwargs): | ||
"""Places all requirements on the tiling in every direction.""" | ||
for req in tiling.requirements: | ||
for direction in [DIR_NORTH, DIR_SOUTH, DIR_EAST, DIR_WEST]: | ||
tilings = place_requirement_list(tiling, req, direction) | ||
if tilings is None: | ||
continue | ||
yield Rule( | ||
formal_step=("Place requirement {} in direction {}." | ||
"".format(req, direction)), | ||
comb_classes=tilings, | ||
ignore_parent=False, | ||
possibly_empty=[True for _ in tilings], | ||
inferable=[True for _ in tilings], | ||
workable=[True for _ in tilings], | ||
constructor='disjoint') | ||
req_placement = RequirementPlacement(tiling) | ||
directions = (DIR_EAST, DIR_NORTH, DIR_SOUTH, DIR_WEST) | ||
for req, direction in product(tiling.requirements, directions): | ||
yield BatchRule(req_placement.place_point_of_req_list(req, direction), | ||
"Inserting {} point of requirement list ({})".format( | ||
req_placement._direction_string(direction), | ||
", ".join(str(r) for r in req))) | ||
|
||
|
||
def row_placements(tiling, row=True, positive=True, regions=False, **kwargs): | ||
"""Places the points in a row (or col if row=False) in the given | ||
direction.""" | ||
if row: | ||
x = tiling.dimensions[1] | ||
y = tiling.dimensions[0] | ||
only_cell_in_col = tiling.only_cell_in_col | ||
directions = [DIR_NORTH, DIR_SOUTH] | ||
else: | ||
x = tiling.dimensions[0] | ||
y = tiling.dimensions[1] | ||
only_cell_in_col = tiling.only_cell_in_row | ||
directions = [DIR_EAST, DIR_WEST] | ||
def row_placements(tiling, **kwargs): | ||
yield from RequirementPlacement(tiling).all_row_placement_rules() | ||
|
||
rows = range(x) | ||
if kwargs.get("index") is not None: | ||
rows = [kwargs.get("index")] | ||
if kwargs.get("direction") is not None: | ||
directions = [kwargs["direction"]] | ||
if regions: | ||
forward_maps = [] | ||
|
||
direction = kwargs.get('direction') | ||
if direction is not None: | ||
if row: | ||
if direction == DIR_NORTH: | ||
directions = [DIR_NORTH] | ||
elif direction == DIR_SOUTH: | ||
directions = [DIR_SOUTH] | ||
else: | ||
raise ValueError("Can't place rows in direction.") | ||
else: | ||
if direction == DIR_EAST: | ||
directions = [DIR_EAST] | ||
elif direction == DIR_WEST: | ||
directions = [DIR_WEST] | ||
else: | ||
raise ValueError("Can't place cols in direction.") | ||
def col_placements(tiling, **kwargs): | ||
yield from RequirementPlacement(tiling).all_col_placement_rules() | ||
|
||
for i in rows: | ||
place = True | ||
cells_in_row = [] | ||
for j in range(y): | ||
cell = (j, i) if row else (i, j) | ||
if positive and cell not in tiling.positive_cells: | ||
place = False | ||
break | ||
cells_in_row.append(cell) | ||
if place: | ||
if (len(cells_in_row) != 1 or | ||
not cells_in_row[0] in tiling.point_cells or | ||
not only_cell_in_col(cells_in_row[0])): | ||
req_list = tuple(Requirement(Perm((0,)), (cell,)) | ||
for cell in cells_in_row) | ||
if not positive: | ||
"""Adding the empty row case.""" | ||
empty_row_tiling = Tiling(tiling.obstructions + | ||
tuple(Obstruction(Perm((0,)), | ||
(cell,)) | ||
for cell in cells_in_row), | ||
tiling.requirements) | ||
if regions: | ||
forward_maps.append({c: frozenset([c]) | ||
for c in tiling.active_cells}) | ||
for direction in directions: | ||
if regions: | ||
tilings, placed_maps = place_requirement_list( | ||
tiling, req_list, direction, | ||
regions=regions) | ||
if not positive: | ||
tilings = [empty_row_tiling] + tilings | ||
forward_maps.extend(placed_maps) | ||
yield tilings, forward_maps | ||
else: | ||
tilings = place_requirement_list(tiling, req_list, | ||
direction) | ||
if not positive: | ||
tilings = [empty_row_tiling] + tilings | ||
yield Rule( | ||
formal_step=("Placing {} {} in direction {}." | ||
"".format("row" if row else "col", | ||
i, direction, | ||
i, direction, int(positive))), | ||
comb_classes=tilings, | ||
ignore_parent=False, | ||
possibly_empty=[True for _ in tilings], | ||
inferable=[True for _ in tilings], | ||
workable=[True for _ in tilings], | ||
constructor='disjoint') | ||
|
||
def row_and_col_placements(tiling, **kwargs): | ||
req_placements = RequirementPlacement(tiling) | ||
yield from req_placements.all_row_placement_rules() | ||
yield from req_placements.all_col_placement_rules() | ||
|
||
def col_placements(tiling, **kwargs): | ||
yield from row_placements(tiling, row=False, **kwargs) | ||
|
||
def partial_row_placements(tiling, **kwargs): | ||
req_placements = (RequirementPlacement(tiling, own_row=False), | ||
RequirementPlacement(tiling, own_col=False)) | ||
for req_placement in req_placements: | ||
yield from req_placement.all_row_placement_rules() | ||
|
||
def place_requirement_list(tiling, req_list, direction, regions=False): | ||
"""Return the list of tilings obtained by placing the direction-most point | ||
of a requirement list. This represents a batch strategy, where the | ||
direction-most point of each requirement in the list is placed.""" | ||
# Compute the points furthest in the given direction. | ||
min_points = minimum_points(req_list, direction) | ||
if len([c for _, c in min_points]) != len(set([c for _, c in min_points])): | ||
# Can't handle list requirements with more than req farthest in the | ||
# direction in same cell. | ||
return None | ||
# For each tiling, compute the tiling where this point is placed furthest | ||
# in that direction. | ||
res = [] | ||
if regions: | ||
forward_maps = [] | ||
for (idx, cell), req in zip(min_points, req_list): | ||
# Placing the forced occurrence of the point in the requirement | ||
new_req, forced_obstructions = req.place_forced_point(idx, direction) | ||
assert len(new_req) == 1 | ||
# Add the forced obstruction to ensure no other requirement has a point | ||
# further in that direction. | ||
forced_obstructions = (forced_obstructions + | ||
list(chain.from_iterable( | ||
r.other_req_forced_point(cell, direction) | ||
for r in req_list if r != req))) | ||
# New indices of the point | ||
point_cell = (cell[0] + 1, cell[1] + 1) | ||
# The set of new obstructions, consisting of the forced obstructions, | ||
# other obstructions where the point placement has been taken into | ||
# account and the 12, 21 in the cell. | ||
newobs = forced_obstructions + list(chain.from_iterable( | ||
ob.place_point(cell, DIR_NONE) for ob in tiling.obstructions)) + [ | ||
Obstruction.single_cell(Perm((0, 1)), point_cell), | ||
Obstruction.single_cell(Perm((1, 0)), point_cell)] | ||
# The rest of the requirements | ||
other_reqs = [reqs for reqs in tiling.requirements if reqs != req_list] | ||
# The new requirements, consisting of the requirement with the point | ||
# placed, other requirements where point placement has been taken into | ||
# account and the point requirement in the cell. | ||
newreqs = [list(chain.from_iterable(r.place_point(cell, DIR_NONE) | ||
for r in reqs)) | ||
for reqs in other_reqs] + [new_req] + [ | ||
[Requirement.single_cell(Perm((0,)), point_cell)]] | ||
placed_tiling = Tiling(newobs, newreqs) | ||
res.append(placed_tiling) | ||
if regions: | ||
def cell_map(c): | ||
mindex, minval = c | ||
maxdex = mindex + 1 | ||
maxval = minval + 1 | ||
if mindex >= cell[0]: | ||
maxdex += 2 | ||
if minval >= cell[1]: | ||
maxval += 2 | ||
if mindex > cell[0]: | ||
mindex += 2 | ||
if minval > cell[1]: | ||
minval += 2 | ||
return frozenset([(x, y) for x in range(mindex, maxdex) | ||
for y in range(minval, maxval)]) | ||
forward_maps.append({c: cell_map(c) for c in tiling.active_cells}) | ||
if regions: | ||
return res, forward_maps | ||
else: | ||
return res | ||
|
||
def partial_col_placements(tiling, **kwargs): | ||
req_placements = (RequirementPlacement(tiling, own_row=False), | ||
RequirementPlacement(tiling, own_col=False)) | ||
for req_placement in req_placements: | ||
yield from req_placement.all_col_placement_rules() | ||
|
||
def minimum_points(req_list, direction): | ||
"""Return a list of tuple containing the index and cell of the point in the | ||
requirement furthest to the geiven direction.""" | ||
res = [] | ||
if direction == DIR_WEST: | ||
res = [(0, req.pos[0]) for req in req_list] | ||
elif direction == DIR_EAST: | ||
res = [(len(req) - 1, req.pos[-1]) for req in req_list] | ||
elif direction == DIR_SOUTH: | ||
for req in req_list: | ||
mindex = req.patt.index(0) | ||
res.append((mindex, req.pos[mindex])) | ||
elif direction == DIR_NORTH: | ||
for req in req_list: | ||
maxdex = req.patt.index(0) | ||
res.append((maxdex, req.pos[maxdex])) | ||
else: | ||
raise ValueError("Must choose north, south, east or west.") | ||
|
||
return res | ||
def partial_row_and_col_placements(tiling, **kwargs): | ||
req_placements = (RequirementPlacement(tiling, own_row=False), | ||
RequirementPlacement(tiling, own_col=False)) | ||
for req_placement in req_placements: | ||
yield from req_placement.all_row_placement_rules() | ||
yield from req_placement.all_col_placement_rules() |
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
21 changes: 7 additions & 14 deletions
21
tilescopethree/strategies/equivalence_strategies/isolate_points.py
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 |
---|---|---|
@@ -1,19 +1,12 @@ | ||
from comb_spec_searcher import EquivalenceRule | ||
from permuta.misc import DIR_WEST | ||
from tilescopethree.strategies.batch_strategies.point_placements import \ | ||
place_point_of_requirement | ||
from tilings.algorithms import RequirementPlacement | ||
|
||
|
||
def point_isolations(tiling, **kwargs): | ||
point_cells = tiling.point_cells | ||
for ri, reqs in enumerate(tiling.requirements): | ||
if len(reqs) > 1: | ||
continue | ||
cell = reqs[0].is_point_perm() | ||
if cell is None or cell not in point_cells: | ||
continue | ||
yield EquivalenceRule( | ||
formal_step=("Isolating point at {} into its own row and " | ||
"column").format(cell), | ||
# Direction does not matter | ||
comb_class=place_point_of_requirement(tiling, ri, 0, DIR_WEST)) | ||
req_placement = RequirementPlacement(tiling) | ||
for cell in tiling.point_cells: | ||
if not tiling.only_cell_in_row_and_col(): | ||
isolated_tiling = req_placement.place_point_in_cell(cell, DIR_WEST) | ||
yield EquivalenceRule("Isolate point at cell {}.".format(cell), | ||
isolated_tiling) |
Oops, something went wrong.