liquid_feedback_core
changeset 167:de59f6b1daf3
Allow to require BOTH direct AND indirect (super)majorities in combination
author | jbe |
---|---|
date | Sun Jun 05 18:59:40 2011 +0200 (2011-06-05) |
parents | 7f2011c7b95e |
children | 9d6fe34d8bbb |
files | core.sql demo.sql |
line diff
1.1 --- a/core.sql Sun Jun 05 01:12:37 2011 +0200 1.2 +++ b/core.sql Sun Jun 05 18:59:40 2011 +0200 1.3 @@ -319,14 +319,18 @@ 1.4 "issue_quorum_den" INT4 NOT NULL, 1.5 "initiative_quorum_num" INT4 NOT NULL, 1.6 "initiative_quorum_den" INT4 NOT NULL, 1.7 - "majority_num" INT4 NOT NULL DEFAULT 1, 1.8 - "majority_den" INT4 NOT NULL DEFAULT 2, 1.9 - "majority_strict" BOOLEAN NOT NULL DEFAULT TRUE, 1.10 - "majority_positive" INT4 NOT NULL DEFAULT 0, 1.11 - "majority_non_negative" INT4 NOT NULL DEFAULT 0, 1.12 - "majority_indirect" BOOLEAN NOT NULL DEFAULT TRUE, 1.13 - "no_reverse_beat_path" BOOLEAN NOT NULL DEFAULT TRUE, 1.14 - "no_multistage_majority" BOOLEAN NOT NULL DEFAULT FALSE ); 1.15 + "direct_majority_num" INT4 NOT NULL DEFAULT 1, 1.16 + "direct_majority_den" INT4 NOT NULL DEFAULT 2, 1.17 + "direct_majority_strict" BOOLEAN NOT NULL DEFAULT TRUE, 1.18 + "direct_majority_positive" INT4 NOT NULL DEFAULT 0, 1.19 + "direct_majority_non_negative" INT4 NOT NULL DEFAULT 0, 1.20 + "indirect_majority_num" INT4 NOT NULL DEFAULT 1, 1.21 + "indirect_majority_den" INT4 NOT NULL DEFAULT 2, 1.22 + "indirect_majority_strict" BOOLEAN NOT NULL DEFAULT TRUE, 1.23 + "indirect_majority_positive" INT4 NOT NULL DEFAULT 0, 1.24 + "indirect_majority_non_negative" INT4 NOT NULL DEFAULT 0, 1.25 + "no_reverse_beat_path" BOOLEAN NOT NULL DEFAULT TRUE, 1.26 + "no_multistage_majority" BOOLEAN NOT NULL DEFAULT FALSE ); 1.27 CREATE INDEX "policy_active_idx" ON "policy" ("active"); 1.28 1.29 COMMENT ON TABLE "policy" IS 'Policies for a particular proceeding type (timelimits, quorum)'; 1.30 @@ -341,14 +345,18 @@ 1.31 COMMENT ON COLUMN "policy"."issue_quorum_den" IS 'Denominator of potential supporter quorum to be reached by one initiative of an issue to be "accepted"'; 1.32 COMMENT ON COLUMN "policy"."initiative_quorum_num" IS 'Numerator of satisfied supporter quorum to be reached by an initiative to be "admitted" for voting'; 1.33 COMMENT ON COLUMN "policy"."initiative_quorum_den" IS 'Denominator of satisfied supporter quorum to be reached by an initiative to be "admitted" for voting'; 1.34 -COMMENT ON COLUMN "policy"."majority_num" IS 'Numerator of fraction of majority to be reached during voting by an initiative to be an "attainable" winner'; 1.35 -COMMENT ON COLUMN "policy"."majority_den" IS 'Denominator of fraction of majority to be reached during voting by an initiative to be an "attainable" winner'; 1.36 -COMMENT ON COLUMN "policy"."majority_strict" IS 'If TRUE, then the majority must be strictly greater than "majority_num"/"majority_den", otherwise it may also be equal.'; 1.37 -COMMENT ON COLUMN "policy"."majority_positive" IS 'Absolute number of "positive_votes" neccessary for an initiative to be an "attainable" winner.'; 1.38 -COMMENT ON COLUMN "policy"."majority_non_negative" IS 'Absolute number of sum of "positive_votes" and abstentions neccessary for an initiative to be an "attainable" winner.'; 1.39 -COMMENT ON COLUMN "policy"."majority_indirect" IS 'If TRUE, then the majority specified by "majority_num", "majority_den", "majority_strict", "majority_positive" and "majority_non_negative" may be indirect through a beat path; if FALSE, then the status quo must be beaten directly with that majority'; 1.40 +COMMENT ON COLUMN "policy"."direct_majority_num" IS 'Numerator of fraction of neccessary direct majority for initiatives to be attainable as winner'; 1.41 +COMMENT ON COLUMN "policy"."direct_majority_den" IS 'Denominator of fraction of neccessary direct majority for initaitives to be attainable as winner'; 1.42 +COMMENT ON COLUMN "policy"."direct_majority_strict" IS 'If TRUE, then the direct majority must be strictly greater than "direct_majority_num"/"direct_majority_den", otherwise it may also be equal.'; 1.43 +COMMENT ON COLUMN "policy"."direct_majority_positive" IS 'Absolute number of "positive_votes" neccessary for an initiative to be attainable as winner'; 1.44 +COMMENT ON COLUMN "policy"."direct_majority_non_negative" IS 'Absolute number of sum of "positive_votes" and abstentions neccessary for an initiative to be attainable as winner'; 1.45 +COMMENT ON COLUMN "policy"."indirect_majority_num" IS 'Numerator of fraction of neccessary indirect majority (through beat path) for initiatives to be attainable as winner'; 1.46 +COMMENT ON COLUMN "policy"."indirect_majority_den" IS 'Denominator of fraction of neccessary indirect majority (through beat path) for initiatives to be attainable as winner'; 1.47 +COMMENT ON COLUMN "policy"."indirect_majority_strict" IS 'If TRUE, then the indirect majority must be strictly greater than "indirect_majority_num"/"indirect_majority_den", otherwise it may also be equal.'; 1.48 +COMMENT ON COLUMN "policy"."indirect_majority_positive" IS 'Absolute number of votes in favor of the winner neccessary in a beat path to the status quo for an initaitive to be attainable as winner'; 1.49 +COMMENT ON COLUMN "policy"."indirect_majority_non_negative" IS 'Absolute number of sum of votes in favor and abstentions in a beat path to the status quo for an initiative to be attainable as winner'; 1.50 COMMENT ON COLUMN "policy"."no_reverse_beat_path" IS 'Causes initiatives with "reverse_beat_path" flag to not be "eligible", thus disallowing them to be winner. See comment on column "initiative"."reverse_beat_path". This option ensures both that a winning initiative is never tied in a (weak) condorcet paradox with the status quo and a winning initiative always beats the status quo directly with a simple majority.'; 1.51 -COMMENT ON COLUMN "policy"."no_multistage_majority" IS 'Causes initiatives with "multistage_majority" flag to not be "eligible", thus disallowing them to be winner. See comment on column "initiative"."multistage_majority". This disqualifies initiatives which could cause an instable result. An instable result in this meaning is a result such that repeating the ballot with same preferences but with the winner of the first ballot as status quo would lead to a different winner in the second ballot. If (a) "majority_indirect" is TRUE, or (b) "no_reverse_beat_path" is TRUE and "majority_num"/"majority_den" is only a simple majority, or (c) "majority_num" is zero, then results are always stable and this flag does not have any effect on the winner (but still affects the "eligible" flag of an "initiative").'; 1.52 +COMMENT ON COLUMN "policy"."no_multistage_majority" IS 'Causes initiatives with "multistage_majority" flag to not be "eligible", thus disallowing them to be winner. See comment on column "initiative"."multistage_majority". This disqualifies initiatives which could cause an instable result. An instable result in this meaning is a result such that repeating the ballot with same preferences but with the winner of the first ballot as status quo would lead to a different winner in the second ballot. If there are no direct majorities required for the winner, or if in direct comparison only simple majorities are required and "no_reverse_beat_path" is true, then results are always stable and this flag does not have any effect on the winner (but still affects the "eligible" flag of an "initiative").'; 1.53 1.54 1.55 CREATE TABLE "unit" ( 1.56 @@ -554,9 +562,10 @@ 1.57 "satisfied_informed_supporter_count" INT4, 1.58 "positive_votes" INT4, 1.59 "negative_votes" INT4, 1.60 - "attainable" BOOLEAN, 1.61 - "favored_to_status_quo" BOOLEAN, 1.62 - "unfavored_to_status_quo" BOOLEAN, 1.63 + "direct_majority" BOOLEAN, 1.64 + "indirect_majority" BOOLEAN, 1.65 + "better_than_status_quo" BOOLEAN, 1.66 + "worse_than_status_quo" BOOLEAN, 1.67 "schulze_rank" INT4, 1.68 "reverse_beat_path" BOOLEAN, 1.69 "multistage_majority" BOOLEAN, 1.70 @@ -571,12 +580,13 @@ 1.71 CHECK ("revoked" ISNULL OR "admitted" ISNULL), 1.72 CONSTRAINT "non_admitted_initiatives_cant_contain_voting_results" CHECK ( 1.73 ( "admitted" NOTNULL AND "admitted" = TRUE ) OR 1.74 - ( "positive_votes" ISNULL AND "negative_votes" ISNULL AND "attainable" ISNULL AND 1.75 - "favored_to_status_quo" ISNULL AND "unfavored_to_status_quo" ISNULL AND 1.76 + ( "positive_votes" ISNULL AND "negative_votes" ISNULL AND 1.77 + "direct_majority" ISNULL AND "indirect_majority" ISNULL AND 1.78 + "better_than_status_quo" ISNULL AND "worse_than_status_quo" ISNULL AND 1.79 "schulze_rank" ISNULL AND 1.80 - "multistage_majority" ISNULL AND "reverse_beat_path" ISNULL AND 1.81 - "winner" ISNULL ) ), 1.82 - CONSTRAINT "favored_excludes_unfavored" CHECK (NOT ("favored_to_status_quo" AND "unfavored_to_status_quo")) ); 1.83 + "reverse_beat_path" ISNULL AND "multistage_majority" ISNULL AND 1.84 + "eligible" ISNULL AND "winner" ISNULL ) ), 1.85 + CONSTRAINT "better_excludes_worse" CHECK (NOT ("better_than_status_quo" AND "worse_than_status_quo")) ); 1.86 CREATE INDEX "initiative_created_idx" ON "initiative" ("created"); 1.87 CREATE INDEX "initiative_revoked_idx" ON "initiative" ("revoked"); 1.88 CREATE INDEX "initiative_text_search_data_idx" ON "initiative" USING gin ("text_search_data"); 1.89 @@ -598,9 +608,10 @@ 1.90 COMMENT ON COLUMN "initiative"."satisfied_informed_supporter_count" IS 'Calculated from table "direct_supporter_snapshot"'; 1.91 COMMENT ON COLUMN "initiative"."positive_votes" IS 'Calculated from table "direct_voter"'; 1.92 COMMENT ON COLUMN "initiative"."negative_votes" IS 'Calculated from table "direct_voter"'; 1.93 -COMMENT ON COLUMN "initiative"."attainable" IS 'TRUE, if "positive_votes"/("positive_votes"+"negative_votes") is strictly greater or greater-equal than "majority_num"/"majority_den", and "positive_votes" is greater-equal than "majority_positive", and ("positive_votes"+abstentions) is greater-equal than "majority_non_negative"'; 1.94 -COMMENT ON COLUMN "initiative"."favored_to_status_quo" IS 'TRUE, if initiative has a schulze-ranking better than the status quo (without tie-breaking)'; 1.95 -COMMENT ON COLUMN "initiative"."unfavored_to_status_quo" IS 'TRUE, if initiative has a schulze-ranking worse than the status quo (without tie-breaking)'; 1.96 +COMMENT ON COLUMN "initiative"."direct_majority" IS 'TRUE, if "positive_votes"/("positive_votes"+"negative_votes") is strictly greater or greater-equal than "direct_majority_num"/"direct_majority_den", and "positive_votes" is greater-equal than "direct_majority_positive", and ("positive_votes"+abstentions) is greater-equal than "direct_majority_non_negative"'; 1.97 +COMMENT ON COLUMN "initiative"."indirect_majority" IS 'Same as "direct_majority", but also considering indirect beat paths'; 1.98 +COMMENT ON COLUMN "initiative"."better_than_status_quo" IS 'TRUE, if initiative has a schulze-ranking better than the status quo (without tie-breaking)'; 1.99 +COMMENT ON COLUMN "initiative"."worse_than_status_quo" IS 'TRUE, if initiative has a schulze-ranking worse than the status quo (without tie-breaking)'; 1.100 COMMENT ON COLUMN "initiative"."schulze_rank" IS 'Schulze-Ranking without tie-breaking'; 1.101 COMMENT ON COLUMN "initiative"."reverse_beat_path" IS 'TRUE, if there is a beat path (may include ties), from this initiative to the status quo'; 1.102 COMMENT ON COLUMN "initiative"."multistage_majority" IS 'TRUE, if either (a) this initiative has no better rank than the status quo, or (b) there exists a better ranked initiative X, which directly beats this initiative, and either more voters prefer X to this initiative than voters preferring X to the status quo or less voters prefer this initiative to X than voters preferring the status quo to X'; 1.103 @@ -3770,65 +3781,74 @@ 1.104 ORDER BY "id" 1.105 LOOP 1.106 UPDATE "initiative" SET 1.107 - "attainable" = 1.108 - CASE WHEN "policy_row"."majority_strict" THEN 1.109 - "positive_votes" * "policy_row"."majority_den" > 1.110 - "policy_row"."majority_num" * ("positive_votes"+"negative_votes") 1.111 + "direct_majority" = 1.112 + CASE WHEN "policy_row"."direct_majority_strict" THEN 1.113 + "positive_votes" * "policy_row"."direct_majority_den" > 1.114 + "policy_row"."direct_majority_num" * ("positive_votes"+"negative_votes") 1.115 ELSE 1.116 - "positive_votes" * "policy_row"."majority_den" >= 1.117 - "policy_row"."majority_num" * ("positive_votes"+"negative_votes") 1.118 + "positive_votes" * "policy_row"."direct_majority_den" >= 1.119 + "policy_row"."direct_majority_num" * ("positive_votes"+"negative_votes") 1.120 END 1.121 - AND "positive_votes" >= "policy_row"."majority_positive" 1.122 + AND "positive_votes" >= "policy_row"."direct_majority_positive" 1.123 AND "issue_row"."voter_count"-"negative_votes" >= 1.124 - "policy_row"."majority_non_negative", 1.125 - "favored_to_status_quo" = "rank_ary"["i"] < "rank_ary"["dimension_v"], 1.126 - "unfavored_to_status_quo" = "rank_ary"["i"] > "rank_ary"["dimension_v"], 1.127 - "schulze_rank" = "rank_ary"["i"], 1.128 - "multistage_majority" = "rank_ary"["i"] >= "rank_ary"["dimension_v"], 1.129 - "reverse_beat_path" = "matrix"["dimension_v"]["i"] >= 0 1.130 + "policy_row"."direct_majority_non_negative", 1.131 + "indirect_majority" = 1.132 + CASE WHEN "policy_row"."indirect_majority_strict" THEN 1.133 + "positive_votes" * "policy_row"."indirect_majority_den" > 1.134 + "policy_row"."indirect_majority_num" * ("positive_votes"+"negative_votes") 1.135 + ELSE 1.136 + "positive_votes" * "policy_row"."indirect_majority_den" >= 1.137 + "policy_row"."indirect_majority_num" * ("positive_votes"+"negative_votes") 1.138 + END 1.139 + AND "positive_votes" >= "policy_row"."indirect_majority_positive" 1.140 + AND "issue_row"."voter_count"-"negative_votes" >= 1.141 + "policy_row"."indirect_majority_non_negative", 1.142 + "better_than_status_quo" = "rank_ary"["i"] < "rank_ary"["dimension_v"], 1.143 + "worse_than_status_quo" = "rank_ary"["i"] > "rank_ary"["dimension_v"], 1.144 + "schulze_rank" = "rank_ary"["i"], 1.145 + "multistage_majority" = "rank_ary"["i"] >= "rank_ary"["dimension_v"], 1.146 + "reverse_beat_path" = "matrix"["dimension_v"]["i"] >= 0 1.147 WHERE "id" = "initiative_id_v"; 1.148 "i" := "i" + 1; 1.149 END LOOP; 1.150 IF "i" != "dimension_v" THEN 1.151 RAISE EXCEPTION 'Wrong winner count (should not happen)'; 1.152 END IF; 1.153 - if "policy_row"."majority_indirect" THEN 1.154 - -- take indirect majorities into account: 1.155 - LOOP 1.156 - UPDATE "initiative" SET "attainable" = TRUE 1.157 - FROM ( 1.158 - SELECT "new_initiative"."id" AS "initiative_id" 1.159 - FROM "initiative" "old_initiative" 1.160 - JOIN "initiative" "new_initiative" 1.161 - ON "new_initiative"."issue_id" = "issue_id_p" 1.162 - AND "new_initiative"."attainable" = FALSE 1.163 - JOIN "battle" "battle_win" 1.164 - ON "battle_win"."issue_id" = "issue_id_p" 1.165 - AND "battle_win"."winning_initiative_id" = "new_initiative"."id" 1.166 - AND "battle_win"."losing_initiative_id" = "old_initiative"."id" 1.167 - JOIN "battle" "battle_lose" 1.168 - ON "battle_lose"."issue_id" = "issue_id_p" 1.169 - AND "battle_lose"."losing_initiative_id" = "new_initiative"."id" 1.170 - AND "battle_lose"."winning_initiative_id" = "old_initiative"."id" 1.171 - WHERE "old_initiative"."issue_id" = "issue_id_p" 1.172 - AND "old_initiative"."attainable" = TRUE 1.173 - AND CASE WHEN "policy_row"."majority_strict" THEN 1.174 - "battle_win"."count" * "policy_row"."majority_den" > 1.175 - "policy_row"."majority_num" * 1.176 - ("battle_win"."count"+"battle_lose"."count") 1.177 - ELSE 1.178 - "battle_win"."count" * "policy_row"."majority_den" >= 1.179 - "policy_row"."majority_num" * 1.180 - ("battle_win"."count"+"battle_lose"."count") 1.181 - END 1.182 - AND "battle_win"."count" >= "policy_row"."majority_positive" 1.183 - AND "issue_row"."voter_count"-"battle_lose"."count" >= 1.184 - "policy_row"."majority_non_negative" 1.185 - ) AS "subquery" 1.186 - WHERE "id" = "subquery"."initiative_id"; 1.187 - EXIT WHEN NOT FOUND; 1.188 - END LOOP; 1.189 - END IF; 1.190 + -- take indirect majorities into account: 1.191 + LOOP 1.192 + UPDATE "initiative" SET "indirect_majority" = TRUE 1.193 + FROM ( 1.194 + SELECT "new_initiative"."id" AS "initiative_id" 1.195 + FROM "initiative" "old_initiative" 1.196 + JOIN "initiative" "new_initiative" 1.197 + ON "new_initiative"."issue_id" = "issue_id_p" 1.198 + AND "new_initiative"."indirect_majority" = FALSE 1.199 + JOIN "battle" "battle_win" 1.200 + ON "battle_win"."issue_id" = "issue_id_p" 1.201 + AND "battle_win"."winning_initiative_id" = "new_initiative"."id" 1.202 + AND "battle_win"."losing_initiative_id" = "old_initiative"."id" 1.203 + JOIN "battle" "battle_lose" 1.204 + ON "battle_lose"."issue_id" = "issue_id_p" 1.205 + AND "battle_lose"."losing_initiative_id" = "new_initiative"."id" 1.206 + AND "battle_lose"."winning_initiative_id" = "old_initiative"."id" 1.207 + WHERE "old_initiative"."issue_id" = "issue_id_p" 1.208 + AND "old_initiative"."indirect_majority" = TRUE 1.209 + AND CASE WHEN "policy_row"."indirect_majority_strict" THEN 1.210 + "battle_win"."count" * "policy_row"."indirect_majority_den" > 1.211 + "policy_row"."indirect_majority_num" * 1.212 + ("battle_win"."count"+"battle_lose"."count") 1.213 + ELSE 1.214 + "battle_win"."count" * "policy_row"."indirect_majority_den" >= 1.215 + "policy_row"."indirect_majority_num" * 1.216 + ("battle_win"."count"+"battle_lose"."count") 1.217 + END 1.218 + AND "battle_win"."count" >= "policy_row"."indirect_majority_positive" 1.219 + AND "issue_row"."voter_count"-"battle_lose"."count" >= 1.220 + "policy_row"."indirect_majority_non_negative" 1.221 + ) AS "subquery" 1.222 + WHERE "id" = "subquery"."initiative_id"; 1.223 + EXIT WHEN NOT FOUND; 1.224 + END LOOP; 1.225 -- set "multistage_majority" for remaining matching initiatives: 1.226 UPDATE "initiative" SET "multistage_majority" = TRUE 1.227 FROM ( 1.228 @@ -3866,8 +3886,9 @@ 1.229 JOIN "initiative" 1.230 ON "issue"."id" = "initiative"."issue_id" 1.231 WHERE "issue_id" = "issue_id_p" 1.232 - AND "initiative"."attainable" 1.233 - AND "initiative"."favored_to_status_quo" 1.234 + AND "initiative"."direct_majority" 1.235 + AND "initiative"."indirect_majority" 1.236 + AND "initiative"."better_than_status_quo" 1.237 AND ( 1.238 "policy"."no_multistage_majority" = FALSE OR 1.239 "initiative"."multistage_majority" = FALSE )
2.1 --- a/demo.sql Sun Jun 05 01:12:37 2011 +0200 2.2 +++ b/demo.sql Sun Jun 05 18:59:40 2011 +0200 2.3 @@ -40,8 +40,7 @@ 2.4 "voting_time", 2.5 "issue_quorum_num", "issue_quorum_den", 2.6 "initiative_quorum_num", "initiative_quorum_den", 2.7 - "majority_num", "majority_den", "majority_strict", 2.8 - "majority_indirect", 2.9 + "direct_majority_num", "direct_majority_den", "direct_majority_strict", 2.10 "no_reverse_beat_path", "no_multistage_majority" 2.11 ) VALUES ( 2.12 1, 2.13 @@ -50,7 +49,6 @@ 2.14 25, 100, 2.15 20, 100, 2.16 1, 2, TRUE, 2.17 - TRUE, 2.18 TRUE, FALSE ); 2.19 2.20 CREATE FUNCTION "time_warp"() RETURNS VOID