Пример #1
0
def get_supplier_solutions():
    """Execute the equivalent of the following SPARQL query, querying the Turtle file supplier.ttl:
        SELECT
            ?suppkey, ?nationkey
        FROM
            supplier
        WHERE {
            ?supplier <tpch:suppkey> ?suppkey .
            ?supplier <tpch:nationkey> ?nationkey .
        }
    """
    timer = FunctionTimer()
    short_prints = True

    suppliers = rdf.import_graph("supplier.ttl")
    timer.lap("suppliers", short=short_prints)

    # Find all triples that define a 'suppkey' (as predicate).
    bgp_suppkey_matches = clans.superstrict(suppliers, clans.from_dict({"p": rdflib.URIRef("tpch:suppkey")}))
    # Give the subject a name for later joining and object the name we need in the output.
    bgp_suppkey = clans.compose(bgp_suppkey_matches, clans.from_dict({"supplier": "s", "suppkey": "o"}))

    # Find all triples that define a 'nationkey' (as predicate) and give the subject a name for
    # later joining and object the name we need in the output.
    bgp_nationkey = clans.compose(
        clans.superstrict(suppliers, clans.from_dict({"p": rdflib.URIRef("tpch:nationkey")})),
        clans.from_dict({"supplier": "s", "nationkey": "o"}),
    )

    # Join the previous results on 'supplier' and project the columns we need.
    supplier_solutions = clans.project(clans.functional_cross_union(bgp_suppkey, bgp_nationkey), "nationkey", "suppkey")
    timer.end("supplier_solutions", short=short_prints)

    return supplier_solutions
Пример #2
0
def check_blocks(_board):
    """Check each block.  If there is only one value missing..."""
    if VERBOSE:
        print("* check_blocks")

    board = get_filled_cells(_board)
    blocks = partition.partition(board, partial(by_keys, 'band', 'stack'))
    for block_clan in _SORT(blocks, key=partial(by_clan_keys, 'band', 'stack')):
        new_possible, conflict = get_block_candidates(block_clan, board)

        if new_possible.is_empty:
            continue
        if new_possible.cardinality == 1:
            _board = get_new_board(_board, new_possible)
            continue

        if block_clan.cardinality == GRID_SIZE - 2:
            # Knowing that the value in conflict can't be placed in the conflict cell
            # ..it must go in the other...
            first_choice = clans.superstrict(new_possible, project(conflict, 'value'))
            if first_choice.cardinality == 2:
                # place both values
                _board = get_new_board(_board, first_choice)
                continue

            # Remove the first choice for all_possible
            remaining_possible = sets.minus(new_possible, first_choice)

            # Knowing that first_choice goes in a row/col, remove other value from that cell
            first_rowcol = project(first_choice, 'row', 'col')

            # The remaining cell is the second choice
            second_choice = sets.minus(remaining_possible,
                                       clans.superstrict(remaining_possible, first_rowcol))

            new_cells = sets.union(first_choice, second_choice)
            _board = get_new_board(_board, new_cells)
            continue

        # Partition by value
        candidates = partition.partition(new_possible, partial(by_key, 'value'))
        for candidate in _SORT(candidates, key=partial(by_clan_key, 'value')):
            # If any value fits in only 1 cell, place it
            if candidate.cardinality == 1:
                # Remove band/stack
                new_cell = project(candidate, 'row', 'col', 'value')
                _board = get_new_board(_board, new_cell)

    return _board
Пример #3
0
def check_blocks(_board):
    """Check each block.  If there is only one value missing..."""
    if VERBOSE:
        print("* check_blocks")

    board = get_filled_cells(_board)
    blocks = partition.partition(board, partial(by_keys, 'band', 'stack'))
    for block_clan in _SORT(blocks, key=partial(by_clan_keys, 'band', 'stack')):
        new_possible, conflict = get_block_candidates(block_clan, board)

        if new_possible.is_empty:
            continue
        if new_possible.cardinality == 1:
            _board = get_new_board(_board, new_possible)
            continue

        if block_clan.cardinality == GRID_SIZE - 2:
            # Knowing that the value in conflict can't be placed in the conflict cell
            # ..it must go in the other...
            first_choice = clans.superstrict(new_possible, project(conflict, 'value'))
            if first_choice.cardinality == 2:
                # place both values
                _board = get_new_board(_board, first_choice)
                continue

            # Remove the first choice for all_possible
            remaining_possible = sets.minus(new_possible, first_choice)

            # Knowing that first_choice goes in a row/col, remove other value from that cell
            first_rowcol = project(first_choice, 'row', 'col')

            # The remaining cell is the second choice
            second_choice = sets.minus(remaining_possible,
                                       clans.superstrict(remaining_possible, first_rowcol))

            new_cells = sets.union(first_choice, second_choice)
            _board = get_new_board(_board, new_cells)
            continue

        # Partition by value
        candidates = partition.partition(new_possible, partial(by_key, 'value'))
        for candidate in _SORT(candidates, key=partial(by_clan_key, 'value')):
            # If any value fits in only 1 cell, place it
            if candidate.cardinality == 1:
                # Remove band/stack
                new_cell = project(candidate, 'row', 'col', 'value')
                _board = get_new_board(_board, new_cell)

    return _board
Пример #4
0
def get_nations(regionname):
    """Execute the equivalent of the following XQuery statement and convert the XML into a clan:
        for $x in doc("regions.xml")/regions/region[name="MIDDLE EAST"]/nation
            return <nation>{$x/nationkey}<nationname>{data($x/name)}</nationname></nation>
    """
    timer = FunctionTimer()
    short_prints = True

    # Load the XML document. (Don't use multiplicity or sequence; our data doesn't require this.)
    regions = xml.import_xml("regions.xml", convert_numerics=True)
    timer.lap("regions", short=short_prints)

    # Get a clan where each region is a row.
    regions_clan = regions("regions")["region"]
    timer.lap("regions_clan", short=short_prints)

    # Filter this clan down to the region of interest (name is `regionname`).
    target_region = clans.superstrict(regions_clan, clans.from_dict({"name": regionname}))
    timer.lap("target_region", short=short_prints)

    # Get all 'nation' lefts out of this clan and create a clan where every row is a nation's data.
    nations_clan = target_region["nation"]
    timer.lap("nations_clan", short=short_prints)

    # Rename 'name' to 'nationname' and project 'nationkey' and 'nationname' (removing 'comment').
    nations = clans.compose(nations_clan, clans.from_dict({"nationkey": "nationkey", "nationname": "name"}))
    timer.end("nations", short=short_prints)

    return nations
Пример #5
0
def get_nations(regionname):
    """Execute the equivalent of the following XQuery statement and convert the XML into a clan:
        for $x in doc("regions.xml")/regions/region[name="MIDDLE EAST"]/nation
            return <nation>{$x/nationkey}<nationname>{data($x/name)}</nationname></nation>
    """
    timer = FunctionTimer()
    short_prints = True

    # Load the XML document. (Don't use multiplicity or sequence; our data doesn't require this.)
    regions = xml.import_xml('regions.xml', convert_numerics=True)
    timer.lap('regions', short=short_prints)

    # Get a clan where each region is a row.
    regions_clan = regions('regions')['region']
    timer.lap('regions_clan', short=short_prints)

    # Filter this clan down to the region of interest (name is `regionname`).
    target_region = clans.superstrict(regions_clan,
                                      clans.from_dict({'name': regionname}))
    timer.lap('target_region', short=short_prints)

    # Get all 'nation' lefts out of this clan and create a clan where every row is a nation's data.
    nations_clan = target_region['nation']
    timer.lap('nations_clan', short=short_prints)

    # Rename 'name' to 'nationname' and project 'nationkey' and 'nationname' (removing 'comment').
    nations = clans.compose(
        nations_clan,
        clans.from_dict({
            'nationkey': 'nationkey',
            'nationname': 'name'
        }))
    timer.end('nations', short=short_prints)

    return nations
Пример #6
0
def check_values(_board):
    """Look for values where only one is missing.  If there is only one missing, then there is
    only one cell where adding the value would not cause a duplicate in a row or column.  Fill
    in those cells if they exist."""
    if VERBOSE:
        print("* check_values")
    board = get_filled_cells(_board)

    new_cells = Set()
    value_clans = partition.partition(board, partial(by_key, 'value'))
    for value_clan in _SORT(value_clans, key=partial(by_clan_key, 'value')):
        # If there is only 1 missing value..fill in the cell
        if value_clan.cardinality == GRID_SIZE - 1:
            # Get the set of rows and cols containing value
            occupied_rows = project(value_clan, 'row')
            occupied_cols = project(value_clan, 'col')
            # Get the entire set of rows and cols based on the occupied rows and cols
            occupied = clans.superstrict(_board, sets.union(occupied_rows, occupied_cols))
            # Remove all occupied rows to get the only candidate row_col left
            row_col = sets.minus(_board, occupied)
            value = project(value_clan, 'value')
            new_cells = sets.union(new_cells, clans.cross_union(row_col, value))
    if new_cells:
        return get_new_board(_board, new_cells)
    return _board
Пример #7
0
def check_values(_board):
    """Look for values where only one is missing.  If there is only one missing, then there is
    only one cell where adding the value would not cause a duplicate in a row or column.  Fill
    in those cells if they exist."""
    if verbose:
        print("* check_values")
    board = get_filled_cells(_board)

    new_cells = Set()
    value_clans = partition.partition(board, partial(by_key, 'value'))
    for value_clan in _sort(value_clans, key=partial(by_clan_key, 'value')):
        # If there is only 1 missing value..fill in the cell
        if value_clan.cardinality == GRID_SIZE-1:
            # Get the set of rows and cols containing value
            occupied_rows = project(value_clan, 'row')
            occupied_cols = project(value_clan, 'col')
            # Get the entire set of rows and cols based on the occupied rows and cols
            occupied = clans.superstrict(_board, sets.union(occupied_rows, occupied_cols))
            # Remove all occupied rows to get the only candidate row_col left
            row_col = sets.minus(_board, occupied)
            value = project(value_clan, 'value')
            new_cells = sets.union(new_cells, clans.cross_union(row_col, value))
    if new_cells:
        return get_new_board(_board, new_cells)
    return _board
Пример #8
0
def get_supplier_solutions():
    """Execute the equivalent of the following SPARQL query, querying the Turtle file supplier.ttl:
        SELECT
            ?suppkey, ?nationkey
        FROM
            supplier
        WHERE {
            ?supplier <tpch:suppkey> ?suppkey .
            ?supplier <tpch:nationkey> ?nationkey .
        }
    """
    timer = FunctionTimer()
    short_prints = True

    suppliers = rdf.import_graph('supplier.ttl')
    timer.lap('suppliers', short=short_prints)

    # Find all triples that define a 'suppkey' (as predicate).
    bgp_suppkey_matches = clans.superstrict(
        suppliers, clans.from_dict({'p': rdflib.URIRef('tpch:suppkey')}))
    # Give the subject a name for later joining and object the name we need in the output.
    bgp_suppkey = clans.compose(
        bgp_suppkey_matches, clans.from_dict({
            'supplier': 's',
            'suppkey': 'o'
        }))

    # Find all triples that define a 'nationkey' (as predicate) and give the subject a name for
    # later joining and object the name we need in the output.
    bgp_nationkey = clans.compose(
        clans.superstrict(
            suppliers, clans.from_dict({'p':
                                        rdflib.URIRef('tpch:nationkey')})),
        clans.from_dict({
            'supplier': 's',
            'nationkey': 'o'
        }))

    # Join the previous results on 'supplier' and project the columns we need.
    supplier_solutions = clans.project(
        clans.cross_functional_union(bgp_suppkey, bgp_nationkey), 'nationkey',
        'suppkey')
    timer.end('supplier_solutions', short=short_prints)

    return supplier_solutions
Пример #9
0
def get_missing_rowcols(block_clan):
    band, stack = by_clan_keys('band', 'stack', block_clan)

    # Get block defined by band, stack
    full_block_clan = clans.superstrict(BANDS_STACKS,
                                        clans.from_dict({'band': band, 'stack': stack}))
    # Get missing rows/cols from the block
    target_rowcols = sets.minus(project(full_block_clan, 'row', 'col'),
                                project(block_clan, 'row', 'col'))
    return target_rowcols
Пример #10
0
def pattern_match(graph: 'PP( AxA )', pattern: dict):
    r"""Return all relations in ``graph`` that contain all members of ``pattern``.

    :param graph: An absolute :term:`clan`.
    :param pattern: A dictionary where the keys are the :term:`left`\s and the values the
        :term:`right`\s that will be matched.
    """
    assert _clans.is_member(graph)
    match_predicate = _clans.from_dict(pattern)
    return _clans.superstrict(graph, match_predicate, _checked=False)
Пример #11
0
def get_missing_rowcols(block_clan):
    band, stack = by_clan_keys('band', 'stack', block_clan)

    # Get block defined by band, stack
    full_block_clan = clans.superstrict(BANDS_STACKS,
                                        clans.from_dict({'band': band, 'stack': stack}))
    # Get missing rows/cols from the block
    target_rowcols = sets.minus(project(full_block_clan, 'row', 'col'),
                                project(block_clan, 'row', 'col'))
    return target_rowcols
Пример #12
0
def pattern_match(graph: 'PP( AxA )', pattern: dict):
    """Return all relations in ``graph`` that contain all members of ``pattern``.

    :param graph: An absolute clan.
    :param pattern: A dictionary where the keys are the lefts and the values the rights that
        will be matched.
    """
    assert(_clans.is_member(graph))
    match_predicate = _clans.from_dict(pattern)
    return _clans.superstrict(graph, match_predicate, _checked=False)
Пример #13
0
def get_new_board(board, new_cells):
    if verbose:
        for cell in new_cells:
            row = cell('row').value
            col = cell('col').value
            value = cell('value').value
            print("*** value %d goes in Row %d, Col %d" % (value, row, col))

    cell_filter = project(new_cells, 'row', 'col')
    old_cells = clans.superstrict(board, cell_filter)
    new_board = sets.minus(board, old_cells)

    bands_stacks = clans.superstrict(BANDS_STACKS, cell_filter)
    new_cells = clans.functional_cross_union(new_cells, bands_stacks)

    new_board = sets.union(new_board, new_cells)
    # if verbose:
    #     print(get_string(new_board))
    assert len(new_board) == GRID_SIZE*GRID_SIZE
    return new_board
Пример #14
0
def get_new_board(board, new_cells):
    if VERBOSE:
        for cell in new_cells:
            row = cell('row').value
            col = cell('col').value
            value = cell('value').value
            print("*** value %d goes in Row %d, Col %d" % (value, row, col))

    cell_filter = project(new_cells, 'row', 'col')
    old_cells = clans.superstrict(board, cell_filter)
    new_board = sets.minus(board, old_cells)

    band = new_cells['band']
    if not band:
        # print("missing band")
        bands_stacks = clans.superstrict(BANDS_STACKS, cell_filter)
        new_cells = clans.cross_functional_union(new_cells, bands_stacks)

    new_board = sets.union(new_board, new_cells)
    # if VERBOSE:
    #     print(get_string(new_board))
    assert len(new_board) == GRID_SIZE * GRID_SIZE
    return new_board
Пример #15
0
def get_block_candidates(block_clan, board):
    # Get the set of missing values...see if any can be placed due to row/col information
    values_clan = get_missing_values(block_clan)

    # Get the set of missing values...see if any can be placed due to row/col information
    target_rowcols = get_missing_rowcols(block_clan)

    if block_clan.cardinality == GRID_SIZE - 1:
        new_cells = clans.cross_union(target_rowcols, values_clan)
        return new_cells, Set()

    # Need cross union values with rows
    rows_clan = project(target_rowcols, 'row')
    cols_clan = project(target_rowcols, 'col')
    possible_rows_values = clans.cross_union(values_clan, rows_clan)
    possible_cols_values = clans.cross_union(values_clan, cols_clan)

    possible_rows_cols_values = sets.union(possible_rows_values, possible_cols_values)

    # The occupied_clan is the row/col/value set that is a conflict for values
    occupied_clan = clans.superstrict(board, possible_rows_cols_values)

    # If there are no conflicts then no cells can be placed
    if occupied_clan.is_empty:
        return Set(), Set()

    all_possible = clans.cross_union(values_clan, target_rowcols).cache_functional(CacheStatus.IS)

    # Get the set of conflicts...conflicting row/value + col/value
    conflict = sets.union(
        clans.superstrict(all_possible, project(occupied_clan, 'value', 'col')),
        clans.superstrict(all_possible, project(occupied_clan, 'value', 'row')))

    # Remove the conflicts from all_possible
    new_possible = sets.minus(all_possible, conflict)
    return new_possible, conflict
Пример #16
0
def get_block_candidates(block_clan, board):
    # Get the set of missing values...see if any can be placed due to row/col information
    values_clan = get_missing_values(block_clan)

    # Get the set of missing values...see if any can be placed due to row/col information
    target_rowcols = get_missing_rowcols(block_clan)

    if block_clan.cardinality == GRID_SIZE - 1:
        new_cells = clans.cross_union(target_rowcols, values_clan)
        return new_cells, Set()

    # Need cross union values with rows
    rows_clan = project(target_rowcols, 'row')
    cols_clan = project(target_rowcols, 'col')
    possible_rows_values = clans.cross_union(values_clan, rows_clan)
    possible_cols_values = clans.cross_union(values_clan, cols_clan)

    possible_rows_cols_values = sets.union(possible_rows_values, possible_cols_values)

    # The occupied_clan is the row/col/value set that is a conflict for values
    occupied_clan = clans.superstrict(board, possible_rows_cols_values)

    # If there are no conflicts then no cells can be placed
    if occupied_clan.is_empty:
        return Set(), Set()

    all_possible = clans.cross_union(values_clan, target_rowcols).cache_functional(CacheStatus.IS)

    # Get the set of conflicts...conflicting row/value + col/value
    conflict = sets.union(
        clans.superstrict(all_possible, project(occupied_clan, 'value', 'col')),
        clans.superstrict(all_possible, project(occupied_clan, 'value', 'row')))

    # Remove the conflicts from all_possible
    new_possible = sets.minus(all_possible, conflict)
    return new_possible, conflict
Пример #17
0
# Get all nation names
# /regions/region/nation/name
nations = regions['nation']
print('regions[\'nation\']:\n' + mo_to_str(nations))

nation_names = nations['name']
print('nation_names:\n' + mo_to_str(nation_names))

# Get all nation names of a given region
# for $x in doc("regions.xml")/regions/region where $x/name='AMERICA' return $x/nation/name
from algebraixlib.algebras.clans import superstrict, from_dict
america_region_name = from_dict({'name': 'AMERICA'})
print('america_region_name:\n' + mo_to_str(america_region_name))

america_region = superstrict(regions, america_region_name)
print('america_region:\n' + mo_to_str(america_region))

america_nations_names = america_region['nation']['name']
print('america_nations_names:\n' + mo_to_str(america_nations_names))

# Get all region key and nation name pairs
# for $x in doc("regions.xml")/regions/region/nation/name return <pair>{$x/../../regionkey}{$x}</pair>
from algebraixlib.mathobjects import Set
from algebraixlib.algebras.clans import project, cross_union
from algebraixlib.algebras.sets import union
region_key_nation_name_pairs_accumulator = Set()
for region in regions:
    region_key = project(Set(region), 'regionkey')
    print('region_key:\n' + mo_to_str(region_key))
Пример #18
0
def check_blocks(_board):
    """Check each block.  If there is only one value missing..."""
    if verbose:
        print("* check_blocks")

    board = get_filled_cells(_board)
    blocks = partition.partition(board, partial(by_keys, 'band', 'stack'))
    for block_clan in _sort(blocks, key=partial(by_clan_keys, 'band', 'stack')):
        # Get the set of missing values...see if any can be placed due to row/col information
        values_clan = get_missing_values(block_clan)

        # Get the set of missing values...see if any can be placed due to row/col information
        target_rowcols = get_missing_rowcols(block_clan)

        if block_clan.cardinality == GRID_SIZE-1:
            new_cells = clans.cross_union(target_rowcols, values_clan)
            _board = get_new_board(_board, new_cells)
            continue

        # Need cross union values with rows
        rows_clan = project(target_rowcols, 'row')
        cols_clan = project(target_rowcols, 'col')
        possible_rows_values = clans.cross_union(values_clan, rows_clan)
        possible_cols_values = clans.cross_union(values_clan, cols_clan)

        possible_rows_cols_values = sets.union(possible_rows_values, possible_cols_values)

        # The occupied_clan is the row/col/value set that is a conflict for values
        occupied_clan = project(clans.superstrict(board, possible_rows_cols_values),
                                'value', 'row', 'col')

        # If there are no conflicts then no cells can be placed
        if occupied_clan.is_empty:
            continue

        all_possible = clans.cross_union(values_clan, target_rowcols).cache_is_left_functional(True)
        for rel in all_possible:
            rel.cache_is_left_functional(True)

        # Get the set of conflicts...conflicting row/value + col/value
        conflict = sets.union(
            clans.superstrict(all_possible, project(occupied_clan, 'value', 'col')),
            clans.superstrict(all_possible, project(occupied_clan, 'value', 'row')))

        # Remove the conflicts from all_possible
        new_possible = sets.minus(all_possible, conflict)

        if block_clan.cardinality == GRID_SIZE-2:
            # Knowing that the value in conflict can't be placed in the conflict cell
            # ..it must go in the other...
            first_choice = clans.superstrict(new_possible, project(conflict, 'value'))
            if first_choice.cardinality == 2:
                # place both values
                _board = get_new_board(_board, first_choice)
                continue

            # Remove the first choice for all_possible
            remaining_possible = sets.minus(new_possible, first_choice)

            # Knowing that first_choice goes in a row/col, remove other value from that cell
            first_rowcol = project(first_choice, 'row', 'col')

            # The remaining cell is the second choice
            second_choice = sets.minus(remaining_possible,
                                       clans.superstrict(remaining_possible, first_rowcol))

            new_cells = sets.union(first_choice, second_choice)
            _board = get_new_board(_board, new_cells)
            continue

        # Partition by value
        candidates = partition.partition(new_possible, partial(by_key, 'value'))
        for candidate in _sort(candidates, key=partial(by_clan_key, 'value')):
            # If any value fits in only 1 cell, place it
            if candidate.cardinality == 1:
                # Remove band/stack
                new_cell = project(candidate, 'row', 'col', 'value')
                _board = get_new_board(_board, new_cell)
    return _board
Пример #19
0
def check_rows(_board):
    """Look for rows where there is only one missing value.  If any are found fill in the missing
    value.  Look for rows where there are two missing values.  If either missing value is blocked
    by the same value in the candidate row, col, or block then the other value can be placed in
    the blocked cell.  The other value can be placed in the other cell.  Look for rows with more
    than two missing values.  Check each empty cell to see only one of the missing values can be
    placed in it.  Check each value to see if there is only one cell where it can be placed."""
    if verbose:
        print("* check_rows")
    board = get_filled_cells(_board)

    all_rows_clans = partition.partition(board, partial(by_key, 'row'))
    for row_clan in _sort(all_rows_clans, key=partial(by_clan_key, 'row')):
        row = project(row_clan, 'row')
        board_row = clans.superstrict(_board, row)
        values_clan = get_missing_values(row_clan)

        if row_clan.cardinality == GRID_SIZE-1:
            # Row is missing only 1 value, remove row_clan from the board leaving target row_col
            row_col = sets.minus(board_row, row_clan)
            new_cells = clans.cross_union(row_col, values_clan)
            _board = get_new_board(_board, new_cells)
            continue

        # Get the set of candidate col/value pairs
        row_possible = clans.cross_union(values_clan,
                                         project(sets.minus(board_row, row_clan), 'col'))

        if row_clan.cardinality == GRID_SIZE-2:

            # The occupied_clan is the col/value pair that is a conflict for each col/value
            occupied_clan = project(clans.superstrict(board, row_possible), 'col', 'value')

            # If there are no conflicts neither value can be placed without checking entire board
            if not occupied_clan.is_empty:
                # ..remove occupied_clan col/value pairs from all possible
                new_possible = sets.minus(row_possible, occupied_clan)

                if new_possible.cardinality == 2:
                    # Of the 4 possibilities (2 values * 2 cols), 2 were removed, place remaining
                    new_cells = clans.cross_union(row, new_possible)
                    _board = get_new_board(_board, new_cells)
                    continue

                # 3 of the possibilities remain...
                occupied_col = project(occupied_clan, 'col')

                # Remove the occupied_col choices to get the first col/value pair
                col_value1 = clans.superstrict(new_possible, occupied_col)

                occupied_val = project(col_value1, 'value')

                # Remove the occupied_val choices to get the second col/value pair
                col_value2 = sets.minus(new_possible, clans.superstrict(new_possible, occupied_val))

                new_cells = clans.cross_union(row, col_value1)
                new_cells = sets.union(new_cells, clans.cross_union(row, col_value2))
                _board = get_new_board(_board, new_cells)
                continue

        # The occupied_clan is the row/col/value set that could be a conflict for values
        occupied_clan = clans.superstrict(board, values_clan)

        # If there are no conflicts then no cells can be placed
        if occupied_clan.is_empty:
            continue

        # Add row to row_possible for remaining checks
        all_possible = clans.cross_union(row_possible, row)

        # Get the set of conflicts...conflicting row/value + col/value
        conflict = sets.union(
            clans.superstrict(all_possible,
                              project(occupied_clan, 'value', 'col')),
            clans.superstrict(all_possible,
                              project(occupied_clan, 'value', 'row')))

        # Remove the conflicts from all_possible
        new_possible = sets.minus(all_possible, conflict)

        if new_possible.is_empty:
            continue  # All possible may have been excluded due to row/col conflicts

        # Otherwise...need to check for block (band+stack) conflicts too!!
        # ...if value exists in same block as element of all_possible

        # Add band/stack
        new_targets = clans.superstrict(BANDS_STACKS, project(new_possible, 'row', 'col'))
        new_possible3 = clans.functional_cross_union(new_targets, new_possible)
        occupied_clan2 = occupied_clan

        # Remove block (band+stack) conflicts
        new_possible4a = sets.minus(project(new_possible3, 'value', 'band', 'stack'),
                                    project(occupied_clan2, 'value', 'band', 'stack'))
        new_possible4 = clans.superstrict(new_possible3, new_possible4a)

        # Partition by row/col
        placed = 0
        candidates = partition.partition(new_possible4, partial(by_keys, 'row', 'col'))
        for candidate in _sort(candidates, key=partial(by_clan_key, 'col')):
            # If any row/col has only 1 candidate, place it
            if candidate.cardinality == 1:
                # Remove band/stack
                cell = project(candidate, 'row', 'col', 'value')
                _board = get_new_board(_board, cell)
                placed += 1

        if placed:
            continue

        # Partition by value
        candidates = partition.partition(new_possible4, partial(by_key, 'value'))
        for candidate in _sort(candidates, key=partial(by_clan_key, 'value')):
            # If any value fits in only 1 cell, place it
            if candidate.cardinality == 1:
                # Remove band/stack
                cell = project(candidate, 'row', 'col', 'value')
                _board = get_new_board(_board, cell)
    return _board
Пример #20
0
vocab_clan = import_csv(file)
print("vocab_clan:", vocab_clan)

# Superstriction(A, B) is a partial binary operation on sets. It is defined as A if A is a superset
# of B, otherwise it is undefined.
hello_relation = Set(Couplet('word', 'hello'), Couplet('language', 'English'),
                     Couplet('meaning', 'salutation'))
super_pos = sets.superstrict(hello_relation, Set(Couplet('language', 'English')))
super_neg = sets.superstrict(hello_relation, Set(Couplet('language', 'Mandarin')))
print(super_pos)
print(super_neg)

# By extending superstriction to clans, which are sets of sets (of Couplets), we can define a helpful
# mechanism to restrict vocab_clan to only those relations that contain particular values.
import algebraixlib.algebras.clans as clans
salutation_records_clan = clans.superstrict(vocab_clan, Set(Set(Couplet('meaning', 'salutation'))))
earth_records_clan = clans.superstrict(vocab_clan, Set(Set(Couplet('meaning', 'earth'))))
print("salutation_records_clan:", salutation_records_clan)
print("earth_records_clan:", earth_records_clan)

# By choosing an appropriate right-hand argument, our extended composition operation from earlier can
# model projection.
words_langs_clan = Set(Set(Couplet('word', 'word'), Couplet('language', 'language')))
print("words_langs_clan:", words_langs_clan)

# The relations.diag and clans.diag utility functions create a "diagonal" relation or clan,
# respectively, with simpler syntax.
assert words_langs_clan == clans.diag('word', 'language')

# Since the meaning of each set of records ('salutation') is invariant among the relations in
# salutation_records_clan, we can drop those Couplets. Note that the cardinality of the resulting
Пример #21
0
def check_rows(_board, try_harder=0):
    """Look for rows where there is only one missing value.  If any are found fill in the missing
    value.  Look for rows where there are two missing values.  If either missing value is blocked
    by the same value in the candidate row, col, or block then the other value can be placed in
    the blocked cell.  The other value can be placed in the other cell.  Look for rows with more
    than two missing values.  Check each empty cell to see only one of the missing values can be
    placed in it.  Check each value to see if there is only one cell where it can be placed."""
    if VERBOSE:
        print("* check_rows")
    board = get_filled_cells(_board)

    all_rows_clans = partition.partition(board, partial(by_key, 'row'))
    for row_clan in _SORT(all_rows_clans, key=partial(by_clan_key, 'row')):
        row = project(row_clan, 'row')
        board_row = clans.superstrict(_board, row)
        values_clan = get_missing_values(row_clan)

        if row_clan.cardinality == GRID_SIZE - 1:
            # Row is missing only 1 value, remove row_clan from the board leaving target row_col
            row_col = sets.minus(board_row, row_clan)
            new_cells = clans.cross_union(row_col, values_clan)
            _board = get_new_board(_board, new_cells)
            try_harder = 0
            continue

        # Get the set of candidate col/value pairs
        row_possible = clans.cross_union(values_clan,
                                         project(sets.minus(board_row, row_clan), 'col'))

        if row_clan.cardinality == GRID_SIZE - 2:

            # The occupied_clan is the col/value pair that is a conflict for each col/value
            occupied_clan = project(clans.superstrict(board, row_possible), 'col', 'value')

            # If there are no conflicts neither value can be placed without checking entire board
            if not occupied_clan.is_empty:
                # ..remove occupied_clan col/value pairs from all possible
                new_possible = sets.minus(row_possible, occupied_clan)

                if new_possible.cardinality == 2:
                    # Of the 4 possibilities (2 values * 2 cols), 2 were removed, place remaining
                    new_cells = clans.cross_union(row, new_possible)
                    _board = get_new_board(_board, new_cells)
                    try_harder = 0
                    continue

                # 3 of the possibilities remain...
                occupied_col = project(occupied_clan, 'col')

                # Remove the occupied_col choices to get the first col/value pair
                col_value1 = clans.superstrict(new_possible, occupied_col)

                occupied_val = project(col_value1, 'value')

                # Remove the occupied_val choices to get the second col/value pair
                col_value2 = sets.minus(new_possible, clans.superstrict(new_possible, occupied_val))

                new_cells = clans.cross_union(row, col_value1)
                new_cells = sets.union(new_cells, clans.cross_union(row, col_value2))
                _board = get_new_board(_board, new_cells)
                try_harder = 0
                continue

        # The occupied_clan is the row/col/value set that could be a conflict for values
        occupied_clan = clans.superstrict(board, values_clan)

        # If there are no conflicts then no cells can be placed
        if occupied_clan.is_empty:
            continue

        # Add row to row_possible for remaining checks
        all_possible = clans.cross_union(row_possible, row)

        # Get the set of conflicts...conflicting row/value + col/value
        conflict = sets.union(
            clans.superstrict(all_possible,
                              project(occupied_clan, 'value', 'col')),
            clans.superstrict(all_possible,
                              project(occupied_clan, 'value', 'row')))

        # Remove the conflicts from all_possible
        new_possible = sets.minus(all_possible, conflict)

        if new_possible.is_empty:
            continue  # All possible may have been excluded due to row/col conflicts

        # Otherwise...need to check for block (band+stack) conflicts too!!
        # ...if value exists in same block as element of all_possible

        # Add band/stack
        new_targets = clans.superstrict(BANDS_STACKS, project(new_possible, 'row', 'col'))
        new_possible3 = clans.cross_functional_union(new_targets, new_possible)
        occupied_clan2 = occupied_clan

        # Remove block (band+stack) conflicts
        new_possible4a = sets.minus(project(new_possible3, 'value', 'band', 'stack'),
                                    project(occupied_clan2, 'value', 'band', 'stack'))
        new_possible4 = clans.superstrict(new_possible3, new_possible4a)

        while True:
            candidates_updated = False
            # Partition by row/col
            placed = 0
            candidates = partition.partition(new_possible4, partial(by_keys, 'row', 'col'))
            for candidate in _SORT(candidates, key=partial(by_clan_key, 'col')):
                # If any row/col has only 1 candidate, place it
                if candidate.cardinality == 1:
                    # Remove band/stack
                    _board = get_new_board(_board, candidate)
                    try_harder = 0
                    placed += 1
            if placed:
                break

            # Partition by value
            candidates = partition.partition(new_possible4, partial(by_key, 'value'))
            for candidate in _SORT(candidates, key=partial(by_clan_key, 'value')):
                # If any value fits in only 1 cell, place it
                if candidate.cardinality == 1:
                    # Remove band/stack
                    _board = get_new_board(_board, candidate)
                    try_harder = 0
                else:  # If any value must be placed elsewhere, remove as candidate for this cell
                    if try_harder:
                        value = project(candidate, 'value')
                        # If this row of a sibling block must contain this value...
                        blocks = partition.partition(candidate, partial(by_keys, 'band', 'stack'))
                        if blocks.cardinality > 1:
                            for block_clan in _SORT(blocks,
                                                    key=partial(by_clan_keys, 'band', 'stack')):
                                block = project(block_clan, 'band', 'stack')
                                board_block = clans.superstrict(board, block)
                                if board_block.is_empty:
                                    continue

                                new_possible, conflict = get_block_candidates(board_block, board)
                                new_possible_value = clans.superstrict(new_possible, value)

                                if new_possible_value['row'].cardinality == 1:
                                    # Value must be placed in this block
                                    # ...other block candidates can be removed
                                    remove = sets.minus(candidate, block_clan)
                                    new_possible4 = sets.minus(new_possible4, remove)
                                    candidates_updated = True
            if not candidates_updated or not try_harder:
                break
    return _board
Пример #22
0
# Superstriction(A, B) is a partial binary operation on sets. It is defined as A if A is a superset
# of B, otherwise it is undefined.
hello_relation = Set(Couplet('word', 'hello'), Couplet('language', 'English'),
                     Couplet('meaning', 'salutation'))
super_pos = sets.superstrict(hello_relation,
                             Set(Couplet('language', 'English')))
super_neg = sets.superstrict(hello_relation,
                             Set(Couplet('language', 'Mandarin')))
print(super_pos)
print(super_neg)

# By extending superstriction to clans, which are sets of sets (of Couplets), we can define a
# helpful mechanism to restrict vocab_clan to only those relations that contain particular values.
import algebraixlib.algebras.clans as clans
salutation_records_clan = clans.superstrict(
    vocab_clan, Set(Set(Couplet('meaning', 'salutation'))))
earth_records_clan = clans.superstrict(vocab_clan,
                                       Set(Set(Couplet('meaning', 'earth'))))
print("salutation_records_clan:", salutation_records_clan)
print("earth_records_clan:", earth_records_clan)

# By choosing an appropriate right-hand argument, our extended composition operation from earlier
# can model projection.
words_langs_clan = Set(
    Set(Couplet('word', 'word'), Couplet('language', 'language')))
print("words_langs_clan:", words_langs_clan)

# The relations.diag and clans.diag utility functions create a "diagonal" relation or clan,
# respectively, with simpler syntax.
assert words_langs_clan == clans.diag('word', 'language')
Пример #23
0
# Get all nation names
# /regions/region/nation/name
nations = regions['nation']
print('regions[\'nation\']:\n' + mo_to_str(nations))

nation_names = nations['name']
print('nation_names:\n' + mo_to_str(nation_names))

# Get all nation names of a given region
# for $x in doc("regions.xml")/regions/region where $x/name='AMERICA' return $x/nation/name
from algebraixlib.algebras.clans import superstrict, from_dict
america_region_name = from_dict({'name': 'AMERICA'})
print('america_region_name:\n' + mo_to_str(america_region_name))

america_region = superstrict(regions, america_region_name)
print('america_region:\n' + mo_to_str(america_region))

america_nations_names = america_region['nation']['name']
print('america_nations_names:\n' + mo_to_str(america_nations_names))

# Get all region key and nation name pairs
# for $x in doc("regions.xml")/regions/region/nation/name return <pair>{$x/../../regionkey}{$x}</pair>
from algebraixlib.mathobjects import Set
from algebraixlib.algebras.clans import project, cross_union
from algebraixlib.algebras.sets import union
region_key_nation_name_pairs_accumulator = Set()
for region in regions:
    region_key = project(Set(region), 'regionkey')
    print('region_key:\n' + mo_to_str(region_key))