diff --git a/.gitignore b/.gitignore index 6ec38dd..35855cd 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,4 @@ node_modules package-lock.json test*.lp yarn-error.log +build diff --git a/asp/_all.lp b/asp/_all.lp index 3a029a7..b2d54c4 100644 --- a/asp/_all.lp +++ b/asp/_all.lp @@ -1,12 +1,24 @@ % Collection of ASP files that can be used to quickly run an experiment. % E.g. clingo asp/_all.lp test.lp -#include "asp/define.lp". -#include "asp/generate.lp". -#include "asp/hard.lp". -#include "asp/soft.lp". -#include "asp/weights.lp". -#include "asp/assign_weights.lp". -#include "asp/optimize.lp". -#include "asp/output.lp". -% #include "asp/topk-lua.lp". +% #include "asp/define.lp". +% #include "asp/generate.lp". +% #include "asp/hard.lp". +% #include "asp/soft.lp". +% #include "asp/weights.lp". +% #include "asp/assign_weights.lp". +% #include "asp/optimize.lp". +% #include "asp/output.lp". +% % #include "asp/topk-lua.lp". + +#include "define.lp". +#include "generate.lp". +#include "hard.lp". +#include "soft.lp". +#include "weights.lp". +#include "assign_weights.lp". +#include "optimize_draco.lp". +#include "output.lp". +#include "compare.lp". +#include "assign_compare_weights.lp". +#include "compare_weights.lp". diff --git a/asp/assign_compare_weights.lp b/asp/assign_compare_weights.lp new file mode 100644 index 0000000..b6303a8 --- /dev/null +++ b/asp/assign_compare_weights.lp @@ -0,0 +1,139 @@ +%% GENERATED FILE. DO NOT EDIT. + +compare_weight(edit_area_bar,edit_area_bar_weight). +compare_weight(edit_area_line,edit_area_line_weight). +compare_weight(edit_area_point,edit_area_point_weight). +compare_weight(edit_area_text,edit_area_text_weight). +compare_weight(edit_area_tick,edit_area_tick_weight). +compare_weight(edit_bar_line,edit_bar_line_weight). +compare_weight(edit_bar_point,edit_bar_point_weight). +compare_weight(edit_bar_text,edit_bar_text_weight). +compare_weight(edit_bar_tick,edit_bar_tick_weight). +compare_weight(edit_line_point,edit_line_point_weight). +compare_weight(edit_line_text,edit_line_text_weight). +compare_weight(edit_line_tick,edit_line_tick_weight). +compare_weight(edit_point_text,edit_point_text_weight). +compare_weight(edit_point_tick,edit_point_tick_weight). +compare_weight(edit_text_tick,edit_text_tick_weight). +compare_weight(edit_scale,edit_scale_weight). +compare_weight(edit_sort,edit_sort_weight). +compare_weight(edit_bin,edit_bin_weight). +compare_weight(edit_aggregate,edit_aggregate_weight). +compare_weight(edit_add_filter,edit_add_filter_weight). +compare_weight(edit_remove_filter,edit_remove_filter_weight). +compare_weight(edit_modify_filter,edit_modify_filter_weight). +compare_weight(edit_add_x,edit_add_x_weight). +compare_weight(edit_add_y,edit_add_y_weight). +compare_weight(edit_add_color,edit_add_color_weight). +compare_weight(edit_add_shape,edit_add_shape_weight). +compare_weight(edit_add_size,edit_add_size_weight). +compare_weight(edit_add_row,edit_add_row_weight). +compare_weight(edit_add_column,edit_add_column_weight). +compare_weight(edit_add_text,edit_add_text_weight). +compare_weight(edit_add_x_count,edit_add_x_count_weight). +compare_weight(edit_add_y_count,edit_add_y_count_weight). +compare_weight(edit_add_color_count,edit_add_color_count_weight). +compare_weight(edit_add_shape_count,edit_add_shape_count_weight). +compare_weight(edit_add_size_count,edit_add_size_count_weight). +compare_weight(edit_add_row_count,edit_add_row_count_weight). +compare_weight(edit_add_column_count,edit_add_column_count_weight). +compare_weight(edit_add_text_count,edit_add_text_count_weight). +compare_weight(edit_remove_x_count,edit_remove_x_count_weight). +compare_weight(edit_remove_y_count,edit_remove_y_count_weight). +compare_weight(edit_remove_color_count,edit_remove_color_count_weight). +compare_weight(edit_remove_shape_count,edit_remove_shape_count_weight). +compare_weight(edit_remove_size_count,edit_remove_size_count_weight). +compare_weight(edit_remove_row_count,edit_remove_row_count_weight). +compare_weight(edit_remove_column_count,edit_remove_column_count_weight). +compare_weight(edit_remove_text_count,edit_remove_text_count_weight). +compare_weight(edit_remove_x,edit_remove_x_weight). +compare_weight(edit_remove_y,edit_remove_y_weight). +compare_weight(edit_remove_color,edit_remove_color_weight). +compare_weight(edit_remove_shape,edit_remove_shape_weight). +compare_weight(edit_remove_size,edit_remove_size_weight). +compare_weight(edit_remove_row,edit_remove_row_weight). +compare_weight(edit_remove_column,edit_remove_column_weight). +compare_weight(edit_remove_text,edit_remove_text_weight). +compare_weight(edit_modify_x,edit_modify_x_weight). +compare_weight(edit_modify_y,edit_modify_y_weight). +compare_weight(edit_modify_color,edit_modify_color_weight). +compare_weight(edit_modify_shape,edit_modify_shape_weight). +compare_weight(edit_modify_size,edit_modify_size_weight). +compare_weight(edit_modify_row,edit_modify_row_weight). +compare_weight(edit_modify_column,edit_modify_column_weight). +compare_weight(edit_modify_text,edit_modify_text_weight). +compare_weight(edit_modify_x_add_count,edit_modify_x_add_count_weight). +compare_weight(edit_modify_y_add_count,edit_modify_y_add_count_weight). +compare_weight(edit_modify_color_add_count,edit_modify_color_add_count_weight). +compare_weight(edit_modify_shape_add_count,edit_modify_shape_add_count_weight). +compare_weight(edit_modify_size_add_count,edit_modify_size_add_count_weight). +compare_weight(edit_modify_row_add_count,edit_modify_row_add_count_weight). +compare_weight(edit_modify_column_add_count,edit_modify_column_add_count_weight). +compare_weight(edit_modify_text_add_count,edit_modify_text_add_count_weight). +compare_weight(edit_modify_x_remove_count,edit_modify_x_remove_count_weight). +compare_weight(edit_modify_y_remove_count,edit_modify_y_remove_count_weight). +compare_weight(edit_modify_color_remove_count,edit_modify_color_remove_count_weight). +compare_weight(edit_modify_shape_remove_count,edit_modify_shape_remove_count_weight). +compare_weight(edit_modify_size_remove_count,edit_modify_size_remove_count_weight). +compare_weight(edit_modify_row_remove_count,edit_modify_row_remove_count_weight). +compare_weight(edit_modify_column_remove_count,edit_modify_column_remove_count_weight). +compare_weight(edit_modify_text_remove_count,edit_modify_text_remove_count_weight). +compare_weight(edit_move_x_row,edit_move_x_row_weight). +compare_weight(edit_move_x_column,edit_move_x_column_weight). +compare_weight(edit_move_x_size,edit_move_x_size_weight). +compare_weight(edit_move_x_shape,edit_move_x_shape_weight). +compare_weight(edit_move_x_color,edit_move_x_color_weight). +compare_weight(edit_move_x_y,edit_move_x_y_weight). +compare_weight(edit_move_x_text,edit_move_x_text_weight). +compare_weight(edit_move_y_row,edit_move_y_row_weight). +compare_weight(edit_move_y_column,edit_move_y_column_weight). +compare_weight(edit_move_y_size,edit_move_y_size_weight). +compare_weight(edit_move_y_shape,edit_move_y_shape_weight). +compare_weight(edit_move_y_color,edit_move_y_color_weight). +compare_weight(edit_move_y_x,edit_move_y_x_weight). +compare_weight(edit_move_y_text,edit_move_y_text_weight). +compare_weight(edit_move_color_row,edit_move_color_row_weight). +compare_weight(edit_move_color_column,edit_move_color_column_weight). +compare_weight(edit_move_color_size,edit_move_color_size_weight). +compare_weight(edit_move_color_shape,edit_move_color_shape_weight). +compare_weight(edit_move_color_y,edit_move_color_y_weight). +compare_weight(edit_move_color_x,edit_move_color_x_weight). +compare_weight(edit_move_color_text,edit_move_color_text_weight). +compare_weight(edit_move_shape_row,edit_move_shape_row_weight). +compare_weight(edit_move_shape_column,edit_move_shape_column_weight). +compare_weight(edit_move_shape_size,edit_move_shape_size_weight). +compare_weight(edit_move_shape_color,edit_move_shape_color_weight). +compare_weight(edit_move_shape_y,edit_move_shape_y_weight). +compare_weight(edit_move_shape_x,edit_move_shape_x_weight). +compare_weight(edit_move_shape_text,edit_move_shape_text_weight). +compare_weight(edit_move_size_row,edit_move_size_row_weight). +compare_weight(edit_move_size_column,edit_move_size_column_weight). +compare_weight(edit_move_size_shape,edit_move_size_shape_weight). +compare_weight(edit_move_size_color,edit_move_size_color_weight). +compare_weight(edit_move_size_y,edit_move_size_y_weight). +compare_weight(edit_move_size_x,edit_move_size_x_weight). +compare_weight(edit_move_size_text,edit_move_size_text_weight). +compare_weight(edit_move_text_row,edit_move_text_row_weight). +compare_weight(edit_move_text_column,edit_move_text_column_weight). +compare_weight(edit_move_text_shape,edit_move_text_shape_weight). +compare_weight(edit_move_text_color,edit_move_text_color_weight). +compare_weight(edit_move_text_y,edit_move_text_y_weight). +compare_weight(edit_move_text_x,edit_move_text_x_weight). +compare_weight(edit_move_text_size,edit_move_text_size_weight). +compare_weight(edit_move_column_row,edit_move_column_row_weight). +compare_weight(edit_move_column_size,edit_move_column_size_weight). +compare_weight(edit_move_column_shape,edit_move_column_shape_weight). +compare_weight(edit_move_column_color,edit_move_column_color_weight). +compare_weight(edit_move_column_y,edit_move_column_y_weight). +compare_weight(edit_move_column_x,edit_move_column_x_weight). +compare_weight(edit_move_column_text,edit_move_column_text_weight). +compare_weight(edit_move_row_column,edit_move_row_column_weight). +compare_weight(edit_move_row_size,edit_move_row_size_weight). +compare_weight(edit_move_row_shape,edit_move_row_shape_weight). +compare_weight(edit_move_row_color,edit_move_row_color_weight). +compare_weight(edit_move_row_y,edit_move_row_y_weight). +compare_weight(edit_move_row_x,edit_move_row_x_weight). +compare_weight(edit_move_row_text,edit_move_row_text_weight). +compare_weight(edit_swap_x_y,edit_swap_x_y_weight). +compare_weight(edit_swap_row_column,edit_swap_row_column_weight). +compare_weight(edit_ceiling,edit_ceiling_weight). diff --git a/asp/assign_weights.lp b/asp/assign_weights.lp index b292c42..b470973 100644 --- a/asp/assign_weights.lp +++ b/asp/assign_weights.lp @@ -13,7 +13,9 @@ soft_weight(same_field_2,same_field_2_weight). soft_weight(same_field_gte3,same_field_gte3_weight). soft_weight(count_twice,count_twice_weight). soft_weight(shape_cardinality,shape_cardinality_weight). +soft_weight(string_non_nominal,string_non_nominal_weight). soft_weight(number_nominal,number_nominal_weight). +soft_weight(number_high_cardinality_ordinal,number_high_cardinality_ordinal_weight). soft_weight(bin_cardinality,bin_cardinality_weight). soft_weight(quant_bin,quant_bin_weight). soft_weight(agg_dim,agg_dim_weight). @@ -24,6 +26,7 @@ soft_weight(aggregate_group_by_raw,aggregate_group_by_raw_weight). soft_weight(x_y_raw,x_y_raw_weight). soft_weight(log,log_weight). soft_weight(zero,zero_weight). +soft_weight(zero_bin,zero_bin_weight). soft_weight(zero_size,zero_size_weight). soft_weight(zero_positional,zero_positional_weight). soft_weight(zero_skew,zero_skew_weight). @@ -149,3 +152,5 @@ soft_weight(summary_discrete_row,summary_discrete_row_weight). soft_weight(summary_discrete_column,summary_discrete_column_weight). soft_weight(stack_zero,stack_zero_weight). soft_weight(stack_normalize,stack_normalize_weight). +soft_weight(x_y_fields_order,x_y_fields_order_weight). +soft_weight(rect_no_agg,rect_no_agg_weight). diff --git a/asp/compare.lp b/asp/compare.lp new file mode 100644 index 0000000..d624d77 --- /dev/null +++ b/asp/compare.lp @@ -0,0 +1,165 @@ +%% FILE GENERATED BY graphscapeToAsp.js, DO NOT MODIFY %% +comparable(V1,V2) :- view(V1), base(V1), view(V2), V1 != V2. +% MARK EDITS +compare(edit_area_bar,V1,V2,area,bar) :- comparable(V1,V2), mark(V1,area), mark(V2,bar). +compare(edit_area_bar,V1,V2,bar,area) :- comparable(V1,V2), mark(V1,bar), mark(V2,area). +compare(edit_area_line,V1,V2,area,line) :- comparable(V1,V2), mark(V1,area), mark(V2,line). +compare(edit_area_line,V1,V2,line,area) :- comparable(V1,V2), mark(V1,line), mark(V2,area). +compare(edit_area_point,V1,V2,area,point) :- comparable(V1,V2), mark(V1,area), mark(V2,point). +compare(edit_area_point,V1,V2,point,area) :- comparable(V1,V2), mark(V1,point), mark(V2,area). +compare(edit_area_text,V1,V2,area,text) :- comparable(V1,V2), mark(V1,area), mark(V2,text). +compare(edit_area_text,V1,V2,text,area) :- comparable(V1,V2), mark(V1,text), mark(V2,area). +compare(edit_area_tick,V1,V2,area,tick) :- comparable(V1,V2), mark(V1,area), mark(V2,tick). +compare(edit_area_tick,V1,V2,tick,area) :- comparable(V1,V2), mark(V1,tick), mark(V2,area). +compare(edit_bar_line,V1,V2,bar,line) :- comparable(V1,V2), mark(V1,bar), mark(V2,line). +compare(edit_bar_line,V1,V2,line,bar) :- comparable(V1,V2), mark(V1,line), mark(V2,bar). +compare(edit_bar_point,V1,V2,bar,point) :- comparable(V1,V2), mark(V1,bar), mark(V2,point). +compare(edit_bar_point,V1,V2,point,bar) :- comparable(V1,V2), mark(V1,point), mark(V2,bar). +compare(edit_bar_text,V1,V2,bar,text) :- comparable(V1,V2), mark(V1,bar), mark(V2,text). +compare(edit_bar_text,V1,V2,text,bar) :- comparable(V1,V2), mark(V1,text), mark(V2,bar). +compare(edit_bar_tick,V1,V2,bar,tick) :- comparable(V1,V2), mark(V1,bar), mark(V2,tick). +compare(edit_bar_tick,V1,V2,tick,bar) :- comparable(V1,V2), mark(V1,tick), mark(V2,bar). +compare(edit_line_point,V1,V2,line,point) :- comparable(V1,V2), mark(V1,line), mark(V2,point). +compare(edit_line_point,V1,V2,point,line) :- comparable(V1,V2), mark(V1,point), mark(V2,line). +compare(edit_line_text,V1,V2,line,text) :- comparable(V1,V2), mark(V1,line), mark(V2,text). +compare(edit_line_text,V1,V2,text,line) :- comparable(V1,V2), mark(V1,text), mark(V2,line). +compare(edit_line_tick,V1,V2,line,tick) :- comparable(V1,V2), mark(V1,line), mark(V2,tick). +compare(edit_line_tick,V1,V2,tick,line) :- comparable(V1,V2), mark(V1,tick), mark(V2,line). +compare(edit_point_text,V1,V2,point,text) :- comparable(V1,V2), mark(V1,point), mark(V2,text). +compare(edit_point_text,V1,V2,text,point) :- comparable(V1,V2), mark(V1,text), mark(V2,point). +compare(edit_point_tick,V1,V2,point,tick) :- comparable(V1,V2), mark(V1,point), mark(V2,tick). +compare(edit_point_tick,V1,V2,tick,point) :- comparable(V1,V2), mark(V1,tick), mark(V2,point). +compare(edit_text_tick,V1,V2,text,tick) :- comparable(V1,V2), mark(V1,text), mark(V2,tick). +compare(edit_text_tick,V1,V2,tick,text) :- comparable(V1,V2), mark(V1,tick), mark(V2,text). + + +% ENCODING EDITS +compare(edit_add_x,V1,V2,E2,F2,add,none,x) :- not compare(edit_add_x_count,V1,V2,E2,count,add,none,x), not compare(_,V1,V2,_,E2,move,_,x), comparable(V1,V2), channel(V2,E2,x), field(V2,E2,F2), not channel(V1,_,x). +compare(edit_add_y,V1,V2,E2,F2,add,none,y) :- not compare(edit_add_y_count,V1,V2,E2,count,add,none,y), not compare(_,V1,V2,_,E2,move,_,y), comparable(V1,V2), channel(V2,E2,y), field(V2,E2,F2), not channel(V1,_,y). +compare(edit_add_color,V1,V2,E2,F2,add,none,color) :- not compare(edit_add_color_count,V1,V2,E2,count,add,none,color), not compare(_,V1,V2,_,E2,move,_,color), comparable(V1,V2), channel(V2,E2,color), field(V2,E2,F2), not channel(V1,_,color). +compare(edit_add_shape,V1,V2,E2,F2,add,none,shape) :- not compare(edit_add_shape_count,V1,V2,E2,count,add,none,shape), not compare(_,V1,V2,_,E2,move,_,shape), comparable(V1,V2), channel(V2,E2,shape), field(V2,E2,F2), not channel(V1,_,shape). +compare(edit_add_size,V1,V2,E2,F2,add,none,size) :- not compare(edit_add_size_count,V1,V2,E2,count,add,none,size), not compare(_,V1,V2,_,E2,move,_,size), comparable(V1,V2), channel(V2,E2,size), field(V2,E2,F2), not channel(V1,_,size). +compare(edit_add_row,V1,V2,E2,F2,add,none,row) :- not compare(edit_add_row_count,V1,V2,E2,count,add,none,row), not compare(_,V1,V2,_,E2,move,_,row), comparable(V1,V2), channel(V2,E2,row), field(V2,E2,F2), not channel(V1,_,row). +compare(edit_add_column,V1,V2,E2,F2,add,none,column) :- not compare(edit_add_column_count,V1,V2,E2,count,add,none,column), not compare(_,V1,V2,_,E2,move,_,column), comparable(V1,V2), channel(V2,E2,column), field(V2,E2,F2), not channel(V1,_,column). +compare(edit_add_text,V1,V2,E2,F2,add,none,text) :- not compare(edit_add_text_count,V1,V2,E2,count,add,none,text), not compare(_,V1,V2,_,E2,move,_,text), comparable(V1,V2), channel(V2,E2,text), field(V2,E2,F2), not channel(V1,_,text). +compare(edit_add_x_count,V1,V2,E2,count,add,none,x) :- not compare(_,V1,V2,_,E2,move,_,x), comparable(V1,V2), channel(V2,E2,x), aggregate(V2,E2,count), not channel(V1,_,x). +compare(edit_add_y_count,V1,V2,E2,count,add,none,y) :- not compare(_,V1,V2,_,E2,move,_,y), comparable(V1,V2), channel(V2,E2,y), aggregate(V2,E2,count), not channel(V1,_,y). +compare(edit_add_color_count,V1,V2,E2,count,add,none,color) :- not compare(_,V1,V2,_,E2,move,_,color), comparable(V1,V2), channel(V2,E2,color), aggregate(V2,E2,count), not channel(V1,_,color). +compare(edit_add_shape_count,V1,V2,E2,count,add,none,shape) :- not compare(_,V1,V2,_,E2,move,_,shape), comparable(V1,V2), channel(V2,E2,shape), aggregate(V2,E2,count), not channel(V1,_,shape). +compare(edit_add_size_count,V1,V2,E2,count,add,none,size) :- not compare(_,V1,V2,_,E2,move,_,size), comparable(V1,V2), channel(V2,E2,size), aggregate(V2,E2,count), not channel(V1,_,size). +compare(edit_add_row_count,V1,V2,E2,count,add,none,row) :- not compare(_,V1,V2,_,E2,move,_,row), comparable(V1,V2), channel(V2,E2,row), aggregate(V2,E2,count), not channel(V1,_,row). +compare(edit_add_column_count,V1,V2,E2,count,add,none,column) :- not compare(_,V1,V2,_,E2,move,_,column), comparable(V1,V2), channel(V2,E2,column), aggregate(V2,E2,count), not channel(V1,_,column). +compare(edit_add_text_count,V1,V2,E2,count,add,none,text) :- not compare(_,V1,V2,_,E2,move,_,text), comparable(V1,V2), channel(V2,E2,text), aggregate(V2,E2,count), not channel(V1,_,text). +compare(edit_remove_x_count,V1,V2,E1,count,remove,x,none) :- not compare(_,V1,V2,E1,_,move,x,_), comparable(V1,V2), channel(V1,E1,x), aggregate(V1,E1,count), not channel(V2,_,x). +compare(edit_remove_y_count,V1,V2,E1,count,remove,y,none) :- not compare(_,V1,V2,E1,_,move,y,_), comparable(V1,V2), channel(V1,E1,y), aggregate(V1,E1,count), not channel(V2,_,y). +compare(edit_remove_color_count,V1,V2,E1,count,remove,color,none) :- not compare(_,V1,V2,E1,_,move,color,_), comparable(V1,V2), channel(V1,E1,color), aggregate(V1,E1,count), not channel(V2,_,color). +compare(edit_remove_shape_count,V1,V2,E1,count,remove,shape,none) :- not compare(_,V1,V2,E1,_,move,shape,_), comparable(V1,V2), channel(V1,E1,shape), aggregate(V1,E1,count), not channel(V2,_,shape). +compare(edit_remove_size_count,V1,V2,E1,count,remove,size,none) :- not compare(_,V1,V2,E1,_,move,size,_), comparable(V1,V2), channel(V1,E1,size), aggregate(V1,E1,count), not channel(V2,_,size). +compare(edit_remove_row_count,V1,V2,E1,count,remove,row,none) :- not compare(_,V1,V2,E1,_,move,row,_), comparable(V1,V2), channel(V1,E1,row), aggregate(V1,E1,count), not channel(V2,_,row). +compare(edit_remove_column_count,V1,V2,E1,count,remove,column,none) :- not compare(_,V1,V2,E1,_,move,column,_), comparable(V1,V2), channel(V1,E1,column), aggregate(V1,E1,count), not channel(V2,_,column). +compare(edit_remove_text_count,V1,V2,E1,count,remove,text,none) :- not compare(_,V1,V2,E1,_,move,text,_), comparable(V1,V2), channel(V1,E1,text), aggregate(V1,E1,count), not channel(V2,_,text). +compare(edit_remove_x,V1,V2,E1,F1,remove,x,none) :- not compare(edit_remove_x_count,V1,V2,E1,count,remove,x,none), not compare(_,V1,V2,E1,_,move,x,_), comparable(V1,V2), channel(V1,E1,x), field(V1,E1,F1), not channel(V2,_,x). +compare(edit_remove_y,V1,V2,E1,F1,remove,y,none) :- not compare(edit_remove_y_count,V1,V2,E1,count,remove,y,none), not compare(_,V1,V2,E1,_,move,y,_), comparable(V1,V2), channel(V1,E1,y), field(V1,E1,F1), not channel(V2,_,y). +compare(edit_remove_color,V1,V2,E1,F1,remove,color,none) :- not compare(edit_remove_color_count,V1,V2,E1,count,remove,color,none), not compare(_,V1,V2,E1,_,move,color,_), comparable(V1,V2), channel(V1,E1,color), field(V1,E1,F1), not channel(V2,_,color). +compare(edit_remove_shape,V1,V2,E1,F1,remove,shape,none) :- not compare(edit_remove_shape_count,V1,V2,E1,count,remove,shape,none), not compare(_,V1,V2,E1,_,move,shape,_), comparable(V1,V2), channel(V1,E1,shape), field(V1,E1,F1), not channel(V2,_,shape). +compare(edit_remove_size,V1,V2,E1,F1,remove,size,none) :- not compare(edit_remove_size_count,V1,V2,E1,count,remove,size,none), not compare(_,V1,V2,E1,_,move,size,_), comparable(V1,V2), channel(V1,E1,size), field(V1,E1,F1), not channel(V2,_,size). +compare(edit_remove_row,V1,V2,E1,F1,remove,row,none) :- not compare(edit_remove_row_count,V1,V2,E1,count,remove,row,none), not compare(_,V1,V2,E1,_,move,row,_), comparable(V1,V2), channel(V1,E1,row), field(V1,E1,F1), not channel(V2,_,row). +compare(edit_remove_column,V1,V2,E1,F1,remove,column,none) :- not compare(edit_remove_column_count,V1,V2,E1,count,remove,column,none), not compare(_,V1,V2,E1,_,move,column,_), comparable(V1,V2), channel(V1,E1,column), field(V1,E1,F1), not channel(V2,_,column). +compare(edit_remove_text,V1,V2,E1,F1,remove,text,none) :- not compare(edit_remove_text_count,V1,V2,E1,count,remove,text,none), not compare(_,V1,V2,E1,_,move,text,_), comparable(V1,V2), channel(V1,E1,text), field(V1,E1,F1), not channel(V2,_,text). +compare(edit_modify_x,V1,V2,E1,F2,modify,x,none) :- not compare(edit_modify_x_add_count,V1,V2,E1,count,modify,x,none), not compare(edit_modify_x_remove_count,V1,V2,E1,count,modify,x,none), comparable(V1,V2), channel(V1,E1,x), channel(V2,E2,x), field(V2,E2,F2), not field(V1,_,F2). +compare(edit_modify_y,V1,V2,E1,F2,modify,y,none) :- not compare(edit_modify_y_add_count,V1,V2,E1,count,modify,y,none), not compare(edit_modify_y_remove_count,V1,V2,E1,count,modify,y,none), comparable(V1,V2), channel(V1,E1,y), channel(V2,E2,y), field(V2,E2,F2), not field(V1,_,F2). +compare(edit_modify_color,V1,V2,E1,F2,modify,color,none) :- not compare(edit_modify_color_add_count,V1,V2,E1,count,modify,color,none), not compare(edit_modify_color_remove_count,V1,V2,E1,count,modify,color,none), comparable(V1,V2), channel(V1,E1,color), channel(V2,E2,color), field(V2,E2,F2), not field(V1,_,F2). +compare(edit_modify_shape,V1,V2,E1,F2,modify,shape,none) :- not compare(edit_modify_shape_add_count,V1,V2,E1,count,modify,shape,none), not compare(edit_modify_shape_remove_count,V1,V2,E1,count,modify,shape,none), comparable(V1,V2), channel(V1,E1,shape), channel(V2,E2,shape), field(V2,E2,F2), not field(V1,_,F2). +compare(edit_modify_size,V1,V2,E1,F2,modify,size,none) :- not compare(edit_modify_size_add_count,V1,V2,E1,count,modify,size,none), not compare(edit_modify_size_remove_count,V1,V2,E1,count,modify,size,none), comparable(V1,V2), channel(V1,E1,size), channel(V2,E2,size), field(V2,E2,F2), not field(V1,_,F2). +compare(edit_modify_row,V1,V2,E1,F2,modify,row,none) :- not compare(edit_modify_row_add_count,V1,V2,E1,count,modify,row,none), not compare(edit_modify_row_remove_count,V1,V2,E1,count,modify,row,none), comparable(V1,V2), channel(V1,E1,row), channel(V2,E2,row), field(V2,E2,F2), not field(V1,_,F2). +compare(edit_modify_column,V1,V2,E1,F2,modify,column,none) :- not compare(edit_modify_column_add_count,V1,V2,E1,count,modify,column,none), not compare(edit_modify_column_remove_count,V1,V2,E1,count,modify,column,none), comparable(V1,V2), channel(V1,E1,column), channel(V2,E2,column), field(V2,E2,F2), not field(V1,_,F2). +compare(edit_modify_text,V1,V2,E1,F2,modify,text,none) :- not compare(edit_modify_text_add_count,V1,V2,E1,count,modify,text,none), not compare(edit_modify_text_remove_count,V1,V2,E1,count,modify,text,none), comparable(V1,V2), channel(V1,E1,text), channel(V2,E2,text), field(V2,E2,F2), not field(V1,_,F2). +compare(edit_modify_x_add_count,V1,V2,E1,count,modify,x,none) :- comparable(V1,V2), channel(V1,E1,x), channel(V2,E2,x), not aggregate(V1,E1,count), aggregate(V2,E2,count). +compare(edit_modify_y_add_count,V1,V2,E1,count,modify,y,none) :- comparable(V1,V2), channel(V1,E1,y), channel(V2,E2,y), not aggregate(V1,E1,count), aggregate(V2,E2,count). +compare(edit_modify_color_add_count,V1,V2,E1,count,modify,color,none) :- comparable(V1,V2), channel(V1,E1,color), channel(V2,E2,color), not aggregate(V1,E1,count), aggregate(V2,E2,count). +compare(edit_modify_shape_add_count,V1,V2,E1,count,modify,shape,none) :- comparable(V1,V2), channel(V1,E1,shape), channel(V2,E2,shape), not aggregate(V1,E1,count), aggregate(V2,E2,count). +compare(edit_modify_size_add_count,V1,V2,E1,count,modify,size,none) :- comparable(V1,V2), channel(V1,E1,size), channel(V2,E2,size), not aggregate(V1,E1,count), aggregate(V2,E2,count). +compare(edit_modify_row_add_count,V1,V2,E1,count,modify,row,none) :- comparable(V1,V2), channel(V1,E1,row), channel(V2,E2,row), not aggregate(V1,E1,count), aggregate(V2,E2,count). +compare(edit_modify_column_add_count,V1,V2,E1,count,modify,column,none) :- comparable(V1,V2), channel(V1,E1,column), channel(V2,E2,column), not aggregate(V1,E1,count), aggregate(V2,E2,count). +compare(edit_modify_text_add_count,V1,V2,E1,count,modify,text,none) :- comparable(V1,V2), channel(V1,E1,text), channel(V2,E2,text), not aggregate(V1,E1,count), aggregate(V2,E2,count). +compare(edit_modify_x_remove_count,V1,V2,E1,count,modify,x,none) :- comparable(V1,V2), channel(V1,E1,x), channel(V2,E2,x), aggregate(V1,E1,count), not aggregate(V2,E2,count). +compare(edit_modify_y_remove_count,V1,V2,E1,count,modify,y,none) :- comparable(V1,V2), channel(V1,E1,y), channel(V2,E2,y), aggregate(V1,E1,count), not aggregate(V2,E2,count). +compare(edit_modify_color_remove_count,V1,V2,E1,count,modify,color,none) :- comparable(V1,V2), channel(V1,E1,color), channel(V2,E2,color), aggregate(V1,E1,count), not aggregate(V2,E2,count). +compare(edit_modify_shape_remove_count,V1,V2,E1,count,modify,shape,none) :- comparable(V1,V2), channel(V1,E1,shape), channel(V2,E2,shape), aggregate(V1,E1,count), not aggregate(V2,E2,count). +compare(edit_modify_size_remove_count,V1,V2,E1,count,modify,size,none) :- comparable(V1,V2), channel(V1,E1,size), channel(V2,E2,size), aggregate(V1,E1,count), not aggregate(V2,E2,count). +compare(edit_modify_row_remove_count,V1,V2,E1,count,modify,row,none) :- comparable(V1,V2), channel(V1,E1,row), channel(V2,E2,row), aggregate(V1,E1,count), not aggregate(V2,E2,count). +compare(edit_modify_column_remove_count,V1,V2,E1,count,modify,column,none) :- comparable(V1,V2), channel(V1,E1,column), channel(V2,E2,column), aggregate(V1,E1,count), not aggregate(V2,E2,count). +compare(edit_modify_text_remove_count,V1,V2,E1,count,modify,text,none) :- comparable(V1,V2), channel(V1,E1,text), channel(V2,E2,text), aggregate(V1,E1,count), not aggregate(V2,E2,count). +compare(edit_move_x_row,V1,V2,E1A,E2A,move,x,row) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,x), channel(V2,E2A,row). +compare(edit_move_x_column,V1,V2,E1A,E2A,move,x,column) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,x), channel(V2,E2A,column). +compare(edit_move_x_size,V1,V2,E1A,E2A,move,x,size) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,x), channel(V2,E2A,size). +compare(edit_move_x_shape,V1,V2,E1A,E2A,move,x,shape) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,x), channel(V2,E2A,shape). +compare(edit_move_x_color,V1,V2,E1A,E2A,move,x,color) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,x), channel(V2,E2A,color). +compare(edit_move_x_y,V1,V2,E1A,E2A,move,x,y) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,x), channel(V2,E2A,y). +compare(edit_move_x_text,V1,V2,E1A,E2A,move,x,text) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,x), channel(V2,E2A,text). +compare(edit_move_y_row,V1,V2,E1A,E2A,move,y,row) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,y), channel(V2,E2A,row). +compare(edit_move_y_column,V1,V2,E1A,E2A,move,y,column) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,y), channel(V2,E2A,column). +compare(edit_move_y_size,V1,V2,E1A,E2A,move,y,size) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,y), channel(V2,E2A,size). +compare(edit_move_y_shape,V1,V2,E1A,E2A,move,y,shape) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,y), channel(V2,E2A,shape). +compare(edit_move_y_color,V1,V2,E1A,E2A,move,y,color) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,y), channel(V2,E2A,color). +compare(edit_move_y_x,V1,V2,E1A,E2A,move,y,x) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,y), channel(V2,E2A,x). +compare(edit_move_y_text,V1,V2,E1A,E2A,move,y,text) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,y), channel(V2,E2A,text). +compare(edit_move_color_row,V1,V2,E1A,E2A,move,color,row) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,color), channel(V2,E2A,row). +compare(edit_move_color_column,V1,V2,E1A,E2A,move,color,column) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,color), channel(V2,E2A,column). +compare(edit_move_color_size,V1,V2,E1A,E2A,move,color,size) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,color), channel(V2,E2A,size). +compare(edit_move_color_shape,V1,V2,E1A,E2A,move,color,shape) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,color), channel(V2,E2A,shape). +compare(edit_move_color_y,V1,V2,E1A,E2A,move,color,y) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,color), channel(V2,E2A,y). +compare(edit_move_color_x,V1,V2,E1A,E2A,move,color,x) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,color), channel(V2,E2A,x). +compare(edit_move_color_text,V1,V2,E1A,E2A,move,color,text) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,color), channel(V2,E2A,text). +compare(edit_move_shape_row,V1,V2,E1A,E2A,move,shape,row) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,shape), channel(V2,E2A,row). +compare(edit_move_shape_column,V1,V2,E1A,E2A,move,shape,column) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,shape), channel(V2,E2A,column). +compare(edit_move_shape_size,V1,V2,E1A,E2A,move,shape,size) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,shape), channel(V2,E2A,size). +compare(edit_move_shape_color,V1,V2,E1A,E2A,move,shape,color) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,shape), channel(V2,E2A,color). +compare(edit_move_shape_y,V1,V2,E1A,E2A,move,shape,y) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,shape), channel(V2,E2A,y). +compare(edit_move_shape_x,V1,V2,E1A,E2A,move,shape,x) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,shape), channel(V2,E2A,x). +compare(edit_move_shape_text,V1,V2,E1A,E2A,move,shape,text) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,shape), channel(V2,E2A,text). +compare(edit_move_size_row,V1,V2,E1A,E2A,move,size,row) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,size), channel(V2,E2A,row). +compare(edit_move_size_column,V1,V2,E1A,E2A,move,size,column) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,size), channel(V2,E2A,column). +compare(edit_move_size_shape,V1,V2,E1A,E2A,move,size,shape) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,size), channel(V2,E2A,shape). +compare(edit_move_size_color,V1,V2,E1A,E2A,move,size,color) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,size), channel(V2,E2A,color). +compare(edit_move_size_y,V1,V2,E1A,E2A,move,size,y) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,size), channel(V2,E2A,y). +compare(edit_move_size_x,V1,V2,E1A,E2A,move,size,x) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,size), channel(V2,E2A,x). +compare(edit_move_size_text,V1,V2,E1A,E2A,move,size,text) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,size), channel(V2,E2A,text). +compare(edit_move_text_row,V1,V2,E1A,E2A,move,text,row) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,text), channel(V2,E2A,row). +compare(edit_move_text_column,V1,V2,E1A,E2A,move,text,column) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,text), channel(V2,E2A,column). +compare(edit_move_text_shape,V1,V2,E1A,E2A,move,text,shape) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,text), channel(V2,E2A,shape). +compare(edit_move_text_color,V1,V2,E1A,E2A,move,text,color) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,text), channel(V2,E2A,color). +compare(edit_move_text_y,V1,V2,E1A,E2A,move,text,y) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,text), channel(V2,E2A,y). +compare(edit_move_text_x,V1,V2,E1A,E2A,move,text,x) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,text), channel(V2,E2A,x). +compare(edit_move_text_size,V1,V2,E1A,E2A,move,text,size) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,text), channel(V2,E2A,size). +compare(edit_move_column_row,V1,V2,E1A,E2A,move,column,row) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,column), channel(V2,E2A,row). +compare(edit_move_column_size,V1,V2,E1A,E2A,move,column,size) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,column), channel(V2,E2A,size). +compare(edit_move_column_shape,V1,V2,E1A,E2A,move,column,shape) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,column), channel(V2,E2A,shape). +compare(edit_move_column_color,V1,V2,E1A,E2A,move,column,color) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,column), channel(V2,E2A,color). +compare(edit_move_column_y,V1,V2,E1A,E2A,move,column,y) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,column), channel(V2,E2A,y). +compare(edit_move_column_x,V1,V2,E1A,E2A,move,column,x) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,column), channel(V2,E2A,x). +compare(edit_move_column_text,V1,V2,E1A,E2A,move,column,text) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,column), channel(V2,E2A,text). +compare(edit_move_row_column,V1,V2,E1A,E2A,move,row,column) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,row), channel(V2,E2A,column). +compare(edit_move_row_size,V1,V2,E1A,E2A,move,row,size) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,row), channel(V2,E2A,size). +compare(edit_move_row_shape,V1,V2,E1A,E2A,move,row,shape) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,row), channel(V2,E2A,shape). +compare(edit_move_row_color,V1,V2,E1A,E2A,move,row,color) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,row), channel(V2,E2A,color). +compare(edit_move_row_y,V1,V2,E1A,E2A,move,row,y) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,row), channel(V2,E2A,y). +compare(edit_move_row_x,V1,V2,E1A,E2A,move,row,x) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,row), channel(V2,E2A,x). +compare(edit_move_row_text,V1,V2,E1A,E2A,move,row,text) :- comparable(V1,V2), field(V1,E1A,F), field(V2,E2A,F), channel(V1,E1A,row), channel(V2,E2A,text). +compare(edit_swap_x_y,V1,V2,E1A,E2A,swap,x,y) :- comparable(V1,V2), channel(V1,E1A,x), channel(V1,E1B,y), channel(V2,E2A,x), channel(V2,E2B,y), field(V1,E1A,FA), field(V2,E2B,FA), field(V1,E1B,FB), field(V2,E2A,FB). +compare(edit_swap_row_column,V1,V2,E1A,E2A,swap,row,column) :- comparable(V1,V2), channel(V1,E1A,row), channel(V1,E1B,column), channel(V2,E2A,row), channel(V2,E2B,column), field(V1,E1A,FA), field(V2,E2B,FA), field(V1,E1B,FB), field(V2,E2A,FB). + + +compare(edit_scale,V1,V2,E1,E2) :- comparable(V1,V2), field(V1,E1,F), field(V2,E2,F), log(V1,E1), not log(V2,E2). +compare(edit_scale,V1,V2,E1,E2) :- comparable(V1,V2), field(V1,E1,F), field(V2,E2,F), not log(V1,E1), log(V2,E2). +compare(edit_scale,V1,V2,E1,E2) :- comparable(V1,V2), field(V1,E1,F), field(V2,E2,F), zero(V1,E1), not zero(V2,E2). +compare(edit_scale,V1,V2,E1,E2) :- comparable(V1,V2), field(V1,E1,F), field(V2,E2,F), not zero(V1,E1), zero(V2,E2). + +compare(edit_bin,V1,V2,E1,E2) :- comparable(V1,V2), field(V1,E1,F), field(V2,E2,F), bin(V1,E1,_), not bin(V2,E2,_). +compare(edit_bin,V1,V2,E1,E2) :- comparable(V1,V2), field(V1,E1,F), field(V2,E2,F), not bin(V1,E1,_), bin(V2,E2,_). + +compare(edit_aggregate,V1,V2,E1,E2) :- comparable(V1,V2), field(V1,E1,F), field(V2,E2,F), aggregate(V1,E1,A1), aggregate(V2,E2,A2), A1 != A2. +compare(edit_aggregate,V1,V2,E1,E2) :- comparable(V1,V2), field(V1,E1,F), field(V2,E2,F), aggregate(V1,E1,_), not aggregate(V2,E2,_), not compare(_,V1,V2,E2,count,_,_,_). +compare(edit_aggregate,V1,V2,E1,E2) :- comparable(V1,V2), field(V1,E1,F), field(V2,E2,F), not aggregate(V1,E1,_), aggregate(V2,E2,_), not compare(_,V1,V2,E2,count,_,_,_). + +compare(NAME,V1,V2,A,B) :- compare(NAME,V1,V2,A,B,_,_,_). diff --git a/asp/compare_hard.lp b/asp/compare_hard.lp new file mode 100644 index 0000000..d63e154 --- /dev/null +++ b/asp/compare_hard.lp @@ -0,0 +1,2 @@ +% don't have different when anchoring. +:- comparable(V1,V2), field(V1,E1,F), field(V2,E2,F), type(V1,E1,T1), type(V2,E2,T2), T1 != T2. diff --git a/asp/compare_weights.lp b/asp/compare_weights.lp new file mode 100644 index 0000000..6b6f071 --- /dev/null +++ b/asp/compare_weights.lp @@ -0,0 +1,138 @@ +%% FILE GENERATED BY graphscapeToAsp.js, DO NOT MODIFY %% +#const edit_area_bar_weight = 3. +#const edit_area_line_weight = 2. +#const edit_area_point_weight = 4. +#const edit_area_text_weight = 8. +#const edit_area_tick_weight = 4. +#const edit_bar_line_weight = 4. +#const edit_bar_point_weight = 2. +#const edit_bar_text_weight = 6. +#const edit_bar_tick_weight = 2. +#const edit_line_point_weight = 3. +#const edit_line_text_weight = 7. +#const edit_line_tick_weight = 3. +#const edit_point_text_weight = 5. +#const edit_point_tick_weight = 1. +#const edit_text_tick_weight = 5. +#const edit_scale_weight = 60. +#const edit_sort_weight = 61. +#const edit_bin_weight = 62. +#const edit_aggregate_weight = 63. +#const edit_add_filter_weight = 65. +#const edit_remove_filter_weight = 65. +#const edit_modify_filter_weight = 64. +#const edit_add_x_weight = 459. +#const edit_add_y_weight = 459. +#const edit_add_color_weight = 455. +#const edit_add_shape_weight = 451. +#const edit_add_size_weight = 453. +#const edit_add_row_weight = 457. +#const edit_add_column_weight = 457. +#const edit_add_text_weight = 449. +#const edit_add_x_count_weight = 458. +#const edit_add_y_count_weight = 458. +#const edit_add_color_count_weight = 454. +#const edit_add_shape_count_weight = 450. +#const edit_add_size_count_weight = 452. +#const edit_add_row_count_weight = 456. +#const edit_add_column_count_weight = 456. +#const edit_add_text_count_weight = 448. +#const edit_remove_x_count_weight = 458. +#const edit_remove_y_count_weight = 458. +#const edit_remove_color_count_weight = 454. +#const edit_remove_shape_count_weight = 450. +#const edit_remove_size_count_weight = 452. +#const edit_remove_row_count_weight = 456. +#const edit_remove_column_count_weight = 456. +#const edit_remove_text_count_weight = 448. +#const edit_remove_x_weight = 459. +#const edit_remove_y_weight = 459. +#const edit_remove_color_weight = 455. +#const edit_remove_shape_weight = 451. +#const edit_remove_size_weight = 453. +#const edit_remove_row_weight = 457. +#const edit_remove_column_weight = 457. +#const edit_remove_text_weight = 449. +#const edit_modify_x_weight = 471. +#const edit_modify_y_weight = 471. +#const edit_modify_color_weight = 467. +#const edit_modify_shape_weight = 463. +#const edit_modify_size_weight = 465. +#const edit_modify_row_weight = 469. +#const edit_modify_column_weight = 469. +#const edit_modify_text_weight = 461. +#const edit_modify_x_add_count_weight = 470. +#const edit_modify_y_add_count_weight = 470. +#const edit_modify_color_add_count_weight = 466. +#const edit_modify_shape_add_count_weight = 462. +#const edit_modify_size_add_count_weight = 464. +#const edit_modify_row_add_count_weight = 468. +#const edit_modify_column_add_count_weight = 468. +#const edit_modify_text_add_count_weight = 460. +#const edit_modify_x_remove_count_weight = 470. +#const edit_modify_y_remove_count_weight = 470. +#const edit_modify_color_remove_count_weight = 466. +#const edit_modify_shape_remove_count_weight = 462. +#const edit_modify_size_remove_count_weight = 464. +#const edit_modify_row_remove_count_weight = 468. +#const edit_modify_column_remove_count_weight = 468. +#const edit_modify_text_remove_count_weight = 460. +#const edit_move_x_row_weight = 445. +#const edit_move_x_column_weight = 443. +#const edit_move_x_size_weight = 446. +#const edit_move_x_shape_weight = 446. +#const edit_move_x_color_weight = 446. +#const edit_move_x_y_weight = 444. +#const edit_move_x_text_weight = 446. +#const edit_move_y_row_weight = 443. +#const edit_move_y_column_weight = 445. +#const edit_move_y_size_weight = 446. +#const edit_move_y_shape_weight = 446. +#const edit_move_y_color_weight = 446. +#const edit_move_y_x_weight = 444. +#const edit_move_y_text_weight = 446. +#const edit_move_color_row_weight = 447. +#const edit_move_color_column_weight = 447. +#const edit_move_color_size_weight = 443. +#const edit_move_color_shape_weight = 443. +#const edit_move_color_y_weight = 446. +#const edit_move_color_x_weight = 446. +#const edit_move_color_text_weight = 443. +#const edit_move_shape_row_weight = 447. +#const edit_move_shape_column_weight = 447. +#const edit_move_shape_size_weight = 443. +#const edit_move_shape_color_weight = 443. +#const edit_move_shape_y_weight = 446. +#const edit_move_shape_x_weight = 446. +#const edit_move_shape_text_weight = 443. +#const edit_move_size_row_weight = 447. +#const edit_move_size_column_weight = 447. +#const edit_move_size_shape_weight = 443. +#const edit_move_size_color_weight = 443. +#const edit_move_size_y_weight = 446. +#const edit_move_size_x_weight = 446. +#const edit_move_size_text_weight = 443. +#const edit_move_text_row_weight = 447. +#const edit_move_text_column_weight = 447. +#const edit_move_text_shape_weight = 443. +#const edit_move_text_color_weight = 443. +#const edit_move_text_y_weight = 446. +#const edit_move_text_x_weight = 446. +#const edit_move_text_size_weight = 443. +#const edit_move_column_row_weight = 444. +#const edit_move_column_size_weight = 447. +#const edit_move_column_shape_weight = 447. +#const edit_move_column_color_weight = 447. +#const edit_move_column_y_weight = 445. +#const edit_move_column_x_weight = 443. +#const edit_move_column_text_weight = 447. +#const edit_move_row_column_weight = 444. +#const edit_move_row_size_weight = 447. +#const edit_move_row_shape_weight = 447. +#const edit_move_row_color_weight = 447. +#const edit_move_row_y_weight = 443. +#const edit_move_row_x_weight = 445. +#const edit_move_row_text_weight = 447. +#const edit_swap_x_y_weight = 442. +#const edit_swap_row_column_weight = 441. +#const edit_ceiling_weight = 1413. \ No newline at end of file diff --git a/asp/define.lp b/asp/define.lp index 0182c07..8504e77 100644 --- a/asp/define.lp +++ b/asp/define.lp @@ -10,13 +10,13 @@ primitive_type(string;number;boolean;datetime). aggregate_op(count;mean;median;min;max;stdev;sum). summative_aggregate_op(count;sum). % Numbers of bins that can be recommended; any natural number is allowed. -binning(10;25;200). +binning(10;25). % Encoding channels. single_channel(x;y;color;size;shape;text;row;column). multi_channel(detail). channel(C) :- single_channel(C). -channel(C) :- multi_channel(C). +% channel(C) :- multi_channel(C). non_positional(color;size;shape;text;detail). % Possible tasks. @@ -27,95 +27,96 @@ stacking(zero;normalize). % ====== Helpers ====== -discrete(E) :- type(E,(nominal;ordinal)). -discrete(E) :- bin(E,_). -continuous(E) :- encoding(E), not discrete(E). +discrete(V,E) :- type(V,E,(nominal;ordinal)). +discrete(V,E) :- bin(V,E,_). +continuous(V,E) :- encoding(V,E), not discrete(V,E). -channel_discrete(C) :- discrete(E), channel(E,C). -channel_continuous(C) :- continuous(E), channel(E,C). +channel_discrete(V,C) :- discrete(V,E), channel(V,E,C). +channel_continuous(V,C) :- continuous(V,E), channel(V,E,C). -ordered(E) :- type(E,(ordinal;quantitative)). +ordered(E) :- type(V,E,(ordinal;quantitative)). % Fields field(F) :- fieldtype(F,_). % Stacking is applied to the continuous x or y. -stack(EC,S) :- channel(EC,(x;y)), channel(ED,(x;y)), continuous(EC), discrete(ED), stack(S). +stack(V,EC,S) :- channel(V,EC,(x;y)), channel(V,ED,(x;y)), continuous(V,EC), discrete(V,ED), stack(V,S). % X and y are continuous. -stack(E,S) :- channel_continuous(x), channel(E,y), continuous(E), stack(S). +stack(E,S) :- channel_continuous(V,x), channel(V,E,y), continuous(V,E), stack(V,S). -stack(S) :- stack(_,S). +stack(V,S) :- encoding(V,E), stack(E,S). % Data properties -enc_cardinality(E,C) :- field(E,F), cardinality(F,C). -enc_entropy(E,EN) :- field(E,F), entropy(F,EN). -enc_interesting(E) :- field(E,F), interesting(F). -enc_extent(E,MIN,MAX) :- field(E,F), extent(F,MIN,MAX). +enc_cardinality(V,E,C) :- field(V,E,F), cardinality(F,C). +enc_entropy(V,E,EN) :- field(V,E,F), entropy(F,EN). +enc_interesting(V,E) :- field(V,E,F), interesting(F). +enc_extent(V,E,MIN,MAX) :- field(V,E,F), extent(F,MIN,MAX). % Cardinality of discrete field. A binned field has the cadinality of its field. -discrete_cardinality(E,CE) :- discrete(E), enc_cardinality(E,CE), channel(E,C), not bin(E,_). -discrete_cardinality(E,CB) :- channel(E,C), bin(E,CB). +discrete_cardinality(V,E,CE) :- discrete(V,E), enc_cardinality(V,E,CE), channel(V,E,C), not bin(V,E,_). +discrete_cardinality(V,E,CB) :- channel(V,E,C), bin(V,E,CB). % Define a fake soft/2 for all soft/1. -soft(F,_placeholder) :- soft(F). +soft(F,V,_placeholder) :- soft(F,V). % Silence warnings about properties never appearing in head. entropy(0,0) :- #false. interesting(0) :- #false. extent(0,0,0) :- #false. soft(0) :- #false. -task(value) :- #false. -task(summary) :- #false. +task(0,value) :- #false. +task(0,summary) :- #false. data(0) :- #false. +base(0) :- #false. % == Chart Types == % Continuous by continuous. -is_c_c :- channel_continuous(x), channel_continuous(y). +is_c_c(V) :- channel_continuous(V,x), channel_continuous(V,y). % Continuous by discrete (or continuous only). -is_c_d :- channel_continuous(x), not channel_continuous(y). -is_c_d :- channel_continuous(y), not channel_continuous(x). +is_c_d(V) :- channel_continuous(V,x), not channel_continuous(V,y). +is_c_d(V) :- channel_continuous(V,y), not channel_continuous(V,x). % Discrete by discrete. -is_d_d :- channel_discrete(x), channel_discrete(y). +is_d_d(V) :- channel_discrete(V,x), channel_discrete(V,y). % == Overlap == % The continuous variable is a measure (it is aggregated) and all other channels are .aggregated, or we use stack -> no overlap -non_pos_unaggregated :- channel(E,C), non_positional(C), not aggregate(E,_). -no_overlap :- is_c_d, continuous(E), channel(E,(x;y)), aggregate(E,_), not non_pos_unaggregated. -no_overlap :- is_c_d, stack(_). +non_pos_unaggregated(V) :- channel(V,E,C), non_positional(C), not aggregate(V,E,_). +no_overlap(V) :- is_c_d(V), continuous(V,E), channel(V,E,(x;y)), aggregate(V,E,_), not non_pos_unaggregated(V). +no_overlap(V) :- is_c_d(V), stack(V,_). % the size of the discrete positional encoding -discrete_size(S) :- is_c_d, x_y_cardinality(_,S). -discrete_size(1) :- is_c_d, channel_continuous(x), not channel(_,y). -discrete_size(1) :- is_c_d, channel_continuous(y), not channel(_,x). +discrete_size(V,S) :- is_c_d(V), x_y_cardinality(V,_,S). +discrete_size(V,1) :- is_c_d(V), channel_continuous(V,x), not channel(V,_,y). +discrete_size(V,1) :- is_c_d(V), channel_continuous(V,y), not channel(V,_,x). % Data size is as small as discrete dimension -> no overlap. -no_overlap :- is_c_d, num_rows(S), discrete_size(S). +no_overlap(V) :- is_c_d(V), num_rows(S), discrete_size(V,S). % We definitely overlap if the data size > discrete size. -overlap :- is_c_d, not no_overlap, num_rows(S1), discrete_size(S2), S1 > S2. +overlap(V) :- is_c_d(V), not no_overlap(V), num_rows(S1), discrete_size(V,S2), S1 > S2. % helpers to go from quadratic to linear number of grounding -x_y_cardinality(x,S) :- channel(E,x), discrete_cardinality(E,S). -x_y_cardinality(y,S) :- channel(E,y), discrete_cardinality(E,S). +x_y_cardinality(V,x,S) :- channel(V,E,x), discrete_cardinality(V,E,S). +x_y_cardinality(V,y,S) :- channel(V,E,y), discrete_cardinality(V,E,S). % No overlap if all other dimensions are aggregated. -discrete_size(S) :- is_d_d, x_y_cardinality(x,SX), x_y_cardinality(y,SY), S = SX*SY. -no_overlap :- is_d_d, not non_pos_unaggregated. -no_overlap :- is_d_d, num_rows(S1), discrete_size(S2), S1 <= S2. % This cannot guarantee no overlap. +discrete_size(V,S) :- is_d_d(V), x_y_cardinality(V,x,SX), x_y_cardinality(V,y,SY), S = SX*SY. +no_overlap(V) :- is_d_d(V), not non_pos_unaggregated(V). +no_overlap(V) :- is_d_d(V), num_rows(S1), discrete_size(V,S2), S1 <= S2. % This cannot guarantee no overlap. % We can guarantee overlap using this rule unless we are using row / column. -row_col :- channel(_,(row;column)). -overlap :- is_d_d, channel(E,C), not row_col, not no_overlap, num_rows(S1), discrete_size(S2), S1 > S2. +row_col(V) :- channel(V,_,(row;column)). +overlap(V) :- is_d_d(V), channel(V,E,C), not row_col(V), not no_overlap(V), num_rows(S1), discrete_size(V,S2), S1 > S2. % == Orientation == % Orientation tells us which one is the dependent and independent variable. -orientation(vertical) :- mark(bar;tick;area;line), channel_discrete(x). -orientation(vertical) :- mark(area;line), channel_continuous(x), channel_continuous(y). +orientation(V,vertical) :- mark(V,(bar;tick;area;line)), channel_discrete(V,x). +orientation(V,vertical) :- mark(V,(area;line)), channel_continuous(V,x), channel_continuous(V,y). -orientation(horizontal) :- mark(bar;tick;area;line), channel_discrete(y). +orientation(V,horizontal) :- mark(V,(bar;tick;area;line)), channel_discrete(V,y). diff --git a/asp/generate.lp b/asp/generate.lp index ea185e3..227c6b0 100644 --- a/asp/generate.lp +++ b/asp/generate.lp @@ -3,31 +3,36 @@ % encodings % maximum number for each multi channel encoding -#const max_extra_encs = 5. +#const max_extra_encs = 1. obj_id(1..max_extra_encs). -{ encoding(E): obj_id(E) }. +{ encoding(V,E): obj_id(E) } :- view(V), not base(V). -:- not encoding(ID), encoding(ID-1), obj_id(ID), obj_id(ID-1). +:- not encoding(V,ID), not base(V), encoding(V,ID-1), obj_id(ID), obj_id(ID-1). + +% don't add extra field +:- obj_id(ID), field(_,ID,_). % properties of encodings % channel and type have to be present -{ channel(E,C): channel(C) } = 1 :- encoding(E). -{ type(E,T): type(T) } = 1 :- encoding(E). +{ channel(V,E,C) : channel(C) } = 1 :- encoding(V,E), not base(V). +{ type(V,E,T): type(T) } = 1 :- encoding(V,E), not base(V). % other properties that are not required -0 { field(E,F): field(F) } 1 :- encoding(E). -0 { aggregate(E,A): aggregate_op(A) } 1 :- encoding(E). -0 { bin(E,B): binning(B) } 1 :- encoding(E). -0 { zero(E) } 1 :- encoding(E). -0 { log(E) } 1 :- encoding(E). +0 { field(V,E,F): field(F) } 1 :- encoding(V,E), not base(V). +0 { aggregate(V,E,A): aggregate_op(A) } 1 :- encoding(V,E), not base(V). +0 { bin(V,E,B): binning(B) } 1 :- encoding(V,E), not base(V). +0 { zero(V,E) } 1 :- encoding(V,E), not base(V). +0 { log(V,E) } 1 :- encoding(V,E), not base(V). % pick one mark type -{ mark(M) : marktype(M) } = 1. +{ mark(V,M) : marktype(M) } = 1 :- view(V), not base(V). % stacking -0 { stack(S): stacking(S) } 1. +0 { stack(V,S): stacking(S) } 1 :- view(V), not base(V). + +:- field(V,E1,F1), field(V,E2,F2), E1 > E2, F1 <= F2. diff --git a/asp/hard.lp b/asp/hard.lp index a596615..1e6bbf7 100644 --- a/asp/hard.lp +++ b/asp/hard.lp @@ -1,212 +1,215 @@ -:- hard(_). -:- hard(_,_). -:- hard(_,_,_). +:- view(V), hard(_,V). +:- view(V), hard(_,V,_). +:- view(V), hard(_,V,_,_). % ====== Expressiveness and Well-Formedness Constraints ====== % === Within Encodings === % @constraint Primitive type has to support data type. -hard(enc_type_valid,E,F) :- type(E,quantitative), field(E,F), fieldtype(F,(string;boolean)). -hard(enc_type_valid,E,F) :- type(E,temporal), field(E,F), not fieldtype(F,datetime). +hard(enc_type_valid,V,E,F) :- type(V,E,quantitative), field(V,E,F), fieldtype(F,(string;boolean)). +hard(enc_type_valid,V,E,F) :- type(V,E,temporal), field(V,E,F), not fieldtype(F,datetime). % @constraint Can only bin quantitative or ordinal. -hard(bin_q_o,E,T) :- type(E,T), bin(E,_), T != quantitative, T != ordinal. +hard(bin_q_o,V,E,T) :- type(V,E,T), bin(V,E,_), T != quantitative, T != ordinal. % @constraint Can only use log with quantitative. -hard(log_q,E) :- log(E), not type(E,quantitative). +hard(log_q,V,E) :- log(V,E), not type(V,E,quantitative). % @constraint Can only use zero with quantitative. -hard(zero_q,E) :- zero(E), not type(E,quantitative). +hard(zero_q,V,E) :- zero(V,E), not type(V,E,quantitative). % @constraint Cannot use log scale with discrete (which includes binned). -hard(log_discrete,E) :- log(E), discrete(E). +hard(log_discrete,V,E) :- log(V,E), discrete(V,E). % @constraint Cannot use log and zero together. -hard(log_zero,E) :- log(E), zero(E). +hard(log_zero,V,E) :- log(V,E), zero(V,E). % @constraint Cannot use log if the data is negative or zero. -hard(log_non_positive,E,F) :- log(E), field(E,F), extent(F,MIN,_), MIN <= 0. +hard(log_non_positive,V,E,F) :- log(V,E), field(V,E,F), extent(F,MIN,_), MIN <= 0. % @constraint Cannot bin and aggregate. -hard(bin_and_aggregate,E) :- bin(E,_), aggregate(E,_). +hard(bin_and_aggregate,V,E) :- aggregate(V,E,_), bin(V,E,_). % @constraint Oridnal only supports min, max, and median. -hard(aggregate_o_valid,E,A) :- type(E,ordinal), aggregate(E,A), A != min, A != max, A != median. +hard(aggregate_o_valid,V,E,A) :- aggregate(V,E,A), type(V,E,ordinal), A != min, A != max, A != median. % @constraint Temporal only supports min and max. -hard(aggregate_t_valid,E,A) :- type(E,temporal), aggregate(E,A), A != min, A != max. +hard(aggregate_t_valid,V,E,A) :- aggregate(V,E,A), type(V,E,temporal), A != min, A != max. % @constraint Cannot aggregate nominal. -hard(aggregate_nominal,E) :- aggregate(E,_), type(E,nominal). +hard(aggregate_nominal,V,E) :- aggregate(V,E,_), type(V,E,nominal). % @constraint Detail cannot be aggregated. -hard(aggregate_detail,E) :- channel(E,detail), aggregate(E,_). +hard(aggregate_detail,V,E) :- channel(V,E,detail), aggregate(V,E,_). % @constraint Count has to be quantitative and not use a field. -hard(count_q_without_field,E) :- aggregate(E,count), field(E,_). -hard(count_q_without_field,E) :- aggregate(E,count), not type(E,quantitative). +hard(count_q_without_field,V,E) :- aggregate(V,E,count), field(V,E,_). +hard(count_q_without_field,V,E) :- aggregate(V,E,count), not type(V,E,quantitative). % @constraint Shape requires discrete and not ordered (nominal). Using ordinal would't make a difference in Vega-Lite. -hard(shape_discrete_non_ordered,E) :- channel(E,shape), not type(E,nominal). +hard(shape_discrete_non_ordered,V,E) :- channel(V,E,shape), not type(V,E,nominal). % @constraint Detail requires nominal. -hard(detail_non_ordered,E) :- channel(E,detail), not type(E,nominal). +hard(detail_non_ordered,V,E) :- channel(V,E,detail), not type(V,E,nominal). % @constraint Size implies order so nominal is misleading. -hard(size_nominal) :- channel(E,size), type(E,nominal). +hard(size_nominal,V,E) :- channel(V,E,size), type(V,E,nominal). % @constraint Do not use size when data is negative as size implies that data is positive. -hard(size_negative,E) :- channel(E,size), enc_extent(E,MIN,MAX), MIN < 0, MAX > 0. +hard(size_negative,V,E) :- channel(V,E,size), enc_extent(V,E,MIN,MAX), MIN < 0, MAX > 0. % === Across encodings and between encodings and marks === % @constraint Cannot use single channels twice. -hard(repeat_channel,C):- single_channel(C), 2 { channel(_,C) }. +hard(repeat_channel,V,C) :- view(V), single_channel(C), 2 { channel(V,_,C) }. % @constraint There has to be at least one encoding. Otherwise, the visualization doesn't show anything. -hard(no_encodings) :- not encoding(_). +hard(no_encodings,V) :- view(V), not encoding(V,_). % @constraint Row and column require discrete. -hard(row_or_column_c) :- channel_continuous(row;column). +hard(row_or_column_c,V) :- channel_continuous(V,(row;column)). % @constraint Don't use row without y. Just using y is simpler. -hard(row_no_y) :- channel(_,row), not channel(_,y). +hard(row_no_y,V) :- channel(V,_,row), not channel(V,_,y). % @constraint Don't use column without x. Just using x is simpler. -hard(column_no_x) :- channel(_,column), not channel(_,x). +hard(column_no_x,V) :- channel(V,_,column), not channel(V,_,x). % @constraint All encodings (if they have a channel) require field except if we have a count aggregate. -hard(encoding_no_field_and_not_count,E) :- not field(E,_), not aggregate(E,count), encoding(E). +hard(encoding_no_field_and_not_count,V,E) :- not field(V,E,_), not aggregate(V,E,count), encoding(V,E). % @constraint Count should not have a field. Having a field doesn't make a difference. -hard(count_with_field,E) :- aggregate(E,count), field(E,_). +hard(count_with_field,V,E) :- aggregate(V,E,count), field(V,E,_). % @constraint Text mark requires text channel. -hard(text_mark_without_text_channel) :- mark(text), not channel(_,text). +hard(text_mark_without_text_channel,V) :- mark(V,text), not channel(V,_,text). % @constraint Text channel requires text mark. -hard(text_channel_without_text_mark) :- channel(_,text), not mark(text). +hard(text_channel_without_text_mark,V) :- channel(V,E,text), not mark(V,text). % @constraint Point, tick, and bar require x or y channel. -hard(point_tick_bar_without_x_or_y) :- mark(point;tick;bar), not channel(_,x), not channel(_,y). +hard(point_tick_bar_without_x_or_y,V) :- mark(V,(point;tick;bar)), not channel(V,_,x), not channel(V,_,y). % @constraint Line and area require x and y channel. -hard(line_area_without_x_y) :- mark(line;area), not channel(_,(x;y)). +hard(line_area_without_x_y,V) :- mark(V,(line;area)), not channel(V,_,(x;y)). % @constraint Line and area cannot have two discrete. -hard(line_area_with_discrete) :- mark(line;area), channel_discrete(x), channel_discrete(y). +hard(line_area_with_discrete,V) :- mark(V,(line;area)), channel_discrete(V,x), channel_discrete(V,y). % @constraint Bar and tick cannot have both x and y continuous. -hard(bar_tick_continuous_x_y) :- mark(bar;tick), channel_continuous(x), channel_continuous(y). +hard(bar_tick_continuous_x_y,V) :- mark(V,(bar;tick)), channel_continuous(V,x), channel_continuous(V,y). % @constraint Bar, tick, line, area require some continuous variable on x or y. -hard(bar_tick_area_line_without_continuous_x_y) :- mark(bar;tick;area;line), not channel_continuous(x), not channel_continuous(y). +hard(bar_tick_area_line_without_continuous_x_y,V) :- mark(V,(bar;tick;area;line)), not channel_continuous(V,x), not channel_continuous(V,y). % @constraint Bar and area mark requires scale of continuous to start at zero. -hard(bar_area_without_zero) :- mark(bar;area), channel(E,x), orientation(horizontal), not zero(E). -hard(bar_area_without_zero) :- mark(bar;area), channel(E,y), orientation(vertical), not zero(E). +hard(bar_area_without_zero,V) :- mark(V,(bar;area)), channel(V,E,x), orientation(V,horizontal), not zero(V,E). +hard(bar_area_without_zero,V) :- mark(V,(bar;area)), channel(V,E,y), orientation(V,vertical), not zero(V,E). % @constraint Shape channel requires point mark. -hard(shape_without_point) :- channel(_,shape), not mark(point). +hard(shape_without_point,V) :- channel(V,_,shape), not mark(V,point). % @constraint Size only works with some marks. Vega-Lite can also size lines, and ticks but that would violate best practices. -hard(size_without_point_text) :- channel(_,size), not mark(point), not mark(text). +hard(size_without_point_text,V) :- channel(V,_,size), not mark(V,point), not mark(V,text). % @constraint Detail requires aggregation. Detail adds a field to the group by. Detail could also be used to add information to tooltips. We may remove this later. -hard(detail_without_agg) :- channel(_,detail), not aggregate(_,_). +hard(detail_without_agg,V) :- channel(V,_,detail), not aggregate(V,_,_). % @constraint Do not use log for bar or area mark as they are often misleading. We may remove this rule in the future. -hard(area_bar_with_log) :- mark(bar;area), log(E), channel(E,(x;y)). +hard(area_bar_with_log,V) :- mark(V,(bar;area)), channel(V,E,(x;y)), log(V,E). % @constraint Rect mark needs discrete x and y. -hard(rect_without_d_d) :- mark(rect), not is_d_d. +hard(rect_without_d_d,V) :- mark(V,rect), not is_d_d(V). % @constraint Don't use the same field on x and y. -hard(same_field_x_and_y) :- { field(E,F) : channel(E,x); field(E,F) : channel(E,y) } >= 2, field(F). +hard(same_field_x_and_y,V) :- view(V), { field(V,E,F) : channel(V,E,x); field(V,E,F) : channel(V,E,y) } >= 2, field(F). % @constraint Don't use count on x and y. -hard(count_on_x_and_y):- channel(EX,x), channel(EY,y), aggregate(EX,count), aggregate(EY,count). +hard(count_on_x_and_y,V):- channel(V,EX,x), channel(V,EY,y), aggregate(V,EX,count), aggregate(V,EY,count). % @constraint If we use aggregation, then all continuous fields need to be aggeragted. -hard(aggregate_not_all_continuous):- aggregate(_,_), continuous(E), not aggregate(E,_). +hard(aggregate_not_all_continuous,V):- aggregate(V,E,_), continuous(V,E), not aggregate(V,E,_). % @constraint Don't use count twice. -hard(count_twice) :- { aggregate(_,count) } = 2. +hard(count_twice) :- view(V), { aggregate(V,_,count) } = 2. % === Global properties === % @constraint Bars and area cannot overlap. -hard(bar_area_overlap) :- mark(bar;area), overlap. +hard(bar_area_overlap,V) :- mark(V,(bar;area)), overlap(V). % @constraint Rects shouldn't overlap. They are used for dioscrete heatmaps. -hard(rect_overlap) :- mark(rect), overlap. +hard(rect_overlap,V) :- mark(V,rect), overlap(V). % == Stacking == % @constraint Only use stacking for bar and area. -hard(stack_without_bar_area) :- stack(_), not mark(bar), not mark(area). +hard(stack_without_bar_area,V) :- stack(V,_), not mark(V,bar), not mark(V,area). % @constraint Don't stack if aggregation is not summative (summative are count, sum, distinct, valid, missing). -hard(stack_without_summative_agg,E,A) :- stack(E,_), aggregate(E,A), not summative_aggregate_op(A). +hard(stack_without_summative_agg,V,E,A) :- aggregate(V,E,A), stack(V,E,_), not summative_aggregate_op(A). % @constraint Need to stack if we use bar, area with discrete color. -hard(no_stack_with_bar_area_discrete_color,E) :- mark(bar;area), channel(E,color), discrete(E), not stack(_). +hard(no_stack_with_bar_area_discrete_color,V,E) :- mark(V,(bar;area)), encoding(V,E), channel(V,E,color), discrete(V,E), not stack(V,_). % @constraint Can only use stack if we also use discrete color, or detail. -hard(stack_without_discrete_color_or_detail) :- stack(_), not channel_discrete(color), not channel(_,detail). +hard(stack_without_discrete_color_or_detail,V) :- stack(V,_), not channel_discrete(V,color), { channel(V,E,detail) } = 0. % @constraint If we use stack and detail, we also have to use quantitative color. -hard(stack_detail_without_q_color) :- stack(_), channel(_,detail), not channel(_,color). -hard(stack_detail_without_q_color,E) :- stack(_), channel(_,detail), channel(E,color), not aggregate(E,_). +hard(stack_detail_without_q_color,V) :- stack(V,_), channel(V,_,detail), not channel(V,_,color). +hard(stack_detail_without_q_color,V,E) :- stack(V,_), channel(V,_,detail), channel(V,E,color), not aggregate(V,E,_). % @constraint Stack can only be on continuous. -hard(stack_discrete,E) :- stack(E,_), discrete(E). +hard(stack_discrete,V,E) :- encoding(V,E), stack(V,E,_), discrete(V,E). % @constraint Stack can only be on x or y. -hard(stack_without_x_y,E) :- stack(E,_), not channel(E,x), not channel(E,y). +hard(stack_without_x_y,V,E) :- encoding(V,E), stack(V,E,_), not channel(V,E,x), not channel(V,E,y). % @constraint Cannot use non positional continuous with stack unless it's aggregated. -hard(stack_with_non_positional_non_agg,E,C) :- stack(_), non_positional(C), channel(E,C), not aggregate(E,_), continuous(E). +hard(stack_with_non_positional_non_agg,V,E,C) :- stack(V,_), encoding(V,E), non_positional(C), channel(V,E,C), not aggregate(V,E,_), continuous(V,E). % @constraint Vega-Lite currently supports 8 shapes. -hard(shape_with_cardinality_gt_eight,E,C) :- channel(E,shape), enc_cardinality(E,C), C > 8. +hard(shape_with_cardinality_gt_eight,V,E,C) :- channel(V,E,shape), enc_cardinality(V,E,C), C > 8. % @constraint At most 20 categorical colors. -hard(color_with_cardinality_gt_twenty,E,C) :- channel(E,color), discrete(E), enc_cardinality(E,C), C > 20. +hard(color_with_cardinality_gt_twenty,V,E,C) :- channel(V,E,color), discrete(V,E), enc_cardinality(V,E,C), C > 20. % === Type checks === % @constraint Check mark. -hard(invalid_mark,M) :- mark(M), not marktype(M). +hard(invalid_mark,V,M) :- mark(V,M), not marktype(M). % @constraint Check types of encoding properties. -hard(invalid_channel,C) :- channel(_,C), not channel(C). -hard(invalid_field,F) :- field(_,F), not field(F). -hard(invalid_type,T) :- type(_,T), not type(T). -hard(invalid_agg,A) :- aggregate(_,A), not aggregate_op(A). -hard(invalid_bin,B) :- bin(_,B), not B >= 0. % @constraint Bin has to be a natural number. +hard(invalid_channel,V,C) :- channel(V,_,C), not channel(C). +hard(invalid_field,V,F) :- field(V,_,F), not field(F). +hard(invalid_type,V,T) :- type(V,_,T), not type(T). +hard(invalid_agg,V,A) :- aggregate(V,_,A), not aggregate_op(A). +hard(invalid_bin,V,B) :- bin(V,_,B), not B >= 0. % @constraint Bin has to be a natural number. % @constraint Fieldtype has to be primitive type. -hard(invalid_fieldtype,T) :- fieldtype(_,T), not primitive_type(T). +hard(invalid_fieldtype,V,T) :- view(V), fieldtype(_,T), not primitive_type(T). % @constraint Task has to be one of the tasks. -hard(invalid_task,T) :- task(T), not tasks(T). +hard(invalid_task,V,T) :- view(V), task(V,T), not tasks(T). % @constraint Num_rows has to be larger than 0. -hard(invalid_num_rows,S) :- num_rows(S), S < 0. +hard(invalid_num_rows,V,S) :- view(V), num_rows(S), S < 0. % @constraint Cardinality has to be larger than 0. -hard(invalid_cardinality,C) :- cardinality(_,C), C < 0. +hard(invalid_cardinality,V,C) :- view(V), cardinality(_,C), C < 0. % @constraint Entropy has to be positive. -hard(invalid_entropy,E) :- entropy(_,E), E < 0. +hard(invalid_entropy,V,E) :- view(V), entropy(_,E), E < 0. % @constraint Extent only allowed for numbers (for now). -hard(invalid_extent_non_number,F) :- extent(F,_,_), not fieldtype(F,number). +hard(invalid_extent_non_number,V,F) :- view(V), extent(F,_,_), not fieldtype(F,number). % @constraint Order has to be correct. -hard(invalid_extent_order,MIN,MAX):- extent(_,MIN,MAX), MIN > MAX. +hard(invalid_extent_order,V,MIN,MAX):- view(V), extent(_,MIN,MAX), MIN > MAX. % @constraint The name of a field cannot be the name of an encoding. This is to prevent errors coming from the shortcuts in define.lp. -hard(encoding_field_same_name,N) :- encoding(N), field(N). +hard(encoding_field_same_name,V,N) :- view(V), encoding(V,N), field(N). + +% @constraint Cannot bin strings. +hard(bin_string,V,E) :- field(V,E,F), fieldtype(F,string), bin(V,E,_). diff --git a/asp/optimize.lp b/asp/optimize.lp index 240c069..e70934b 100644 --- a/asp/optimize.lp +++ b/asp/optimize.lp @@ -1,3 +1,6 @@ % Minimize the feature weight -#minimize { W,F,Q: soft_weight(F,W), soft(F,Q) }. +#minimize { WD,F,V,Q: soft_weight(F,WD), soft(F,V,Q), not base(V) }. + +% #minimize { W@2,F,V,Q: soft_weight(F,W), soft(F,V,Q), not base(V) }. +% #minimize { W@1,F,V1,V2,A,B: compare_weight(F,W), compare(F,V1,V2,A,B) }. diff --git a/asp/optimize_draco.lp b/asp/optimize_draco.lp new file mode 100644 index 0000000..9f72e95 --- /dev/null +++ b/asp/optimize_draco.lp @@ -0,0 +1,4 @@ +#minimize { W,F,V,Q: soft_weight(F,W), soft(F,V,Q), not base(V) }. +% #minimize { W@1,F,V1,V2,A,B: compare_weight(F,W), compare(F,V1,V2,A,B) }. + +% #minimize { W,F,V,Q: soft_weight(F,W), soft(F,V,Q) }. diff --git a/asp/optimize_graphscape.lp b/asp/optimize_graphscape.lp new file mode 100644 index 0000000..18fe463 --- /dev/null +++ b/asp/optimize_graphscape.lp @@ -0,0 +1,2 @@ +% #minimize { W@1,F,V,Q: soft_weight(F,W), soft(F,V,Q), not base(V) }. +#minimize { W,F,V1,V2,A,B: compare_weight(F,W), compare(F,V1,V2,A,B) }. diff --git a/asp/output.lp b/asp/output.lp index 7e4778f..932baa5 100644 --- a/asp/output.lp +++ b/asp/output.lp @@ -2,16 +2,24 @@ #show data/1. -#show mark/1. +#show mark/2. -#show type/2. -#show channel/2. -#show field/2. -#show aggregate/2. -#show bin/2. +#show view/1. +#show base/1. +#show encoding/2. + +#show type/3. +#show channel/3. +#show field/3. +#show aggregate/3. +#show bin/3. #show stack/2. -#show log/1. -#show zero/1. +#show log/2. +#show zero/2. + +#show soft/3. +#show compare/5. -#show soft/2. +#show soft_weight(N,W) : soft(N,_,_), soft_weight(N,W). +#show compare_weight(N,W) : compare(N,_,_,_,_), compare_weight(N,W). diff --git a/asp/process_compare.py b/asp/process_compare.py new file mode 100644 index 0000000..d20d197 --- /dev/null +++ b/asp/process_compare.py @@ -0,0 +1,35 @@ +""" +Reads the weights file and generates assign_weights.lp and weights.json +""" + +import json +import os +import re + + +def absolute_path(p: str) -> str: + return os.path.join(os.path.dirname(os.path.abspath(__file__)), p) + + +def main(): + with open(absolute_path("compare_weights.lp")) as weight_constants, open( + absolute_path("assign_compare_weights.lp"), "w" + ) as assign: + + assign.write("%% GENERATED FILE. DO NOT EDIT.\n\n") + + weights = {} + + for line in weight_constants.readlines(): + match = re.search("#const (.*)_weight = ([\-0-9]*)", line) + if match: + name = match.group(1) + value = int(match.group(2)) + + weights[f"{name}_weight"] = value + + assign.write(f"compare_weight({name},{name}_weight).\n") + +if __name__ == "__main__": + main() +`` \ No newline at end of file diff --git a/asp/soft.lp b/asp/soft.lp index 5fae38e..b7e9c22 100644 --- a/asp/soft.lp +++ b/asp/soft.lp @@ -3,467 +3,482 @@ % ====== Preferences ====== % @constraint Prefer to use raw (no aggregate). -soft(aggregate,E) :- aggregate(E,_). +soft(aggregate,V,E) :- aggregate(V,E,_). % @constraint Prefer to not bin. -soft(bin,E) :- bin(E,_). +soft(bin,V,E) :- bin(V,E,_). % @constraint Prefer binning with at most 12 buckets. -soft(bin_high,E) :- bin(E,B), B > 12. +soft(bin_high,V,E) :- bin(V,E,B), B > 12. % @constraint Prefer binning with more than 7 buckets. -soft(bin_low,E) :- bin(E,B), B <= 7. +soft(bin_low,V,E) :- bin(V,E,B), B <= 7. % @constraint Prefer to use fewer encodings. -soft(encoding,E) :- encoding(E). +soft(encoding,V,E) :- encoding(V,E). % @constraint Prefer to use fewer encodings with fields (count does not have a field). -soft(encoding_field,E) :- encoding(E), field(E,_). +soft(encoding_field,V,E) :- field(V,E,_). % @constraint Prefer not to use the same field twice. -soft(same_field_2,F) :- field(F), { field(_,F) } = 2. +soft(same_field_2,V,F) :- view(V), field(F), { field(V,_,F) } = 2. % @constraint Prefer not to use the same field three or more times. -% @weight {16} -soft(same_field_gte3,F) :- field(F), { field(_,F) } >= 3. -% @end +soft(same_field_gte3,V,F) :- view(V), field(F), { field(V,_,F) } >= 3. % @constraint Prefer not to use count more than once. -soft(count_twice) :- { aggregate(_,count) } = 2. +soft(count_twice,V) :- view(V), { aggregate(V,_,count) } = 2. % @constraint Shape channel should not have too high cardinality. -soft(shape_cardinality,E) :- channel(E,shape), discrete_cardinality(E,C), C > 5. +soft(shape_cardinality,V,E) :- channel(V,E,shape), discrete_cardinality(V,E,C), C > 5. + +% @constraint Prefer nominal string fields +soft(string_non_nominal,V,E) :- type(V,E,ordinal), field(V,E,F), fieldtype(F,string). +soft(string_non_nominal,V,E) :- type(V,E,temporal), field(V,E,F), fieldtype(F,string). +soft(string_non_nominal,V,E) :- type(V,E,quantitative), field(V,E,F), fieldtype(F,string). % @constraint Numbers should not be nominal. -soft(number_nominal,E) :- type(E,nominal), field(E,F), fieldtype(F,number). +soft(number_nominal,V,E) :- type(V,E,nominal), field(V,E,F), fieldtype(F,number). + +% @constraint Numbers should not be ordinal with high cardinality. +soft(number_high_cardinality_ordinal,V,E) :- type(V,E,ordinal), field(V,E,F), fieldtype(F,number), enc_cardinality(V,E,C), C > 20. % @constraint Binned quantitative field should not have too low cardinality. -soft(bin_cardinality,E) :- type(E,quantitative), bin(E,_), enc_cardinality(E,C), C < 15. +soft(bin_cardinality,V,E) :- type(V,E,quantitative), bin(V,E,_), enc_cardinality(V,E,C), C < 15. % @constraint Prefer quantitative for bin. -soft(quant_bin,E) :- bin(E,_), not type(E,quantitative). +soft(quant_bin,V,E) :- bin(V,E,_), not type(V,E,quantitative). % @constraint Plots with only nominal, ordinal, binned q, or t with time unit should add either an aggregation (e.g. count) or a quantitative field. -soft(only_discrete) :- not continuous(_). +soft(only_discrete,V) :- view(V), not continuous(V,_). % @constraint Prefer not to use multiple non-positional encoding channels. -soft(multiple_non_pos) :- {channel(_,C): non_positional(C)} > 1. +soft(multiple_non_pos,V) :- view(V), { channel(V,_,C): non_positional(C) } > 1. % @constraint Prefer not to use non-positional channels until all positional channels are used. -soft(non_positional_pref) :- channel(_,C), non_positional(C), not channel(_,(x;y)). +soft(non_positional_pref,V) :- channel(V,_,C), non_positional(C), not channel(V,_,(x;y)). % @constraint Aggregate plots should not use raw continuous as group by. -soft(aggregate_group_by_raw,E) :- aggregate(_,_), continuous(E), not aggregate(E,_). +soft(aggregate_group_by_raw,E) :- aggregate(V,_,_), continuous(V,E), not aggregate(V,E,_). % @constraint Aggregate should also have a discrete encoding to group by. -soft(agg_dim) :- aggregate(_,_), not discrete(_). +soft(agg_dim,V) :- aggregate(V,_,_), not discrete(V,_). % @constraint Prefer not to use plot with both x and y discrete and no aggregate as it leads to occlusion. -soft(x_y_raw,E) :- channel(EX,x), discrete(EX), channel(EY,y), discrete(EY), not aggregate(E,_), continuous(E). +soft(x_y_raw,V,E) :- channel(V,EX,x), discrete(V,EX), channel(V,EY,y), discrete(V,EY), encoding(V,E), not aggregate(V,E,_), continuous(V,E). % @constraint Prefer not to use log scale. -soft(log,E) :- log(E). +soft(log,V,E) :- log(V,E). % @constraint Prefer to include zero for continuous (binned doesn't need zero). -soft(zero,E) :- continuous(E), not zero(E). +soft(zero,V,E) :- continuous(V,E), not zero(V,E). + +% @constraint Prefer to exclude zero for binned. +soft(zero_bin,V,E) :- bin(V,E,_), zero(V,E). % @constraint Prefer zero size (even when binned). -soft(zero_size) :- channel(E,size), not zero(E). +soft(zero_size,V) :- channel(V,E,size), not zero(V,E). % @constraint Prefer zero positional. -soft(zero_positional) :- continuous(E), channel(E,(x;y)), not zero(E). +soft(zero_positional,V) :- continuous(V,E), channel(V,E,(x;y)), not zero(V,E). % @constraint Prefer not to use zero when the difference between min and max is larger than distance to 0. -soft(zero_skew) :- enc_extent(E,MIN,MAX), EX = MAX - MIN, |MAX| > EX, |MIN| > EX, zero(E). +soft(zero_skew,V) :- enc_extent(V,E,MIN,MAX), EX = MAX - MIN, |MAX| > EX, |MIN| > EX, zero(V,E). % @constraint Do not include zero when the range of data includes zero. -soft(includes_zero) :- zero(E), extent(E,MIN,MAX), MIN < 0, MAX > 0. +soft(includes_zero,V,E) :- zero(V,E), field(V,E,F), extent(F,MIN,MAX), MIN < 0, MAX > 0. % @constraint Prefer to use only x instead of only y. -soft(only_x) :- channel(_,y), not channel(_,x). +soft(only_x,V) :- channel(V,_,y), not channel(V,_,x). % @constraint Chart orientation for bar and tick (with and without bin). Binned fields have short labels if they are quantitative while otherwise labels can be long. -soft(orientation_binned) :- bin(E,_), type(E,quantitative), not channel(E,x). +soft(orientation_binned,V) :- mark(V,(bar;tick)), bin(V,E,_), type(V,E,quantitative), not channel(V,E,x). % @constraint Prefer not to use ordinal for fields with high cardinality. -soft(high_cardinality_ordinal,E) :- type(E,ordinal), discrete_cardinality(E,C), C > 30. +soft(high_cardinality_ordinal,V,E) :- type(V,E,ordinal), discrete_cardinality(V,E,C), C > 30. % @constraint Prefer not to use nominal for fields with high cardinality. -soft(high_cardinality_nominal,E) :- type(E,nominal), enc_cardinality(E,C), C > 12. +soft(high_cardinality_nominal,V,E) :- type(V,E,nominal), enc_cardinality(V,E,C), C > 12. % @constraint Prefer not to use high cardinality nominal for color. -soft(high_cardinality_nominal_color,E) :- type(E,nominal), channel(E,color), enc_cardinality(E,C), C > 10. +soft(high_cardinality_nominal_color,V,E) :- type(V,E,nominal), channel(V,E,color), enc_cardinality(V,E,C), C > 10. % @constraint Avoid high cardinality on x or column as it causes horizontal scrolling. -soft(horizontal_scrolling,E) :- channel(E,x), discrete_cardinality(E,C), C > 50. -soft(horizontal_scrolling,E) :- channel(E,columm), discrete_cardinality(E,C), C > 5. +soft(horizontal_scrolling,V,E) :- channel(V,E,x), discrete_cardinality(V,E,C), C > 50. +soft(horizontal_scrolling,V,E) :- channel(V,E,columm), discrete_cardinality(V,E,C), C > 5. % @constraint Prefer to use temporal type with dates. -soft(temporal_date,E) :- field(E,F), fieldtype(F,datetime), not type(E,temporal). +soft(temporal_date,V,E) :- field(V,E,F), fieldtype(F,datetime), not type(V,E,temporal). % @constraint Prefer quantitative for numbers with high cardinality. -soft(quantitative_numbers) :- field(E,F), fieldtype(F,number), cardinality(F,C), C > 20, not bin(E,_), not type(E,quantitative). +soft(quantitative_numbers,V) :- field(V,E,F), fieldtype(F,number), cardinality(F,C), C > 20, not bin(V,E,_), not type(V,E,quantitative). % @constraint Overplotting. Prefer not to use x and y for continuous with high cardinality and low entropy without aggregation because the points will overplot. -soft(position_entropy,E) :- channel(E,(x;y)), continuous(E), enc_cardinality(E,C), C > 100, enc_entropy(E,EN), EN <= 12, not aggregate(E,_). +soft(position_entropy,V,E) :- channel(V,E,(x;y)), continuous(V,E), enc_cardinality(V,E,C), C > 100, enc_entropy(V,E,EN), EN <= 12, not aggregate(V,E,_). % @constraint Prefer not to use size when the cardinality is large on x or y. -soft(high_cardinality_size,E) :- continuous(E), channel(_,size), enc_cardinality(E,C), C > 100, channel(E,(x;y)). +soft(high_cardinality_size,V,E) :- continuous(V,E), channel(V,_,size), enc_cardinality(V,E,C), C > 100, channel(V,E,(x;y)). % @constraint Prefer not to aggregate for value tasks. -soft(value_agg) :- task(value), aggregate(_,_). +soft(value_agg,V) :- task(V,value), aggregate(V,_,_). % @constraint Prefer not to use row and column for summary tasks as it makes it difficult to compare. -soft(facet_summary,E) :- task(summary), channel(E,row). +soft(facet_summary,V,E) :- task(V,summary), channel(V,E,row). % @constraint Positional interactions as suggested by Kim et al. -soft(x_row) :- channel(_,x), channel(_,row). +soft(x_row,V) :- channel(V,_,x), channel(V,_,row). % @constraint Positional interactions as suggested by Kim et al. -soft(y_row) :- channel(_,y), channel(_,row). +soft(y_row,V) :- channel(V,_,y), channel(V,_,row). % @constraint Positional interactions as suggested by Kim et al. -soft(x_column) :- channel(_,x), channel(_,column). +soft(x_column,V) :- channel(V,_,x), channel(V,_,column). % @constraint Positional interactions as suggested by Kim et al. -soft(y_column) :- channel(_,y), channel(_,column). +soft(y_column,V) :- channel(V,_,y), channel(V,_,column). % @constraint Entropy, primary quantitaty interactions as suggested by Kim et al. -soft(color_entropy_high, E) :- channel(E,color), enc_entropy(E,EN), EN > 12, type(E,quantitative), enc_interesting(E). +soft(color_entropy_high,V,E) :- channel(V,E,color), enc_entropy(V,E,EN), EN > 12, type(V,E,quantitative), enc_interesting(V,E). % @constraint Entropy, primary quantitaty interactions as suggested by Kim et al. -soft(color_entropy_low, E) :- channel(E,color), enc_entropy(E,EN), EN <= 12, type(E,quantitative), enc_interesting(E). +soft(color_entropy_low,V,E) :- channel(V,E,color), enc_entropy(V,E,EN), EN <= 12, type(V,E,quantitative), enc_interesting(V,E). % @constraint Entropy, primary quantitaty interactions as suggested by Kim et al. -soft(size_entropy_high, E) :- channel(E,size), enc_entropy(E,EN), EN > 12, type(E,quantitative), enc_interesting(E). +soft(size_entropy_high,V,E) :- channel(V,E,size), enc_entropy(V,E,EN), EN > 12, type(V,E,quantitative), enc_interesting(V,E). % @constraint Entropy, primary quantitaty interactions as suggested by Kim et al. -soft(size_entropy_low, E) :- channel(E,size), enc_entropy(E,EN), EN <= 12, type(E,quantitative), enc_interesting(E). +soft(size_entropy_low,V,E) :- channel(V,E,size), enc_entropy(V,E,EN), EN <= 12, type(V,E,quantitative), enc_interesting(V,E). % @constraint Prefer not to use continuous on x, discrete on y, and column. -soft(c_d_column) :- channel_continuous(x), channel_discrete(y), channel(_,column). +soft(c_d_column,V) :- channel_continuous(V,x), channel_discrete(V,y), channel(V,_,column). % @constraint Prefer time on x. -soft(temporal_y) :- type(E,temporal), not channel(E,x). +soft(temporal_y,V) :- type(V,E,temporal), not channel(V,E,x). % @constraint Prefer not to overlap with DxD. -soft(d_d_overlap) :- is_d_d, overlap. +soft(d_d_overlap,V) :- is_d_d(V), overlap(V). % ====== Rankings ====== % === Data Types === % @constraint Prefer quantitative > ordinal > nominal. -soft(type_q,E) :- type(E,quantitative). +soft(type_q,V,E) :- type(V,E,quantitative). % @constraint Prefer quantitative > ordinal > nominal. -soft(type_o,E) :- type(E,ordinal). +soft(type_o,V,E) :- type(V,E,ordinal). % @constraint Prefer quantitative > ordinal > nominal. -soft(type_n,E) :- type(E,nominal). +soft(type_n,V,E) :- type(V,E,nominal). % === Mark types === % @constraint Continuous by continuous for point mark. -soft(c_c_point) :- is_c_c, mark(point). +soft(c_c_point,V) :- is_c_c(V), mark(V,point). % @constraint Continuous by continuous for line mark. -soft(c_c_line) :- is_c_c, mark(line). +soft(c_c_line,V) :- is_c_c(V), mark(V,line). % @constraint Continuous by continuous for area mark. -soft(c_c_area) :- is_c_c, mark(area). +soft(c_c_area,V) :- is_c_c(V), mark(V,area). % @constraint Continuous by continuous for text mark. -soft(c_c_text) :- is_c_c, mark(text). +soft(c_c_text,V) :- is_c_c(V), mark(V,text). % @constraint Continuous by continuous for tick mark. -soft(c_c_tick) :- is_c_c, mark(tick). +soft(c_c_tick,V) :- is_c_c(V), mark(V,tick). % @constraint Continuous by discrete for point mark. -soft(c_d_point) :- is_c_d, not no_overlap, mark(point). +soft(c_d_point,V) :- is_c_d(V), not no_overlap(V), mark(V,point). % @constraint Continuous by discrete for bar mark. -soft(c_d_bar) :- is_c_d, not no_overlap, mark(bar). +soft(c_d_bar,V) :- is_c_d(V), not no_overlap(V), mark(V,bar). % @constraint Continuous by discrete for line mark. -soft(c_d_line) :- is_c_d, not no_overlap, mark(line). +soft(c_d_line,V) :- is_c_d(V), not no_overlap(V), mark(V,line). % @constraint Continuous by discrete for area mark. -soft(c_d_area) :- is_c_d, not no_overlap, mark(area). +soft(c_d_area,V) :- is_c_d(V), not no_overlap(V), mark(V,area). % @constraint Continuous by discrete for text mark. -soft(c_d_text) :- is_c_d, not no_overlap, mark(text). +soft(c_d_text,V) :- is_c_d(V), not no_overlap(V), mark(V,text). % @constraint Continuous by discrete for tick mark. -soft(c_d_tick) :- is_c_d, not no_overlap, mark(tick). +soft(c_d_tick,V) :- is_c_d(V), not no_overlap(V), mark(V,tick). % @constraint Continuous by discrete for point mark with no overlap. -soft(c_d_no_overlap_point) :- is_c_d, no_overlap, mark(point). +soft(c_d_no_overlap_point,V) :- is_c_d(V), no_overlap(V), mark(V,point). % @constraint Continuous by discrete for bar mark with no overlap. -soft(c_d_no_overlap_bar) :- is_c_d, no_overlap, mark(bar). +soft(c_d_no_overlap_bar,V) :- is_c_d(V), no_overlap(V), mark(V,bar). % @constraint Continuous by discrete for line mark with no overlap. -soft(c_d_no_overlap_line) :- is_c_d, no_overlap, mark(line). +soft(c_d_no_overlap_line,V) :- is_c_d(V), no_overlap(V), mark(V,line). % @constraint Continuous by discrete for area mark with no overlap. -soft(c_d_no_overlap_area) :- is_c_d, no_overlap, mark(area). +soft(c_d_no_overlap_area,V) :- is_c_d(V), no_overlap(V), mark(V,area). % @constraint Continuous by discrete for text mark with no overlap. -soft(c_d_no_overlap_text) :- is_c_d, no_overlap, mark(text). +soft(c_d_no_overlap_text,V) :- is_c_d(V), no_overlap(V), mark(V,text). % @constraint Continuous by discrete for tick mark with no overlap. -soft(c_d_no_overlap_tick) :- is_c_d, no_overlap, mark(tick). +soft(c_d_no_overlap_tick,V) :- is_c_d(V), no_overlap(V), mark(V,tick). % @constraint Discrete by discrete for point mark. -soft(d_d_point) :- is_d_d, mark(point). +soft(d_d_point,V) :- is_d_d(V), mark(V,point). % @constraint Discrete by discrete for point mark. -soft(d_d_text) :- is_d_d, mark(text). +soft(d_d_text,V) :- is_d_d(V), mark(V,text). % @constraint Discrete by discrete for point mark. -soft(d_d_rect) :- is_d_d, mark(rect). +soft(d_d_rect,V) :- is_d_d(V), mark(V,rect). % === Channel rankings à la APT === % @constraint Continuous on x channel. -soft(continuous_x,E) :- channel(E,x), continuous(E). +soft(continuous_x,V,E) :- channel(V,E,x), continuous(V,E). % @constraint Continuous on y channel. -soft(continuous_y,E) :- channel(E,y), continuous(E). +soft(continuous_y,V,E) :- channel(V,E,y), continuous(V,E). % @constraint Continuous on color channel. -soft(continuous_color,E) :- channel(E,color), continuous(E). +soft(continuous_color,V,E) :- channel(V,E,color), continuous(V,E). % @constraint Continuous on size channel. -soft(continuous_size,E) :- channel(E,size), continuous(E). +soft(continuous_size,V,E) :- channel(V,E,size), continuous(V,E). % @constraint Continuous on text channel. -soft(continuous_text,E) :- channel(E,text), continuous(E). +soft(continuous_text,V,E) :- channel(V,E,text), continuous(V,E). % @constraint Ordered on x channel. -soft(ordered_x,E) :- channel(E,x), discrete(E), not type(E,nominal). +soft(ordered_x,V,E) :- channel(V,E,x), discrete(V,E), not type(V,E,nominal). % @constraint Ordered on y channel. -soft(ordered_y,E) :- channel(E,y), discrete(E), not type(E,nominal). +soft(ordered_y,V,E) :- channel(V,E,y), discrete(V,E), not type(V,E,nominal). % @constraint Ordered on color channel. -soft(ordered_color,E) :- channel(E,color), discrete(E), not type(E,nominal). +soft(ordered_color,V,E) :- channel(V,E,color), discrete(V,E), not type(V,E,nominal). % @constraint Ordered on size channel. -soft(ordered_size,E) :- channel(E,size), discrete(E), not type(E,nominal). +soft(ordered_size,V,E) :- channel(V,E,size), discrete(V,E), not type(V,E,nominal). % @constraint Ordered on text channel. -soft(ordered_text,E) :- channel(E,text), discrete(E), not type(E,nominal). +soft(ordered_text,V,E) :- channel(V,E,text), discrete(V,E), not type(V,E,nominal). % @constraint Ordered on row channel. -soft(ordered_row,E) :- channel(E,row), discrete(E), not type(E,nominal). +soft(ordered_row,V,E) :- channel(V,E,row), discrete(V,E), not type(V,E,nominal). % @constraint Ordered on column channel. -soft(ordered_column,E) :- channel(E,column), discrete(E), not type(E,nominal). +soft(ordered_column,V,E) :- channel(V,E,column), discrete(V,E), not type(V,E,nominal). % @constraint Nominal on x channel. -soft(nominal_x,E) :- channel(E,x), type(E,nominal). +soft(nominal_x,V,E) :- channel(V,E,x), type(V,E,nominal). % @constraint Nominal on y channel. -soft(nominal_y,E) :- channel(E,y), type(E,nominal). +soft(nominal_y,V,E) :- channel(V,E,y), type(V,E,nominal). % @constraint Nominal on color channel. -soft(nominal_color,E) :- channel(E,color), type(E,nominal). +soft(nominal_color,V,E) :- channel(V,E,color), type(V,E,nominal). % @constraint Nominal on shape channel. -soft(nominal_shape,E) :- channel(E,shape), type(E,nominal). +soft(nominal_shape,V,E) :- channel(V,E,shape), type(V,E,nominal). % @constraint Nominal on text channel. -soft(nominal_text,E) :- channel(E,text), type(E,nominal). +soft(nominal_text,V,E) :- channel(V,E,text), type(V,E,nominal). % @constraint Nominal on row channel. -soft(nominal_row,E) :- channel(E,row), type(E,nominal). +soft(nominal_row,V,E) :- channel(V,E,row), type(V,E,nominal). % @constraint Nominal on column channel. -soft(nominal_column,E) :- channel(E,column), type(E,nominal). +soft(nominal_column,V,E) :- channel(V,E,column), type(V,E,nominal). % @constraint Nominal on detail channel. -soft(nominal_detail,E) :- channel(E,detail), type(E,nominal). +soft(nominal_detail,V,E) :- channel(V,E,detail), type(V,E,nominal). % @constraint Interesting on x channel. -soft(interesting_x,E) :- channel(E,x), enc_interesting(E). +soft(interesting_x,V,E) :- channel(V,E,x), enc_interesting(V,E). % @constraint Interesting on y channel. -soft(interesting_y,E) :- channel(E,y), enc_interesting(E). +soft(interesting_y,V,E) :- channel(V,E,y), enc_interesting(V,E). % @constraint Interesting on color channel. -soft(interesting_color,E) :- channel(E,color), enc_interesting(E). +soft(interesting_color,V,E) :- channel(V,E,color), enc_interesting(V,E). % @constraint Interesting on size channel. -soft(interesting_size,E) :- channel(E,size), enc_interesting(E). +soft(interesting_size,V,E) :- channel(V,E,size), enc_interesting(V,E). % @constraint Interesting on shape channel. -soft(interesting_shape,E) :- channel(E,shape), enc_interesting(E). +soft(interesting_shape,V,E) :- channel(V,E,shape), enc_interesting(V,E). % @constraint Interesting on text channel. -soft(interesting_text,E) :- channel(E,text), enc_interesting(E). +soft(interesting_text,V,E) :- channel(V,E,text), enc_interesting(V,E). % @constraint Interesting on row channel. -soft(interesting_row,E) :- channel(E,row), enc_interesting(E). +soft(interesting_row,V,E) :- channel(V,E,row), enc_interesting(V,E). % @constraint Interesting on column channel. -soft(interesting_column,E) :- channel(E,column), enc_interesting(E). +soft(interesting_column,V,E) :- channel(V,E,column), enc_interesting(V,E). % @constraint Interesting on detail channel. -soft(interesting_detail,E) :- channel(E,detail), enc_interesting(E). +soft(interesting_detail,V,E) :- channel(V,E,detail), enc_interesting(V,E). % === Aggregations === % @constraint Count as aggregate op. -soft(aggregate_count,E) :- aggregate(E,count). +soft(aggregate_count,V,E) :- aggregate(V,E,count). % @constraint Sum as aggregate op. -soft(aggregate_sum,E) :- aggregate(E,sum). +soft(aggregate_sum,V,E) :- aggregate(V,E,sum). % @constraint Mean as aggregate op. -soft(aggregate_mean,E) :- aggregate(E,mean). +soft(aggregate_mean,V,E) :- aggregate(V,E,mean). % @constraint Median as aggregate op. -soft(aggregate_median,E) :- aggregate(E,median). +soft(aggregate_median,V,E) :- aggregate(V,E,median). % @constraint Min as aggregate op. -soft(aggregate_min,E) :- aggregate(E,min). +soft(aggregate_min,V,E) :- aggregate(V,E,min). % @constraint Max as aggregate op. -soft(aggregate_max,E) :- aggregate(E,max). +soft(aggregate_max,V,E) :- aggregate(V,E,max). % @constraint Standard Deviation as aggregate op. -soft(aggregate_stdev,E) :- aggregate(E,stdev). +soft(aggregate_stdev,V,E) :- aggregate(V,E,stdev). % === Stack === % @constraint Zero base for stack op. -soft(stack_zero) :- stack(zero). +soft(stack_zero,V) :- stack(V,zero). % @constraint Normalize between groupbys as stack op. -soft(stack_normalize) :- stack(normalize). +soft(stack_normalize,V) :- stack(V,normalize). % === Task - marktype correlations === % @constraint Point mark for value tasks. -soft(value_point) :- task(value), mark(point). +soft(value_point,V) :- task(V,value), mark(V,point). % @constraint Bar mark for value tasks. -soft(value_bar) :- task(value), mark(bar). +soft(value_bar,V) :- task(V,value), mark(V,bar). % @constraint Line mark for value tasks. -soft(value_line) :- task(value), mark(line). +soft(value_line,V) :- task(V,value), mark(V,line). % @constraint Area mark for value tasks. -soft(value_area) :- task(value), mark(area). +soft(value_area,V) :- task(V,value), mark(V,area). % @constraint Text mark for value tasks. -soft(value_text) :- task(value), mark(text). +soft(value_text,V) :- task(V,value), mark(V,text). % @constraint Tick mark for value tasks. -soft(value_tick) :- task(value), mark(tick). +soft(value_tick,V) :- task(V,value), mark(V,tick). % @end % @constraint Rect mark for value tasks. -soft(value_rect) :- task(value), mark(rect). +soft(value_rect,V) :- task(V,value), mark(V,rect). % @constraint Point mark for summary tasks. -soft(summary_point) :- task(summary), mark(point). +soft(summary_point,V) :- task(V,summary), mark(V,point). % @constraint Bar mark for summary tasks. -soft(summary_bar) :- task(summary), mark(bar). +soft(summary_bar,V) :- task(V,summary), mark(V,bar). % @constraint Line mark for summary tasks. -soft(summary_line) :- task(summary), mark(line). +soft(summary_line,V) :- task(V,summary), mark(V,line). % @constraint Area mark for summary tasks. -soft(summary_area) :- task(summary), mark(area). +soft(summary_area,V) :- task(V,summary), mark(V,area). % @constraint Text mark for summary tasks. -soft(summary_text) :- task(summary), mark(text). +soft(summary_text,V) :- task(V,summary), mark(V,text). % @constraint Tick mark for summary tasks. -soft(summary_tick) :- task(summary), mark(tick). +soft(summary_tick,V) :- task(V,summary), mark(V,tick). % @constraint Rect mark for summary tasks. -soft(summary_rect) :- task(summary), mark(rect). +soft(summary_rect,V) :- task(V,summary), mark(V,rect). % === Task - channel correlations === % @constraint Continuous x for value tasks. -soft(value_continuous_x,E) :- task(value), channel(E,x), continuous(E), enc_interesting(E). +soft(value_continuous_x,V,E) :- task(V,value), channel(V,E,x), continuous(V,E), enc_interesting(V,E). % @constraint Continuous y for value tasks. -soft(value_continuous_y,E) :- task(value), channel(E,y), continuous(E), enc_interesting(E). +soft(value_continuous_y,V,E) :- task(V,value), channel(V,E,y), continuous(V,E), enc_interesting(V,E). % @constraint Continuous color for value tasks. -soft(value_continuous_color,E) :- task(value), channel(E,color), continuous(E), enc_interesting(E). +soft(value_continuous_color,V,E) :- task(V,value), channel(V,E,color), continuous(V,E), enc_interesting(V,E). % @constraint Continuous size for value tasks. -soft(value_continuous_size,E) :- task(value), channel(E,size), continuous(E), enc_interesting(E). +soft(value_continuous_size,V,E) :- task(V,value), channel(V,E,size), continuous(V,E), enc_interesting(V,E). % @constraint Continuous text for value tasks. -soft(value_continuous_text,E) :- task(value), channel(E,text), continuous(E), enc_interesting(E). +soft(value_continuous_text,V,E) :- task(V,value), channel(V,E,text), continuous(V,E), enc_interesting(V,E). % @constraint Discrete x for value tasks. -soft(value_discrete_x,E) :- task(value), channel(E,x), discrete(E), enc_interesting(E). +soft(value_discrete_x,V,E) :- task(V,value), channel(V,E,x), discrete(V,E), enc_interesting(V,E). % @constraint Discrete y for value tasks. -soft(value_discrete_y,E) :- task(value), channel(E,y), discrete(E), enc_interesting(E). +soft(value_discrete_y,V,E) :- task(V,value), channel(V,E,y), discrete(V,E), enc_interesting(V,E). % @constraint Discrete color for value tasks. -soft(value_discrete_color,E) :- task(value), channel(E,color), discrete(E), enc_interesting(E). +soft(value_discrete_color,V,E) :- task(V,value), channel(V,E,color), discrete(V,E), enc_interesting(V,E). % @constraint Discrete shape for value tasks. -soft(value_discrete_shape,E) :- task(value), channel(E,shape), discrete(E), enc_interesting(E). +soft(value_discrete_shape,V,E) :- task(V,value), channel(V,E,shape), discrete(V,E), enc_interesting(V,E). % @constraint Discrete size for value tasks. -soft(value_discrete_size,E) :- task(value), channel(E,size), discrete(E), enc_interesting(E). +soft(value_discrete_size,V,E) :- task(V,value), channel(V,E,size), discrete(V,E), enc_interesting(V,E). % @constraint Discrete text for value tasks. -soft(value_discrete_text,E) :- task(value), channel(E,text), discrete(E), enc_interesting(E). +soft(value_discrete_text,V,E) :- task(V,value), channel(V,E,text), discrete(V,E), enc_interesting(V,E). % @constraint Discrete row for value tasks. -soft(value_discrete_row,E) :- task(value), channel(E,row), discrete(E), enc_interesting(E). +soft(value_discrete_row,V,E) :- task(V,value), channel(V,E,row), discrete(V,E), enc_interesting(V,E). % @constraint Discrete column for value tasks. -soft(value_discrete_column,E) :- task(value), channel(E,column), discrete(E), enc_interesting(E). +soft(value_discrete_column,E) :- task(V,value), channel(V,E,column), discrete(V,E), enc_interesting(V,E). % @constraint Continuous x for summary tasks. -soft(summary_continuous_x,E) :- task(summary), channel(E,x), continuous(E), enc_interesting(E). +soft(summary_continuous_x,E) :- task(V,summary), channel(V,E,x), continuous(V,E), enc_interesting(V,E). % @constraint Continuous y for summary tasks. -soft(summary_continuous_y,E) :- task(summary), channel(E,y), continuous(E), enc_interesting(E). +soft(summary_continuous_y,E) :- task(V,summary), channel(V,E,y), continuous(V,E), enc_interesting(V,E). % @constraint Continuous color for summary tasks. -soft(summary_continuous_color,E) :- task(summary), channel(E,color), continuous(E), enc_interesting(E). +soft(summary_continuous_color,E) :- task(V,summary), channel(V,E,color), continuous(V,E), enc_interesting(V,E). % @constraint Continuous size for summary tasks. -soft(summary_continuous_size,E) :- task(summary), channel(E,size), continuous(E), enc_interesting(E). +soft(summary_continuous_size,E) :- task(V,summary), channel(V,E,size), continuous(V,E), enc_interesting(V,E). % @constraint Continuous text for summary tasks. -soft(summary_continuous_text,E) :- task(summary), channel(E,text), continuous(E), enc_interesting(E). +soft(summary_continuous_text,E) :- task(V,summary), channel(V,E,text), continuous(V,E), enc_interesting(V,E). % @constraint Discrete x for summary tasks. -soft(summary_discrete_x,E) :- task(summary), channel(E,x), discrete(E), enc_interesting(E). +soft(summary_discrete_x,E) :- task(V,summary), channel(V,E,x), discrete(V,E), enc_interesting(V,E). % @constraint Discrete y for summary tasks. -soft(summary_discrete_y,E) :- task(summary), channel(E,y), discrete(E), enc_interesting(E). +soft(summary_discrete_y,E) :- task(V,summary), channel(V,E,y), discrete(V,E), enc_interesting(V,E). % @constraint Discrete color for summary tasks. -soft(summary_discrete_color,E) :- task(summary), channel(E,color), discrete(E), enc_interesting(E). +soft(summary_discrete_color,E) :- task(V,summary), channel(V,E,color), discrete(V,E), enc_interesting(V,E). % @constraint Discrete shape for summary tasks. -soft(summary_discrete_shape,E) :- task(summary), channel(E,shape), discrete(E), enc_interesting(E). +soft(summary_discrete_shape,E) :- task(V,summary), channel(V,E,shape), discrete(V,E), enc_interesting(V,E). % @constraint Discrete size for summary tasks. -soft(summary_discrete_size,E) :- task(summary), channel(E,size), discrete(E), enc_interesting(E). +soft(summary_discrete_size,E) :- task(V,summary), channel(V,E,size), discrete(V,E), enc_interesting(V,E). % @constraint Discrete text for summary tasks. -soft(summary_discrete_text,E) :- task(summary), channel(E,text), discrete(E), enc_interesting(E). +soft(summary_discrete_text,E) :- task(V,summary), channel(V,E,text), discrete(V,E), enc_interesting(V,E). % @constraint Discrete row for summary tasks. -soft(summary_discrete_row,E) :- task(summary), channel(E,row), discrete(E), enc_interesting(E). +soft(summary_discrete_row,E) :- task(V,summary), channel(V,E,row), discrete(V,E), enc_interesting(V,E). % @constraint Discrete column for summary tasks. -soft(summary_discrete_column,E) :- task(summary), channel(E,column), discrete(E), enc_interesting(E). \ No newline at end of file +soft(summary_discrete_column,E) :- task(V,summary), channel(V,E,column), discrete(V,E), enc_interesting(V,E). + +% @constraint Tiebreaker to keep fields on x and y consistent. +soft(x_y_fields_order,V) :- field(V,EX,F1), field(V,EY,F2), channel(V,EX,x), channel(V,EY,y), F1 > F2. + +% @constraint Rect without aggregate +% soft(d_d_rect_point_no_agg,V,none) :- mark(V,(point;rect)), is_d_d(V), not aggregate(V,_,_). diff --git a/asp/weights.lp b/asp/weights.lp index 1645cf1..4f804c2 100644 --- a/asp/weights.lp +++ b/asp/weights.lp @@ -3,7 +3,7 @@ #const type_q_weight = 0. #const type_o_weight = 1. #const type_n_weight = 2. -#const aggregate_weight = 1. +#const aggregate_weight = 4. #const bin_weight = 2. #const bin_high_weight = 10. #const bin_low_weight = 6. @@ -13,24 +13,27 @@ #const same_field_gte3_weight = 16. #const count_twice_weight = 50. #const shape_cardinality_weight = 5. -#const number_nominal_weight = 10. +#const string_non_nominal_weight = 100. +#const number_nominal_weight = 50. +#const number_high_cardinality_ordinal_weight = 50. #const bin_cardinality_weight = 5. #const quant_bin_weight = 1. #const agg_dim_weight = 2. #const only_discrete_weight = 30. #const multiple_non_pos_weight = 3. -#const non_positional_pref_weight = 10. -#const aggregate_group_by_raw_weight = 3. +#const non_positional_pref_weight = 40. +#const aggregate_group_by_raw_weight = 20. #const x_y_raw_weight = 1. #const log_weight = 1. #const zero_weight = 1. +#const zero_bin_weight = 1. #const zero_size_weight = 3. #const zero_positional_weight = 1. #const zero_skew_weight = 5. #const includes_zero_weight = 10. #const only_x_weight = 1. -#const orientation_binned_weight = 1. +#const orientation_binned_weight = 2. #const high_cardinality_ordinal_weight = 10. #const high_cardinality_nominal_weight = 10. #const high_cardinality_nominal_color_weight = 10. @@ -67,7 +70,7 @@ #const c_d_text_weight = 50. #const c_d_tick_weight = 0. -#const c_d_no_overlap_point_weight = 20. +#const c_d_no_overlap_point_weight = 10. #const c_d_no_overlap_bar_weight = 0. #const c_d_no_overlap_line_weight = 20. #const c_d_no_overlap_area_weight = 20. @@ -94,12 +97,12 @@ #const nominal_x_weight = 3. #const nominal_y_weight = 0. -#const nominal_color_weight = 10. -#const nominal_shape_weight = 11. -#const nominal_text_weight = 12. -#const nominal_row_weight = 7. -#const nominal_column_weight = 10. -#const nominal_detail_weight = 20. +#const nominal_color_weight = 6. +#const nominal_shape_weight = 10. +#const nominal_text_weight = 15. +#const nominal_row_weight = 8. +#const nominal_column_weight = 9. +#const nominal_detail_weight = 30. #const interesting_x_weight = 0. #const interesting_y_weight = 1. @@ -163,3 +166,5 @@ #const stack_zero_weight = 0. #const stack_normalize_weight = 1. +#const x_y_fields_order_weight = 1. +#const rect_no_agg_weight = 40. diff --git a/data/weights.json b/data/weights.json index 49d8cbf..dbf161b 100644 --- a/data/weights.json +++ b/data/weights.json @@ -2,7 +2,7 @@ "type_q_weight": 0, "type_o_weight": 1, "type_n_weight": 2, - "aggregate_weight": 1, + "aggregate_weight": 4, "bin_weight": 2, "bin_high_weight": 10, "bin_low_weight": 6, @@ -12,6 +12,7 @@ "same_field_gte3_weight": 16, "count_twice_weight": 50, "shape_cardinality_weight": 5, + "string_non_nominal_weight": 4, "number_nominal_weight": 10, "bin_cardinality_weight": 5, "quant_bin_weight": 1, @@ -19,16 +20,17 @@ "only_discrete_weight": 30, "multiple_non_pos_weight": 3, "non_positional_pref_weight": 10, - "aggregate_group_by_raw_weight": 3, + "aggregate_group_by_raw_weight": 10, "x_y_raw_weight": 1, "log_weight": 1, "zero_weight": 1, + "zero_bin_weight": 1, "zero_size_weight": 3, "zero_positional_weight": 1, "zero_skew_weight": 5, "includes_zero_weight": 10, "only_x_weight": 1, - "orientation_binned_weight": 1, + "orientation_binned_weight": 2, "high_cardinality_ordinal_weight": 10, "high_cardinality_nominal_weight": 10, "high_cardinality_nominal_color_weight": 10, @@ -88,8 +90,8 @@ "nominal_shape_weight": 11, "nominal_text_weight": 12, "nominal_row_weight": 7, - "nominal_column_weight": 10, - "nominal_detail_weight": 20, + "nominal_column_weight": 9, + "nominal_detail_weight": 30, "interesting_x_weight": 0, "interesting_y_weight": 1, "interesting_color_weight": 2, diff --git a/draco/js.py b/draco/js.py index a57e0a3..fd586a1 100644 --- a/draco/js.py +++ b/draco/js.py @@ -39,7 +39,6 @@ def asp2vl(asp: List[str]) -> Dict: if stderr: logger.error("stderr: %s", stderr) - print(stdout) return json.loads(stdout) diff --git a/draco/run.py b/draco/run.py index 7291a83..67785c5 100644 --- a/draco/run.py +++ b/draco/run.py @@ -12,6 +12,7 @@ import clyngor from clyngor.answers import Answers + from draco.js import asp2vl logging.basicConfig(level=logging.INFO) @@ -26,6 +27,10 @@ "assign_weights.lp", "optimize.lp", "output.lp", + "compare.lp", + "assign_compare_weights.lp", + "compare_hard.lp", + "compare_weights.lp" ] DRACO_LP_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../asp") @@ -34,30 +39,71 @@ class Result: - props: List[str] + props: Dict[str,List[str]] cost: Optional[int] violations: Dict[str, int] def __init__(self, answers: Answers, cost: Optional[int] = None) -> None: violations: Dict[str, int] = defaultdict(int) - props: List[str] = [] + draco: Dict[str, int] = defaultdict(int) + draco_list = [] + graphscape: Dict[str, int] = defaultdict(int) + graphscape_list = [] + draco_weights: Dict[str, int] = defaultdict(int) + graphscape_weights: Dict[str, int] = defaultdict(int) + + props: Dict[str,List[str]] = {} for ((head, body),) in answers: if head == "cost": cost = int(body[0]) elif head == "soft": violations[body[0]] += 1 + draco[body[0]] += 1 + draco_list.append(body) + elif head == "compare": + violations[body[0]] += 1 + graphscape[body[0]] += 1 + graphscape_list.append(body) + elif head == "soft_weight": + draco_weights[body[0]] = body[1] + elif head == "compare_weight": + graphscape_weights[body[0]] = body[1] else: + name = body[0] b = ",".join(map(str, body)) - props.append(f"{head}({b}).") + if (name not in props): + props[name] = [] + + props[name].append(f"{head}({b}).") + + # print(draco_weights) + # print(draco) + draco_weight = sum([v * draco_weights[k] for k,v in draco.items()]) + graphscape_weight = sum([v * graphscape_weights[k] for k,v in graphscape.items()]) + cost = draco_weight + graphscape_weight + + + # print(graphscape_list) + # if ('\"view\"' in props): + # print('\n'.join(props["\"view\""])) + # print() self.props = props self.violations = violations + self.draco = draco + self.graphscape = graphscape + self.draco_weights = draco_weights + self.graphscape_weights = graphscape_weights + self.draco_list = draco_list + self.graphscape_list = graphscape_list self.cost = cost + self.d = draco_weight + self.g = graphscape_weight - def as_vl(self) -> Dict: - return asp2vl(self.props) - + def as_vl(self,v) -> Dict: + specs = asp2vl(self.props[v]) + return specs[v] def load_file(path: str) -> bytes: content = file_cache.get(path) @@ -75,16 +121,24 @@ def run_clingo( files: List[str] = None, silence_warnings=False, debug=False, + topk=False, + k=1, ) -> Tuple[str, str]: """ Run draco and return stderr and stdout """ - # default args files = files or DRACO_LP + files = files.copy() constants = constants or {} - options = ["--outf=2", "--quiet=1,2,2"] + options = ["--outf=2", "--quiet=1,2,2", "--seed=0"] + + if (topk): + files.append('topk-py.lp') + options.append('--opt-mode=OptN') + options.append("--models={0}".format(k)) + if silence_warnings: options.append("--warn=no-atom-undefined") for name, value in constants.items(): @@ -99,6 +153,7 @@ def run_clingo( program = "\n".join(draco_query) file_names = [os.path.join(DRACO_LP_DIR, f) for f in files] + asp_program = b"\n".join(map(load_file, file_names)) + program.encode("utf8") if debug: @@ -106,9 +161,8 @@ def run_clingo( fd.write(program) logger.info('Debug ASP with "clingo %s %s"', " ".join(file_names), fd.name) - + stdout, stderr = proc.communicate(asp_program) - return (stderr, stdout) @@ -119,6 +173,8 @@ def run( silence_warnings=False, debug=False, clear_cache=False, + topk=False, + k=1, ) -> Optional[Result]: """ Run clingo to compute a completion of a partial spec or violations. """ @@ -127,7 +183,7 @@ def run( logger.warning("Cleared file cache") file_cache.clear() - stderr, stdout = run_clingo(draco_query, constants, files, silence_warnings, debug) + stderr, stdout = run_clingo(draco_query, constants, files, silence_warnings, debug, topk, k) try: json_result = json.loads(stdout) @@ -142,18 +198,32 @@ def run( result = json_result["Result"] if result == "UNSATISFIABLE": - logger.info("Constraints are unsatisfiable.") + # logger.info("Constraints are unsatisfiable.") + if topk and json_result["Calls"] > 1: + return run(draco_query, constants, files, silence_warnings, debug, clear_cache, topk, json_result["Calls"] - 1) return None elif result == "OPTIMUM FOUND": - # get the last witness, which is the best result - answers = json_result["Call"][0]["Witnesses"][-1] - - logger.debug(answers["Value"]) - - return Result( - clyngor.Answers(answers["Value"]).sorted, - cost=json_result["Models"]["Costs"][0], - ) + if (not topk): + # get the last witness, which is the best result + answers = json_result["Call"][0]["Witnesses"][-1] + + logger.debug(answers["Value"]) + + result = Result( + clyngor.Answers(answers["Value"]).sorted + ) + + return result + else: + results = [] + + for call in json_result["Call"]: + for answers in call["Witnesses"]: + result = Result( + clyngor.Answers(answers["Value"]).sorted + ) + results.append(result) + return results elif result == "SATISFIABLE": answers = json_result["Call"][0]["Witnesses"][-1] diff --git a/examples/multi.py b/examples/multi.py new file mode 100644 index 0000000..15162e0 --- /dev/null +++ b/examples/multi.py @@ -0,0 +1,141 @@ +from draco.run import run + +# program = """% ====== Data definitions ====== +# data("cars.json"). +# num_rows(142). + +# fieldtype(horsepower,number). +# cardinality(horsepower,94). + +# fieldtype(acceleration,number). +# cardinality(acceleration,96). + +# % ====== Query constraints ====== +# view(v1). + +# encoding(v1,e0). +# :- not field(v1,e0,acceleration). + +# encoding(v1,e1). +# :- not field(v1,e1,horsepower).""" + +# asp = program.split('\n') + +# result = run(asp) + +# print('{0}'.format('\n'.join(result.props))) + + + +# program = """% ====== Data definitions ====== +# data("cars.json"). +# num_rows(142). + +# fieldtype(horsepower,number). +# cardinality(horsepower,94). + +# fieldtype(acceleration,number). +# cardinality(acceleration,96). + +# % ====== Query constraints ====== +# view(v1). +# data("cars.json"). +# type(v1,e0,quantitative). +# type(v1,e1,quantitative). +# field(v1,e0,acceleration). +# field(v1,e1,horsepower). +# channel(v1,e0,x). +# channel(v1,e1,y). +# zero(v1,e0). +# zero(v1,e1). +# mark(v1,point).""" + +# asp = program.split('\n') +# result = run(asp) + +# print('{0}'.format('\n'.join(result.props))) + + + +program = """view("view"). +num_rows(406). + +fieldtype("Acceleration",number). +cardinality("Acceleration", 96). +fieldtype("Cylinders",number). +cardinality("Cylinders", 5). +fieldtype("Displacement",number). +cardinality("Displacement", 83). +fieldtype("Horsepower",number). +cardinality("Horsepower", 94). +fieldtype("Miles_per_Gallon",number). +cardinality("Miles_per_Gallon", 130). +fieldtype("Name",string). +cardinality("Name", 311). +fieldtype("Origin",string). +cardinality("Origin", 3). +fieldtype("Weight_in_lbs",number). +cardinality("Weight_in_lbs", 356). +fieldtype("Year",number). +cardinality("Year", 12). + +mark("view",point). +encoding("view",e0). +:- not field("view",e0,"Horsepower"). +aggregate("view",e0,mean). +channel("view",e0,x). +encoding("view",e1). +:- not field("view",e1,"Miles_per_Gallon"). +view("first"). +num_rows(406). + +fieldtype("Acceleration",number). +cardinality("Acceleration", 96). +fieldtype("Cylinders",number). +cardinality("Cylinders", 5). +fieldtype("Displacement",number). +cardinality("Displacement", 83). +fieldtype("Horsepower",number). +cardinality("Horsepower", 94). +fieldtype("Miles_per_Gallon",number). +cardinality("Miles_per_Gallon", 130). +fieldtype("Name",string). +cardinality("Name", 311). +fieldtype("Origin",string). +cardinality("Origin", 3). +fieldtype("Weight_in_lbs",number). +cardinality("Weight_in_lbs", 356). +fieldtype("Year",number). +cardinality("Year", 12). + +encoding("first",e0). +base("first"). +:- not field("first",e0,"Horsepower"). +aggregate("first",e0,mean). +channel("first",e0,x). +encoding("first",e1). +:- not field("first",e1,"Miles_per_Gallon"). +view("first"). +encoding("first",e0). +encoding("first",e1). +aggregate("first",e0,mean). +channel("first",e0,x). +bin("first",e1,10). +type("first",e0,quantitative). +type("first",e1,quantitative). +field("first",e0,"Horsepower"). +field("first",e1,"Miles_per_Gallon"). +channel("first",e1,y). +zero("first",e0). +mark("first",bar). +:- not { encoding("first",_) } = 2. +:- not { channel("first",_,_) } = 2. +:- not { bin("first",_,_) } = 1. +:- not { type("first",_,_) } = 2. +:- not { field("first",_,_) } = 2. +:- not { zero("first",_) } = 1.""" + +asp = program.split('\n') +result = run(asp) + +print('{0}'.format('\n'.join(result.props))) \ No newline at end of file diff --git a/js/src/asp2vl.ts b/js/src/asp2vl.ts index 959f3e5..3c543b9 100644 --- a/js/src/asp2vl.ts +++ b/js/src/asp2vl.ts @@ -1,11 +1,31 @@ import { TopLevelFacetedUnitSpec } from 'vega-lite/build/src/spec'; -const REGEX = /(\w+)\(([\w\.\/]+)(,([\w\.]+))?\)/; +const REGEX = /(\w+)\(([\w\.\/]+)(,([\w\.]+))?(,([\w\.]+))?\)/; +const V_REGEX = /view\((.*)\)./; /** * Convert from ASP to Vega-Lite. */ -export default function asp2vl(facts: string[]): TopLevelFacetedUnitSpec { +export default function asp2vl(facts: string[]): { [name: string]: TopLevelFacetedUnitSpec } { + const visualizations = facts + .filter(fact => { + const extract = V_REGEX.exec(fact); + return extract !== null; + }) + .map(fact => { + const extract = V_REGEX.exec(fact); + return extract[1]; + }); + + const result = visualizations.reduce((dict, v) => { + dict[v] = asp2vl_single(facts, v); + return dict; + }, {}); + + return result; +} + +function asp2vl_single(facts: string[], v: string) { let mark = ''; let url = 'data/cars.json'; // default dataset const encodings: { [enc: string]: any } = {}; @@ -14,7 +34,11 @@ export default function asp2vl(facts: string[]): TopLevelFacetedUnitSpec { // TODO: Better handle quoted fields. We currently simply remove all ". const cleanedValue = value.replace(/\"/g, ''); const negSymbol = value.trim().startsWith(':-'); // TODO: remove this - const [_, predicate, first, __, second] = REGEX.exec(cleanedValue) as any; + const [_, predicate, viz, __, first, ___, second] = REGEX.exec(cleanedValue) as any; + + if (viz !== v.replace(/\"/g, '') || predicate === 'view') { + continue; + } if (predicate === 'mark') { mark = first; @@ -36,13 +60,13 @@ export default function asp2vl(facts: string[]): TopLevelFacetedUnitSpec { const enc = encodings[e]; // if quantitative encoding and zero is not set, set zero to false - if (enc.type === 'quantitative' && enc.zero === undefined && enc.bin === undefined) { + if (enc.type === 'quantitative' && typeof enc.zero === 'undefined' && typeof enc.bin === 'undefined') { enc.zero = false; } const scale = { ...(enc.log ? { type: 'log' } : {}), - ...(enc.zero === undefined ? {} : enc.zero ? { zero: true } : { zero: false }), + ...(typeof enc.zero === 'undefined' ? {} : enc.zero ? { zero: true } : { zero: false }), }; encoding[enc.channel] = { @@ -50,7 +74,7 @@ export default function asp2vl(facts: string[]): TopLevelFacetedUnitSpec { ...(enc.aggregate ? { aggregate: enc.aggregate } : {}), ...(enc.field ? { field: enc.field } : {}), ...(enc.stack ? { stack: enc.stack } : {}), - ...(enc.bin !== undefined ? (+enc.bin === 10 ? { bin: true } : { bin: { maxbins: +enc.bin } }) : {}), + ...(typeof enc.bin !== 'undefined' ? (+enc.bin === 10 ? { bin: true } : { bin: { maxbins: +enc.bin } }) : {}), ...(Object.keys(scale).length ? { scale } : {}), }; } diff --git a/js/src/cql2asp.ts b/js/src/cql2asp.ts index 6911684..ddfc100 100644 --- a/js/src/cql2asp.ts +++ b/js/src/cql2asp.ts @@ -3,10 +3,10 @@ const HOLE = '?'; export default function cql2asp(spec: any) { const mark = subst_if_hole(spec.mark); - const facts = []; + const facts = ['view(v1).']; if (mark) { - facts.push(`mark(${spec.mark}).`); + facts.push(`mark(v1,${spec.mark}).`); } if ('data' in spec && 'url' in spec.data) { @@ -16,7 +16,7 @@ export default function cql2asp(spec: any) { for (let i = 0; i < spec.encodings.length; i++) { const enc = spec.encodings[i]; const eid = `e${i}`; - facts.push(`encoding(${eid}).`); + facts.push(`encoding(v1,${eid}).`); let encFieldType = null; let encZero = null; @@ -44,39 +44,39 @@ export default function cql2asp(spec: any) { if ('zero' in fieldContent) { encZero = fieldContent.zero; if (fieldContent.zero) { - facts.push(`zero(${eid}).`); + facts.push(`zero(v1,${eid}).`); } else { - facts.push(`:- zero(${eid}).`); + facts.push(`:- zero(v1,${eid}).`); } } if ('log' in fieldContent) { if (fieldContent.log) { - facts.push(`log(${eid}).`); + facts.push(`log(v1,${eid}).`); } else { - facts.push(`:-log(${eid}).`); + facts.push(`:-log(v1,${eid}).`); } } } else if (field === 'bin') { if (fieldContent.maxbins) { facts.push(`${field}(${eid},${fieldContent.maxbins}).`); } else if (fieldContent) { - facts.push(`:- not bin(${eid},_).`); + facts.push(`:- not bin(v1,${eid},_).`); } else { - facts.push(`:- bin(${eid},_).`); + facts.push(`:- bin(v1,${eid},_).`); } } else if (field === 'field') { // fields can have spaces and start with capital letters - facts.push(`${field}(${eid},"${fieldContent}").`); + facts.push(`${field}(v1,${eid},"${fieldContent}").`); } else { // translate normal fields if (field !== 'bin') { - facts.push(`${field}(${eid},${fieldContent}).`); + facts.push(`${field}(v1,${eid},${fieldContent}).`); } } } if (encFieldType === 'quantitative' && encZero === null && encBinned === null) { - facts.push(`zero(${eid}).`); + facts.push(`zero(v1,${eid}).`); } } diff --git a/output.json b/output.json new file mode 100644 index 0000000..71be386 --- /dev/null +++ b/output.json @@ -0,0 +1,74 @@ +{ + "Solver": "clingo version 5.3.0", + "Input": ["test2.lp"], + "Call": [ + { + "Witnesses": [ + { + "Value": [ + "view(\"view\")", + "encoding(\"view\",e0)", + "encoding(\"view\",e1)", + "encoding(\"view\",1)", + "mark(\"view\",bar)", + "zero(\"view\",1)", + "aggregate(\"view\",1,count)", + "channel(\"view\",1,x)", + "channel(\"view\",e1,y)", + "channel(\"view\",e0,color)", + "field(\"view\",e0,\"MPAA_Rating\")", + "field(\"view\",e1,\"Major_Genre\")", + "soft(aggregate,\"view\",1)", + "soft(encoding,\"view\",e0)", + "soft(encoding,\"view\",e1)", + "soft(encoding,\"view\",1)", + "soft(encoding_field,\"view\",e0)", + "soft(encoding_field,\"view\",e1)", + "soft(high_cardinality_nominal,\"view\",e1)", + "soft(type_q,\"view\",1)", + "soft(type_n,\"view\",e0)", + "soft(type_n,\"view\",e1)", + "soft(nominal_y,\"view\",e1)", + "soft(nominal_color,\"view\",e0)", + "soft(aggregate_count,\"view\",1)", + "stack(\"view\",1,zero)", + "type(\"view\",e0,nominal)", + "type(\"view\",e1,nominal)", + "type(\"view\",1,quantitative)", + "soft(continuous_x,\"view\",1)", + "soft_weight(continuous_x,0)", + "soft_weight(aggregate,4)", + "soft_weight(encoding,0)", + "soft_weight(encoding_field,6)", + "soft_weight(high_cardinality_nominal,10)", + "soft_weight(type_q,0)", + "soft_weight(type_n,2)", + "soft_weight(nominal_y,0)", + "soft_weight(nominal_color,6)", + "soft_weight(aggregate_count,0)", + "soft(c_d_no_overlap_bar,\"view\",_placeholder)", + "soft(stack_zero,\"view\",_placeholder)", + "soft_weight(c_d_no_overlap_bar,0)", + "soft_weight(stack_zero,0)" + ] + } + ] + } + ], + "Result": "OPTIMUM FOUND", + "Models": { + "Number": 2, + "More": "no", + "Optimum": "yes", + "Optimal": 1, + "Costs": [36] + }, + "Calls": 1, + "Time": { + "Total": 0.076, + "Solve": 0.0, + "Model": 0.0, + "Unsat": 0.0, + "CPU": 0.076 + } +} diff --git a/output2.json b/output2.json new file mode 100644 index 0000000..b5b9ab6 --- /dev/null +++ b/output2.json @@ -0,0 +1,74 @@ +{ + "Solver": "clingo version 5.3.0", + "Input": ["test2.lp"], + "Call": [ + { + "Witnesses": [ + { + "Value": [ + "view(\"view\")", + "encoding(\"view\",e0)", + "encoding(\"view\",e1)", + "mark(\"view\",bar)", + "soft(encoding,\"view\",e0)", + "soft(encoding,\"view\",e1)", + "soft_weight(encoding,0)", + "encoding(\"view\",1)", + "channel(\"view\",1,x)", + "channel(\"view\",e1,y)", + "channel(\"view\",e0,color)", + "field(\"view\",e0,\"MPAA_Rating\")", + "field(\"view\",e1,\"Major_Genre\")", + "aggregate(\"view\",1,count)", + "type(\"view\",e0,nominal)", + "type(\"view\",e1,nominal)", + "zero(\"view\",1)", + "type(\"view\",1,quantitative)", + "stack(\"view\",zero)", + "soft(c_d_no_overlap_bar,\"view\",_placeholder)", + "soft(stack_zero,\"view\",_placeholder)", + "soft(aggregate,\"view\",1)", + "soft(encoding,\"view\",1)", + "soft(encoding_field,\"view\",e0)", + "soft(encoding_field,\"view\",e1)", + "soft(high_cardinality_nominal,\"view\",e1)", + "soft(type_q,\"view\",1)", + "soft(type_n,\"view\",e0)", + "soft(type_n,\"view\",e1)", + "soft(continuous_x,\"view\",1)", + "soft(nominal_y,\"view\",e1)", + "soft(nominal_color,\"view\",e0)", + "soft(aggregate_count,\"view\",1)", + "soft_weight(c_d_no_overlap_bar,0)", + "soft_weight(stack_zero,0)", + "soft_weight(aggregate,4)", + "soft_weight(encoding_field,6)", + "soft_weight(high_cardinality_nominal,10)", + "soft_weight(type_q,0)", + "soft_weight(type_n,2)", + "soft_weight(continuous_x,0)", + "soft_weight(nominal_y,0)", + "soft_weight(nominal_color,6)", + "soft_weight(aggregate_count,0)" + ] + } + ] + } + ], + "Result": "OPTIMUM FOUND", + "Models": { + "Number": 9, + "More": "no", + "Optimum": "yes", + "Optimal": 1, + "Costs": [36] + }, + "Calls": 1, + "Time": { + "Total": 0.079, + "Solve": 0.001, + "Model": 0.0, + "Unsat": 0.0, + "CPU": 0.078 + } +}