# HG changeset patch # User jbe # Date 1400702503 -7200 # Node ID c83b2ac5477bc3f935ced15dfab7e5251bd33d6c # Parent 514eacf18e36f9adc0f655345c0067bf92f05e12 Use a composite type of two INT8's to describe the strength of a link for the Schulze method (necessary for tie-breaking of the links); Removed "no_reverse_beat_path" option diff -r 514eacf18e36 -r c83b2ac5477b core.sql --- a/core.sql Mon Apr 14 01:09:54 2014 +0200 +++ b/core.sql Wed May 21 22:01:43 2014 +0200 @@ -386,7 +386,6 @@ "indirect_majority_strict" BOOLEAN NOT NULL DEFAULT TRUE, "indirect_majority_positive" INT4 NOT NULL DEFAULT 0, "indirect_majority_non_negative" INT4 NOT NULL DEFAULT 0, - "no_reverse_beat_path" BOOLEAN NOT NULL DEFAULT FALSE, "no_multistage_majority" BOOLEAN NOT NULL DEFAULT FALSE, CONSTRAINT "timing" CHECK ( ( "polling" = FALSE AND @@ -428,8 +427,7 @@ 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.'; 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'; 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'; -COMMENT ON COLUMN "policy"."no_reverse_beat_path" IS 'EXPERIMENTAL FEATURE: 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.'; -COMMENT ON COLUMN "policy"."no_multistage_majority" IS 'EXPERIMENTAL FEATURE: 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").'; +COMMENT ON COLUMN "policy"."no_multistage_majority" IS 'EXPERIMENTAL FEATURE: 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.'; CREATE TABLE "unit" ( @@ -669,7 +667,6 @@ "schulze_rank" INT4, "better_than_status_quo" BOOLEAN, "worse_than_status_quo" BOOLEAN, - "reverse_beat_path" BOOLEAN, "multistage_majority" BOOLEAN, "eligible" BOOLEAN, "winner" BOOLEAN, @@ -688,7 +685,7 @@ "direct_majority" ISNULL AND "indirect_majority" ISNULL AND "schulze_rank" ISNULL AND "better_than_status_quo" ISNULL AND "worse_than_status_quo" ISNULL AND - "reverse_beat_path" ISNULL AND "multistage_majority" ISNULL AND + "multistage_majority" ISNULL AND "eligible" ISNULL AND "winner" ISNULL AND "rank" ISNULL ) ), CONSTRAINT "better_excludes_worse" CHECK (NOT ("better_than_status_quo" AND "worse_than_status_quo")), CONSTRAINT "minimum_requirement_to_be_eligible" CHECK ( @@ -728,9 +725,8 @@ COMMENT ON COLUMN "initiative"."schulze_rank" IS 'Schulze-Ranking'; COMMENT ON COLUMN "initiative"."better_than_status_quo" IS 'TRUE, if initiative has a schulze-ranking better than the status quo'; COMMENT ON COLUMN "initiative"."worse_than_status_quo" IS 'TRUE, if initiative has a schulze-ranking worse than the status quo (DEPRECATED, since schulze-ranking is unique per issue; use "better_than_status_quo"=FALSE)'; -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'; 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'; -COMMENT ON COLUMN "initiative"."eligible" IS 'Initiative has a "direct_majority" and an "indirect_majority", is "better_than_status_quo" and depending on selected policy the initiative has no "reverse_beat_path" or "multistage_majority"'; +COMMENT ON COLUMN "initiative"."eligible" IS 'Initiative has a "direct_majority" and an "indirect_majority", is "better_than_status_quo" and depending on selected policy the initiative has no "multistage_majority"'; COMMENT ON COLUMN "initiative"."winner" IS 'Winner is the "eligible" initiative with best "schulze_rank"'; COMMENT ON COLUMN "initiative"."rank" IS 'Unique ranking for all "admitted" initiatives per issue; lower rank is better; a winner always has rank 1, but rank 1 does not imply that an initiative is winner; initiatives with "direct_majority" AND "indirect_majority" always have a better (lower) rank than other initiatives'; @@ -3864,24 +3860,28 @@ CREATE FUNCTION "secondary_link_strength" - ( "initiative_id1_p" "initiative"."id"%TYPE, - "initiative_id2_p" "initiative"."id"%TYPE, + ( "initiative1_ord_p" INT4, + "initiative2_ord_p" INT4, "tie_breaking_p" "tie_breaking" ) RETURNS INT8 LANGUAGE 'plpgsql' IMMUTABLE AS $$ BEGIN - IF "initiative_id1_p" = "initiative_id2_p" THEN + IF "initiative1_ord_p" = "initiative2_ord_p" THEN RAISE EXCEPTION 'Identical initiative ids passed to "secondary_link_strength" function (should not happen)'; END IF; RETURN ( - CASE WHEN "initiative_id1_p" < "initiative_id2_p" THEN - 1::INT8 << 62 - ELSE 0 END - + - CASE WHEN "tie_breaking_p" = 'variant2'::"tie_breaking" THEN - ("initiative_id2_p"::INT8 << 31) - "initiative_id1_p"::INT8 + CASE WHEN "tie_breaking_p" = 'simple'::"tie_breaking" THEN + 0 ELSE - "initiative_id2_p"::INT8 - ("initiative_id1_p"::INT8 << 31) + CASE WHEN "initiative1_ord_p" < "initiative2_ord_p" THEN + 1::INT8 << 62 + ELSE 0 END + + + CASE WHEN "tie_breaking_p" = 'variant2'::"tie_breaking" THEN + ("initiative2_ord_p"::INT8 << 31) - "initiative1_ord_p"::INT8 + ELSE + "initiative2_ord_p"::INT8 - ("initiative1_ord_p"::INT8 << 31) + END END ); END; @@ -3890,18 +3890,24 @@ COMMENT ON FUNCTION "secondary_link_strength"(INT4, INT4, "tie_breaking") IS 'Calculates a secondary criterion for the defeat strength (tie-breaking of the links)'; +CREATE TYPE "link_strength" AS ( + "primary" INT8, + "secondary" INT8 ); + + + CREATE FUNCTION "calculate_ranks"("issue_id_p" "issue"."id"%TYPE) RETURNS VOID LANGUAGE 'plpgsql' VOLATILE AS $$ DECLARE "issue_row" "issue"%ROWTYPE; "policy_row" "policy"%ROWTYPE; - "dimension_v" INTEGER; + "dimension_v" INT4; "vote_matrix" INT4[][]; -- absolute votes - "matrix" INT8[][]; -- defeat strength / best paths - "i" INTEGER; - "j" INTEGER; - "k" INTEGER; + "matrix" "link_strength"[][]; -- defeat strength / best paths + "i" INT4; + "j" INT4; + "k" INT4; "battle_row" "battle"%ROWTYPE; "rank_ary" INT4[]; "rank_v" INT4; @@ -3947,11 +3953,18 @@ "j" := 1; LOOP IF "i" != "j" THEN - "matrix"["i"]["j"] := "defeat_strength"( - "vote_matrix"["i"]["j"], - "vote_matrix"["j"]["i"], - "policy_row"."defeat_strength" - ); + "matrix"["i"]["j"] := ( + "defeat_strength"( + "vote_matrix"["i"]["j"], + "vote_matrix"["j"]["i"], + "policy_row"."defeat_strength" + ), + "secondary_link_strength"( + "i", + "j", + "policy_row"."tie_breaking" + ) + )::"link_strength"; END IF; EXIT WHEN "j" = "dimension_v"; "j" := "j" + 1; @@ -4059,7 +4072,6 @@ "better_than_status_quo" = "rank_ary"["i"] < "rank_ary"[1], "worse_than_status_quo" = "rank_ary"["i"] > "rank_ary"[1], "multistage_majority" = "rank_ary"["i"] >= "rank_ary"[1], - "reverse_beat_path" = "matrix"[1]["i"] >= 0, "eligible" = FALSE, "winner" = FALSE, "rank" = NULL -- NOTE: in cases of manual reset of issue state @@ -4138,10 +4150,7 @@ AND "initiative"."better_than_status_quo" AND ( "policy_row"."no_multistage_majority" = FALSE OR - "initiative"."multistage_majority" = FALSE ) - AND ( - "policy_row"."no_reverse_beat_path" = FALSE OR - "initiative"."reverse_beat_path" = FALSE ); + "initiative"."multistage_majority" = FALSE ); -- mark final winner: UPDATE "initiative" SET "winner" = TRUE FROM ( diff -r 514eacf18e36 -r c83b2ac5477b test.sql --- a/test.sql Mon Apr 14 01:09:54 2014 +0200 +++ b/test.sql Wed May 21 22:01:43 2014 +0200 @@ -44,7 +44,7 @@ "issue_quorum_num", "issue_quorum_den", "initiative_quorum_num", "initiative_quorum_den", "direct_majority_num", "direct_majority_den", "direct_majority_strict", - "no_reverse_beat_path", "no_multistage_majority" + "no_multistage_majority" ) VALUES ( 1, 'Default policy', @@ -52,7 +52,7 @@ 25, 100, 20, 100, 1, 2, TRUE, - TRUE, FALSE ); + FALSE ); CREATE FUNCTION "time_warp"() RETURNS VOID LANGUAGE 'plpgsql' VOLATILE AS $$