Skip to content

Commit

Permalink
Use dict of bounds instead of list
Browse files Browse the repository at this point in the history
More efficient way to store the possible indices of a transformation.

Contributes: #34
  • Loading branch information
stephanzwicknagl committed Apr 22, 2024
1 parent 350651f commit b1813a7
Show file tree
Hide file tree
Showing 11 changed files with 46 additions and 35 deletions.
3 changes: 2 additions & 1 deletion backend/src/viasp/asp/justify.py
Expand Up @@ -8,7 +8,7 @@

from clingo.ast import AST, ASTType

from .reify import ProgramAnalyzer, reify_recursion_transformation
from .reify import ProgramAnalyzer, reify_recursion_transformation, LiteralWrapper
from .recursion import RecursionReasoner
from .utils import insert_atoms_into_nodes, identify_reasons, calculate_spacing_factor
from ..shared.model import Node, RuleContainer, Transformation, SymbolIdentifier
Expand Down Expand Up @@ -233,6 +233,7 @@ def get_recursion_subgraph(
clear_temp_names=analyzer.clear_temp_names,
conflict_free_model=analyzer.get_conflict_free_model(),
conflict_free_iterindex=analyzer.get_conflict_free_iterindex(),
conflict_free_derivable=analyzer.get_conflict_free_derivable()
)
justification_program += "\n".join(map(str, justifier_rules))
justification_program += f"\n{model_str}(@new())."
Expand Down
15 changes: 14 additions & 1 deletion backend/src/viasp/asp/reify.py
Expand Up @@ -232,6 +232,13 @@ def get_conflict_free_iterindex(self):
transformations.
"""
return self._get_conflict_free_version_of_name("n")

def get_conflict_free_derivable(self):
"""
For use in generation of subgraphs at recursive
transformations.
"""
return self._get_conflict_free_version_of_name("derivable")

def clear_temp_names(self):
self.temp_names = set()
Expand Down Expand Up @@ -542,7 +549,7 @@ def primary_sort_program_by_dependencies(
def get_index_mapping_for_adjacent_topological_sorts(
self,
sorted_program: List[RuleContainer]
) -> Dict[int, List[int]]:
) -> Dict[int, Dict[str, int]]:
if self.dependency_graph is None:
raise ValueError(
"Dependency graph has not been created yet. Call primary_sort_program_by_dependencies first."
Expand Down Expand Up @@ -783,6 +790,7 @@ class ProgramReifierForRecursions(ProgramReifier):
def __init__(self, *args, **kwargs):
self.model_str: str = kwargs.pop("conflict_free_model", "model")
self.n_str: str = kwargs.pop("conflict_free_iterindex", "n")
self.derivable_str: str = kwargs.pop("conflict_free_derivable", "derivable")
super().__init__(*args, **kwargs)

def visit_Rule(self, rule: ast.Rule) -> List[AST]: # type: ignore
Expand Down Expand Up @@ -822,6 +830,11 @@ def visit_Rule(self, rule: ast.Rule) -> List[AST]: # type: ignore
dep_atm = ast.SymbolicAtom(dep_fun)
conditions.append(ast.Literal(loc, ast.Sign.Negation, dep_atm))

# # Append dependant wrapped in derivable
# derivable_fun = ast.Function(loc, self.derivable_str, [dependant], 0)
# derivable_atm = ast.SymbolicAtom(derivable_fun)
# conditions.append(ast.Literal(loc, ast.Sign.NoSign, derivable_atm))

new_rules.extend([
ast.Rule(rule.location, new_head, conditions)
for new_head in new_head_s
Expand Down
12 changes: 6 additions & 6 deletions backend/src/viasp/asp/utils.py
Expand Up @@ -216,20 +216,20 @@ def topological_sort(g: nx.DiGraph, rules: Sequence[ast.Rule]) -> List: # type:

def find_index_mapping_for_adjacent_topological_sorts(
g: nx.DiGraph,
sorted_program: List[RuleContainer]) -> Dict[int, List[int]]:
new_indices: Dict[int, List[int]] = {}
sorted_program: List[RuleContainer]) -> Dict[int, Dict[str, int]]:
new_indices: Dict[int, Dict[str, int]] = {}
for i, rule_container in enumerate(sorted_program):
lower_bound = max([sorted_program.index(u) for u in g.predecessors(rule_container)]+[-1])
upper_bound = min([sorted_program.index(u) for u in g.successors(rule_container)]+[len(sorted_program)])
new_indices[i] = list(range(lower_bound+1,
upper_bound))
new_indices[i].remove(sorted_program.index(rule_container))
new_indices[i] = {"lower_bound": lower_bound+1, "upper_bound": upper_bound-1}
return new_indices


def register_adjacent_sorts(primary_sort: List[Transformation], primary_hash: str) -> None:
for transformation in primary_sort:
for new_index in transformation.adjacent_sort_indices:
for new_index in range(transformation.adjacent_sort_indices["lower_bound"], transformation.adjacent_sort_indices["upper_bound"]+1):
if new_index == transformation.id:
continue
new_sort_rules = [t.rules for t in primary_sort]
new_sort_rules.remove(transformation.rules)
new_sort_rules.insert(new_index, transformation.rules)
Expand Down
2 changes: 1 addition & 1 deletion backend/src/viasp/server/blueprints/api.py
Expand Up @@ -167,8 +167,8 @@ def show_selected_models():
marked_models = wrap_marked_models(marked_models,
analyzer.get_conflict_free_showTerm())
if analyzer.will_work():
set_primary_sort(analyzer)
save_analyzer_values(analyzer)
set_primary_sort(analyzer)

return "ok", 200

Expand Down
2 changes: 1 addition & 1 deletion backend/src/viasp/server/database.py
Expand Up @@ -305,7 +305,6 @@ def save_many_sorts(self, sorts: List[Tuple[str, List[Transformation],

def save_sort(self, hash: str, sort: List[Transformation],
encoding_id: str):
print(f"Save sort {hash}\n{sort}", flush=True)
self.cursor.execute(
"""
INSERT OR REPLACE INTO graphs (hash, data, sort, encoding_id) VALUES (?, ?, ?, ?)
Expand Down Expand Up @@ -635,6 +634,7 @@ def set_current_graph(hash: str) -> str:

def save_recursive_transformations_hashes(transformation_hashes: Set[str]):
encoding_id = get_or_create_encoding_id()
print(f"Saving recursive, {transformation_hashes}", flush=True)
get_database().save_recursive_transformations_hashes(
transformation_hashes, encoding_id)

Expand Down
2 changes: 1 addition & 1 deletion backend/src/viasp/shared/model.py
Expand Up @@ -110,7 +110,7 @@ def __repr__(self):
class Transformation:
id: int = field(hash=True)
rules: RuleContainer = field(default_factory=RuleContainer, hash=True)
adjacent_sort_indices: List[int] = field(default_factory=list, hash=False)
adjacent_sort_indices: Dict[str, int] = field(default_factory=dict, hash=False)
hash: str = field(default="", hash=True)

def __post_init__(self):
Expand Down
5 changes: 3 additions & 2 deletions backend/test/api/test_query.py
Expand Up @@ -65,8 +65,9 @@ def test_query_multiple_sorts(client_with_a_graph):
switch_from, switch_to = (None, None)
for _ in range(3):
for t in sample(sorted_program, k=len(sorted_program)):
if len(t.adjacent_sort_indices)>0:
switch_from, switch_to= (t.id, t.adjacent_sort_indices[0])
if t.adjacent_sort_indices["upper_bound"] - t.adjacent_sort_indices["lower_bound"]>0:
switch_to = sample(range(t.adjacent_sort_indices["lower_bound"], t.adjacent_sort_indices["upper_bound"]+1), 1)[0]
switch_from = t.id
break
if switch_from is not None:
res = client.post("graph/sorts", json={"old_index": switch_from, "new_index": switch_to})
Expand Down
21 changes: 11 additions & 10 deletions backend/test/test_graph_utils.py
Expand Up @@ -35,9 +35,10 @@ def test_adjacent_sorts(app_context):

adjacent_sorts = analyzer.get_index_mapping_for_adjacent_topological_sorts([t.rules for t in sorted])
assert len(adjacent_sorts.keys()) == 2
assert adjacent_sorts[0] == [1]
assert adjacent_sorts[1] == [0]

assert adjacent_sorts[0]["lower_bound"] == 0
assert adjacent_sorts[0]["upper_bound"] == 1
assert adjacent_sorts[1]["lower_bound"] == 0
assert adjacent_sorts[1]["upper_bound"] == 1

def test_adjacent_sorts_2(app_context):
rules = ["x:-y.",
Expand All @@ -52,10 +53,10 @@ def test_adjacent_sorts_2(app_context):

adjacent_sorts = analyzer.get_index_mapping_for_adjacent_topological_sorts([t.rules for t in sorted])
assert len(adjacent_sorts) == 7
assert adjacent_sorts[0] == []
assert adjacent_sorts[1] == [2,3,4,5,6]
assert adjacent_sorts[2] == [1]
assert adjacent_sorts[3] == [4,5,6]
assert adjacent_sorts[4] == [3,5]
assert adjacent_sorts[5] == [3,4]
assert adjacent_sorts[6] == []
assert list(adjacent_sorts[0].values()) == [0,0]
assert list(adjacent_sorts[1].values()) == [1,6]
assert list(adjacent_sorts[2].values()) == [1,2]
assert list(adjacent_sorts[3].values()) == [3,6]
assert list(adjacent_sorts[4].values()) == [3,5]
assert list(adjacent_sorts[5].values()) == [3,5]
assert list(adjacent_sorts[6].values()) == [6,6]
3 changes: 2 additions & 1 deletion frontend/src/lib/components/Row.react.js
Expand Up @@ -106,8 +106,9 @@ export class RowTemplate extends React.Component {
const background = rowShading;
const thisCanDrop =
transformationDropIndices !== null
? transformationDropIndices.indexOf(transformation.id) !== -1
? transformationDropIndices.lower_bound <= (transformation.id) && transformation.id <= transformationDropIndices.upper_bound
: false;


const containerStyle = {
position: 'relative',
Expand Down
11 changes: 1 addition & 10 deletions frontend/src/lib/main/ViaspDash.react.js
Expand Up @@ -90,7 +90,7 @@ function GraphContainer(props) {
function onMoveEnd(newList, movedItem, oldIndex, newIndex) {
dispatchTransformation(setTransformationDropIndices(null));

if (transformationDropIndices.indexOf(newIndex) !== -1) {
if (transformationDropIndices.lower_bound <= newIndex && newIndex <= transformationDropIndices.upper_bound) {
setShownRecursion([]);
setHighlightedSymbol([]);
dispatchTransformation(reorderTransformation(oldIndex, newIndex));
Expand All @@ -101,20 +101,12 @@ function GraphContainer(props) {
);
})
.then((r) => {
console.log(r)
dispatchTransformation(setCurrentSort(r.hash));
});
return;
}
}

// function onDragStart(draggedItem) {
// console.log('draggedItem', draggedItem)
// if (draggedItem) {
// dispatchTransformation(setTransformationDropIndices(draggedItem.transformation.adjacent_sort_indices));
// }
// }

React.useEffect(() => {
console.log("transformations changed", transformations)
}, [transformations])
Expand All @@ -132,7 +124,6 @@ function GraphContainer(props) {
template={RowTemplate}
list={transformations}
onMoveEnd={onMoveEnd}
// onDragStart={onDragStart}
container={() => scrollContainer.current}
autoScrollRegionSize={200}
padding={0}
Expand Down
5 changes: 4 additions & 1 deletion frontend/src/lib/types/propTypes.js
Expand Up @@ -28,7 +28,10 @@ export const TRANSFORMATION = PropTypes.exact({
_type: PropTypes.oneOf(['Transformation']),
id: PropTypes.number,
rules: RULECONTAINER,
adjacent_sort_indices: PropTypes.array,
adjacent_sort_indices: PropTypes.exact({
lower_bound: PropTypes.number,
upper_bound: PropTypes.number
}),
hash: PropTypes.string
})
export const TRANSFORMATIONWRAPPER = PropTypes.exact({
Expand Down

0 comments on commit b1813a7

Please sign in to comment.