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

Impressum / About Us