From 559b042e1a1f52b1a960a70b385dad89ffaf5945 Mon Sep 17 00:00:00 2001 From: Maxime MORGE <maxime.morge@univ-lille.fr> Date: Tue, 25 Mar 2025 16:51:38 +0100 Subject: [PATCH] Investment game --- .idea/csv-editor.xml | 74 +-- README.md | 44 ++ data/dictator/dictator_consistency.csv | 121 ----- data/investment/investment.csv | 21 + data/investment/investment.old.csv | 97 ++++ .../investment.svg} | 456 ++++++------------ src/investment/__init__.py | 0 .../investment.py} | 121 +++-- .../investment_draw.py} | 4 +- .../investment_experiments.py} | 15 +- 10 files changed, 408 insertions(+), 545 deletions(-) delete mode 100644 data/dictator/dictator_consistency.csv create mode 100644 data/investment/investment.csv create mode 100644 data/investment/investment.old.csv rename figures/{dictator/dictator_consistency.svg => investment/investment.svg} (72%) create mode 100644 src/investment/__init__.py rename src/{dictator/dictator_consistency.py => investment/investment.py} (63%) rename src/{dictator/draw_consistency_draw.py => investment/investment_draw.py} (88%) rename src/{dictator/dictator_consistency_experiments.py => investment/investment_experiments.py} (68%) diff --git a/.idea/csv-editor.xml b/.idea/csv-editor.xml index e5835c3..1fe8589 100644 --- a/.idea/csv-editor.xml +++ b/.idea/csv-editor.xml @@ -31,154 +31,112 @@ </Attribute> </value> </entry> - <entry key="$PROJECT_DIR$/data/ring/ring.1.a.csv"> - <value> - <Attribute> - <option name="separator" value="," /> - </Attribute> - </value> - </entry> - <entry key="$PROJECT_DIR$/data/ring/ring.1.b.csv"> - <value> - <Attribute> - <option name="separator" value="," /> - </Attribute> - </value> - </entry> - <entry key="$PROJECT_DIR$/data/ring/ring.1.c.csv"> - <value> - <Attribute> - <option name="separator" value="," /> - </Attribute> - </value> - </entry> - <entry key="$PROJECT_DIR$/data/ring/ring.1.d.csv"> - <value> - <Attribute> - <option name="separator" value="," /> - </Attribute> - </value> - </entry> - <entry key="$PROJECT_DIR$/data/ring/ring.2.a.csv"> - <value> - <Attribute> - <option name="separator" value="," /> - </Attribute> - </value> - </entry> - <entry key="$PROJECT_DIR$/data/rps/rps.csv"> + <entry key="$PROJECT_DIR$/data/investment/investment.csv"> <value> <Attribute> <option name="separator" value="," /> </Attribute> </value> </entry> - <entry key="$PROJECT_DIR$/figures/ring/ring_accuracy.1.a.csv"> + <entry key="$PROJECT_DIR$/data/investment/investment.old.csv"> <value> <Attribute> <option name="separator" value="," /> </Attribute> </value> </entry> - <entry key="$PROJECT_DIR$/figures/ring/ring_accuracy.1.b.csv"> - <value> - <Attribute> - <option name="separator" value="," /> - </Attribute> - </value> - </entry> - <entry key="$PROJECT_DIR$/figures/ring/ring_accuracy.1.c.csv"> + <entry key="$PROJECT_DIR$/data/ring/ring.1.a.csv"> <value> <Attribute> <option name="separator" value="," /> </Attribute> </value> </entry> - <entry key="$PROJECT_DIR$/figures/ring/ring_accuracy.1.d.csv"> + <entry key="$PROJECT_DIR$/data/ring/ring.1.b.csv"> <value> <Attribute> <option name="separator" value="," /> </Attribute> </value> </entry> - <entry key="$PROJECT_DIR$/figures/ring/ring_accuracy.2.csv"> + <entry key="$PROJECT_DIR$/data/ring/ring.1.c.csv"> <value> <Attribute> <option name="separator" value="," /> </Attribute> </value> </entry> - <entry key="$PROJECT_DIR$/data/dictator/dictator.csv"> + <entry key="$PROJECT_DIR$/data/ring/ring.1.d.csv"> <value> <Attribute> <option name="separator" value="," /> </Attribute> </value> </entry> - <entry key="$PROJECT_DIR$/data/dictator/dictator_consistency.csv"> + <entry key="$PROJECT_DIR$/data/ring/ring.2.a.csv"> <value> <Attribute> <option name="separator" value="," /> </Attribute> </value> </entry> - <entry key="$PROJECT_DIR$/data/dictator/dictator_continuous_setup.csv"> + <entry key="$PROJECT_DIR$/data/rps/rps.csv"> <value> <Attribute> <option name="separator" value="," /> </Attribute> </value> </entry> - <entry key="$PROJECT_DIR$/data/dictator/dictator_setup.csv"> + <entry key="$PROJECT_DIR$/figures/dictator/dictator_continuous_setup_accuracy.csv"> <value> <Attribute> <option name="separator" value="," /> </Attribute> </value> </entry> - <entry key="$PROJECT_DIR$/data/guess/guess.csv"> + <entry key="$PROJECT_DIR$/figures/ring/ring_accuracy.1.a.csv"> <value> <Attribute> <option name="separator" value="," /> </Attribute> </value> </entry> - <entry key="$PROJECT_DIR$/data/ring/ring.1.a.csv"> + <entry key="$PROJECT_DIR$/figures/ring/ring_accuracy.1.b.csv"> <value> <Attribute> <option name="separator" value="," /> </Attribute> </value> </entry> - <entry key="$PROJECT_DIR$/data/ring/ring.1.b.csv"> + <entry key="$PROJECT_DIR$/figures/ring/ring_accuracy.1.c.csv"> <value> <Attribute> <option name="separator" value="," /> </Attribute> </value> </entry> - <entry key="$PROJECT_DIR$/data/ring/ring.1.c.csv"> + <entry key="$PROJECT_DIR$/figures/ring/ring_accuracy.1.d.csv"> <value> <Attribute> <option name="separator" value="," /> </Attribute> </value> </entry> - <entry key="$PROJECT_DIR$/data/ring/ring.1.d.csv"> + <entry key="$PROJECT_DIR$/figures/ring/ring_accuracy.2.csv"> <value> <Attribute> <option name="separator" value="," /> </Attribute> </value> </entry> - <entry key="$PROJECT_DIR$/data/ring/ring.2.a.csv"> + <entry key="$PROJECT_DIR$/data/investment/investment.csv"> <value> <Attribute> <option name="separator" value="," /> </Attribute> </value> </entry> - <entry key="$PROJECT_DIR$/data/rps/rps.csv"> + <entry key="$PROJECT_DIR$/data/investment/investment.old.csv"> <value> <Attribute> <option name="separator" value="," /> diff --git a/README.md b/README.md index bf94a06..e6bb90c 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,49 @@ simple contexts but struggle with more complex scenarios requiring anticipation of other agents' behaviour. Our study outlines research directions to overcome the current limitations of LLMs. +## Consistency + +To assess the decision-making consistency of various LLMs, we introduce an +investment game that allows us to observe whether LLMs follow stable +decision-making patterns or react erratically to variations in the game’s +parameters. + +An investor must allocate a basket (p_t^A, p_t^B) of 100 points between Asset A +and Asset B. The value of these points depends on two random parameters (a_t, +b_t), which determine how much money is received per allocated point. + +For example, if a = 0.8 and b = 0.5, this means that each point allocated to +Asset A is worth $0.8, while each point allocated to Asset B yields $0.5. The +game is played 25 times to analyze the consistency of the investor’s +decision-making. + +The investor’s decisions are then evaluated using an index called the Critical +Cost Efficiency Index (CCEI), which measures whether decisions adhere to a +certain level of economic rationality. This index is commonly used in +experimental economics and behavioral sciences to determine whether an +individual’s choices comply with the Generalized Axiom of Revealed Preference +(GARP). If an individual violates rational choice consistency, it is possible to +make a minimal budget adjustment (reducing resources) to align their decisions +with rationality. The CCEI quantifies the smallest budget reduction necessary to +make the choices consistent with rational principles. + +Each basket’s budget is calculated as follows: +I_t = p_t^A \times a_t + p_t^B \times b_t + +The CCEI index is derived from observed decisions. It is based on a linear +optimization problem that seeks the smallest necessary adjustment to budget +constraints to make the decisions conform to a rational model. + +We aim to find the largest \lambda (0 ≤ λ ≤ 1) such that, for every observation, +the adjusted decisions satisfy the rationality constraint: p^_t \cdot x_s \leq +\lambda I_t This means that if we slightly reduce the individual’s budget (by +multiplying it by \lambda), their choices will become consistent with +rationality. + +A CCEI close to 1 indicates that the choices are rational and consistent with +rational choice theory, whereas a low CCEI suggests irrational behavior. For +each model, 30 iterations of the game are conducted with a fixed temperature of +0.0 to maximize response consistency. ## Preferences @@ -72,6 +115,7 @@ retained by the dictator remains stable. However, the decisions become more deterministic at low temperatures, whereas allocation diversity increases at high temperatures, reflecting a more random exploration of available options. + ### Preference alignment We define four preferences for the dictator, each corresponding to a distinct form of social welfare: diff --git a/data/dictator/dictator_consistency.csv b/data/dictator/dictator_consistency.csv deleted file mode 100644 index 32a1eff..0000000 --- a/data/dictator/dictator_consistency.csv +++ /dev/null @@ -1,121 +0,0 @@ -iteration,model,temperature,ccei -1,random,0.0,0.3519 -2,random,0.0,0.3338 -3,random,0.0,0.1623 -4,random,0.0,0.3429 -5,random,0.0,0.171 -6,random,0.0,0.2451 -7,random,0.0,0.4368 -8,random,0.0,0.2843 -9,random,0.0,0.1131 -10,random,0.0,0.197 -11,random,0.0,0.1562 -12,random,0.0,0.1362 -13,random,0.0,0.1057 -14,random,0.0,0.281 -15,random,0.0,0.224 -16,random,0.0,0.1506 -17,random,0.0,0.2145 -18,random,0.0,0.2451 -19,random,0.0,0.3756 -20,random,0.0,0.237 -21,random,0.0,0.2618 -22,random,0.0,0.2222 -23,random,0.0,0.2669 -24,random,0.0,0.16 -25,random,0.0,0.3 -26,random,0.0,0.2451 -27,random,0.0,0.1736 -28,random,0.0,0.2816 -29,random,0.0,0.2342 -30,random,0.0,0.4048 -1,llama3,0.0,0.3504 -2,llama3,0.0,0.3424 -3,llama3,0.0,0.241 -4,llama3,0.0,0.137 -5,llama3,0.0,0.6632 -6,llama3,0.0,0.4808 -7,llama3,0.0,0.3 -8,llama3,0.0,0.5455 -9,llama3,0.0,0.3675 -10,llama3,0.0,0.4436 -11,llama3,0.0,0.4286 -12,llama3,0.0,0.1593 -13,llama3,0.0,0.3636 -14,llama3,0.0,0.3553 -15,llama3,0.0,0.3212 -16,llama3,0.0,0.3636 -17,llama3,0.0,0.1953 -18,llama3,0.0,0.2045 -19,llama3,0.0,0.137 -20,llama3,0.0,0.2308 -21,llama3,0.0,0.2576 -22,llama3,0.0,0.2195 -23,llama3,0.0,0.2195 -24,llama3,0.0,0.3553 -25,llama3,0.0,0.3455 -26,llama3,0.0,0.3333 -27,llama3,0.0,0.3636 -28,llama3,0.0,0.2 -29,llama3,0.0,0.4231 -30,llama3,0.0,0.3265 -1,mistral-small,0.0,0.2596 -2,mistral-small,0.0,0.3241 -3,mistral-small,0.0,0.1628 -4,mistral-small,0.0,0.272 -5,mistral-small,0.0,0.3239 -6,mistral-small,0.0,0.216 -7,mistral-small,0.0,0.216 -8,mistral-small,0.0,0.28 -9,mistral-small,0.0,0.4 -10,mistral-small,0.0,0.2956 -11,mistral-small,0.0,0.3538 -12,mistral-small,0.0,0.3526 -13,mistral-small,0.0,0.283 -14,mistral-small,0.0,0.322 -15,mistral-small,0.0,0.216 -16,mistral-small,0.0,0.2039 -17,mistral-small,0.0,0.4277 -18,mistral-small,0.0,0.2174 -19,mistral-small,0.0,0.1765 -20,mistral-small,0.0,0.371 -21,mistral-small,0.0,0.2653 -22,mistral-small,0.0,0.3261 -23,mistral-small,0.0,0.3 -24,mistral-small,0.0,0.194 -25,mistral-small,0.0,0.2364 -26,mistral-small,0.0,0.3284 -27,mistral-small,0.0,0.2364 -28,mistral-small,0.0,0.2131 -29,mistral-small,0.0,0.1741 -30,mistral-small,0.0,0.4348 -1,deepseek-r1,0.0,0.3913 -2,deepseek-r1,0.0,0.1425 -3,deepseek-r1,0.0,0.1582 -4,deepseek-r1,0.0,0.1111 -5,deepseek-r1,0.0,0.2725 -6,deepseek-r1,0.0,0.2083 -7,deepseek-r1,0.0,0.3168 -8,deepseek-r1,0.0,0.1 -9,deepseek-r1,0.0,0.1709 -10,deepseek-r1,0.0,0.1009 -11,deepseek-r1,0.0,0.1556 -12,deepseek-r1,0.0,0.1639 -13,deepseek-r1,0.0,0.2 -14,deepseek-r1,0.0,0.1493 -15,deepseek-r1,0.0,0.1825 -16,deepseek-r1,0.0,0.64 -17,deepseek-r1,0.0,0.2875 -18,deepseek-r1,0.0,0.25 -19,deepseek-r1,0.0,0.1111 -20,deepseek-r1,0.0,0.1028 -21,deepseek-r1,0.0,0.2558 -22,deepseek-r1,0.0,0.3636 -23,deepseek-r1,0.0,0.2656 -24,deepseek-r1,0.0,0.133 -25,deepseek-r1,0.0,0.1835 -26,deepseek-r1,0.0,0.3322 -27,deepseek-r1,0.0,0.3137 -28,deepseek-r1,0.0,0.1099 -29,deepseek-r1,0.0,0.3066 -30,deepseek-r1,0.0,0.1761 diff --git a/data/investment/investment.csv b/data/investment/investment.csv new file mode 100644 index 0000000..43aa27b --- /dev/null +++ b/data/investment/investment.csv @@ -0,0 +1,21 @@ +iteration,model,temperature,ccei +1,optimal,0.0,1.0 +2,optimal,0.0,1.0 +3,optimal,0.0,1.0 +4,optimal,0.0,1.0 +5,optimal,0.0,1.0 +6,optimal,0.0,1.0 +7,optimal,0.0,1.0 +8,optimal,0.0,1.0 +9,optimal,0.0,1.0 +10,optimal,0.0,1.0 +1,random,0.0,1.0 +2,random,0.0,1.0 +3,random,0.0,1.0 +4,random,0.0,1.0 +5,random,0.0,1.0 +6,random,0.0,1.0 +7,random,0.0,1.0 +8,random,0.0,1.0 +9,random,0.0,1.0 +10,random,0.0,1.0 diff --git a/data/investment/investment.old.csv b/data/investment/investment.old.csv new file mode 100644 index 0000000..d6fb25e --- /dev/null +++ b/data/investment/investment.old.csv @@ -0,0 +1,97 @@ +iteration,model,temperature,ccei +1,random,0.0,0.1993 +2,random,0.0,0.2841 +3,random,0.0,0.2584 +4,random,0.0,0.3276 +5,random,0.0,0.3676 +6,random,0.0,0.1505 +7,random,0.0,0.1047 +8,random,0.0,0.1385 +9,random,0.0,0.1866 +10,random,0.0,0.3135 +11,random,0.0,0.1835 +12,random,0.0,0.29 +13,random,0.0,0.2523 +14,random,0.0,0.2014 +15,random,0.0,0.1676 +16,random,0.0,0.2469 +17,random,0.0,0.2429 +18,random,0.0,0.1676 +19,random,0.0,0.1818 +20,random,0.0,0.3804 +21,random,0.0,0.2718 +22,random,0.0,0.336 +23,random,0.0,0.2473 +24,random,0.0,0.1942 +25,random,0.0,0.2857 +26,random,0.0,0.2163 +27,random,0.0,0.4202 +28,random,0.0,0.1175 +29,random,0.0,0.2494 +30,random,0.0,0.2693 +1,llama3,0.0,0.3636 +2,llama3,0.0,0.1515 +3,llama3,0.0,0.4684 +4,llama3,0.0,0.1515 +5,llama3,0.0,0.3636 +6,llama3,0.0,0.2222 +7,llama3,0.0,0.2222 +8,llama3,0.0,0.5242 +9,llama3,0.0,0.2632 +10,llama3,0.0,0.3 +11,llama3,0.0,0.1429 +12,llama3,0.0,0.1466 +13,llama3,0.0,0.3226 +14,llama3,0.0,0.1695 +15,llama3,0.0,0.25 +16,llama3,0.0,0.2381 +17,llama3,0.0,0.3391 +18,llama3,0.0,0.4386 +19,llama3,0.0,0.1639 +20,llama3,0.0,0.2909 +21,llama3,0.0,0.3077 +22,llama3,0.0,0.3906 +23,llama3,0.0,0.4 +24,llama3,0.0,0.1563 +25,llama3,0.0,0.2727 +26,llama3,0.0,0.2381 +27,llama3,0.0,0.2759 +28,llama3,0.0,0.1818 +29,llama3,0.0,0.2899 +30,llama3,0.0,0.2857 +1,mistral-small,0.0,0.1429 +2,mistral-small,0.0,0.1111 +3,mistral-small,0.0,0.1 +4,mistral-small,0.0,0.1111 +5,mistral-small,0.0,0.1111 +6,mistral-small,0.0,0.1 +7,mistral-small,0.0,0.1667 +8,mistral-small,0.0,0.1429 +9,mistral-small,0.0,0.1309 +10,mistral-small,0.0,0.2222 +11,mistral-small,0.0,0.1667 +12,mistral-small,0.0,0.125 +13,mistral-small,0.0,0.1 +14,mistral-small,0.0,0.1111 +15,mistral-small,0.0,0.2 +16,mistral-small,0.0,0.1111 +17,mistral-small,0.0,0.1111 +18,mistral-small,0.0,0.1111 +19,mistral-small,0.0,0.1493 +20,mistral-small,0.0,0.1429 +21,mistral-small,0.0,0.125 +22,mistral-small,0.0,0.1111 +23,mistral-small,0.0,0.125 +24,mistral-small,0.0,0.2 +25,mistral-small,0.0,0.1429 +26,mistral-small,0.0,0.1 +27,mistral-small,0.0,0.1111 +28,mistral-small,0.0,0.1111 +29,mistral-small,0.0,0.1111 +30,mistral-small,0.0,0.1111 +1,deepseek-r1, 0.0,0.1667 +2,deepseek-r1,0.0,0.2097 +3,deepseek-r1,0.0,0.3333 +4,deepseek-r1,0.0,0.1905 +5,deepseek-r1,0.0,0.2754 +6,deepseek-r1,0.0,0.1111 \ No newline at end of file diff --git a/figures/dictator/dictator_consistency.svg b/figures/investment/investment.svg similarity index 72% rename from figures/dictator/dictator_consistency.svg rename to figures/investment/investment.svg index b2f50fd..7c81295 100644 --- a/figures/dictator/dictator_consistency.svg +++ b/figures/investment/investment.svg @@ -6,7 +6,7 @@ <rdf:RDF xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <cc:Work> <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/> - <dc:date>2025-03-18T21:46:41.228780</dc:date> + <dc:date>2025-03-24T14:46:52.844601</dc:date> <dc:format>image/svg+xml</dc:format> <dc:creator> <cc:Agent> @@ -41,7 +41,7 @@ z <g id="xtick_1"> <g id="text_1"> <!-- random --> - <g style="fill: #262626" transform="translate(143.200409 414.133865) rotate(-20) scale(0.11 -0.11)"> + <g style="fill: #262626" transform="translate(166.450409 414.133865) rotate(-20) scale(0.11 -0.11)"> <defs> <path id="ArialMT-72" d="M 416 0 L 416 3319 @@ -215,7 +215,7 @@ z <g id="xtick_2"> <g id="text_2"> <!-- llama3 --> - <g style="fill: #262626" transform="translate(284.998692 412.460852) rotate(-20) scale(0.11 -0.11)"> + <g style="fill: #262626" transform="translate(354.748692 412.460852) rotate(-20) scale(0.11 -0.11)"> <defs> <path id="ArialMT-6c" d="M 409 0 L 409 4581 @@ -270,7 +270,7 @@ z <g id="xtick_3"> <g id="text_3"> <!-- mistral-small --> - <g style="fill: #262626" transform="translate(410.725147 422.487172) rotate(-20) scale(0.11 -0.11)"> + <g style="fill: #262626" transform="translate(526.975147 422.487172) rotate(-20) scale(0.11 -0.11)"> <defs> <path id="ArialMT-69" d="M 425 3934 L 425 4581 @@ -368,12 +368,29 @@ z </g> </g> </g> - <g id="xtick_4"> - <g id="text_4"> - <!-- deepseek-r1 --> - <g style="fill: #262626" transform="translate(550.499645 422.322106) rotate(-20) scale(0.11 -0.11)"> - <defs> - <path id="ArialMT-65" d="M 2694 1069 + <g id="text_4"> + <!-- Model --> + <g style="fill: #262626" transform="translate(352.659375 437.13095) scale(0.12 -0.12)"> + <defs> + <path id="ArialMT-4d" d="M 475 0 +L 475 4581 +L 1388 4581 +L 2472 1338 +Q 2622 884 2691 659 +Q 2769 909 2934 1394 +L 4031 4581 +L 4847 4581 +L 4847 0 +L 4263 0 +L 4263 3834 +L 2931 0 +L 2384 0 +L 1059 3900 +L 1059 0 +L 475 0 +z +" transform="scale(0.015625)"/> + <path id="ArialMT-65" d="M 2694 1069 L 3275 997 Q 3138 488 2766 206 Q 2394 -75 1816 -75 @@ -397,98 +414,6 @@ Q 2219 2931 1791 2931 Q 1403 2931 1139 2672 Q 875 2413 847 1978 z -" transform="scale(0.015625)"/> - <path id="ArialMT-70" d="M 422 -1272 -L 422 3319 -L 934 3319 -L 934 2888 -Q 1116 3141 1344 3267 -Q 1572 3394 1897 3394 -Q 2322 3394 2647 3175 -Q 2972 2956 3137 2557 -Q 3303 2159 3303 1684 -Q 3303 1175 3120 767 -Q 2938 359 2589 142 -Q 2241 -75 1856 -75 -Q 1575 -75 1351 44 -Q 1128 163 984 344 -L 984 -1272 -L 422 -1272 -z -M 931 1641 -Q 931 1000 1190 694 -Q 1450 388 1819 388 -Q 2194 388 2461 705 -Q 2728 1022 2728 1688 -Q 2728 2322 2467 2637 -Q 2206 2953 1844 2953 -Q 1484 2953 1207 2617 -Q 931 2281 931 1641 -z -" transform="scale(0.015625)"/> - <path id="ArialMT-6b" d="M 425 0 -L 425 4581 -L 988 4581 -L 988 1969 -L 2319 3319 -L 3047 3319 -L 1778 2088 -L 3175 0 -L 2481 0 -L 1384 1697 -L 988 1316 -L 988 0 -L 425 0 -z -" transform="scale(0.015625)"/> - <path id="ArialMT-31" d="M 2384 0 -L 1822 0 -L 1822 3584 -Q 1619 3391 1289 3197 -Q 959 3003 697 2906 -L 697 3450 -Q 1169 3672 1522 3987 -Q 1875 4303 2022 4600 -L 2384 4600 -L 2384 0 -z -" transform="scale(0.015625)"/> - </defs> - <use xlink:href="#ArialMT-64"/> - <use xlink:href="#ArialMT-65" transform="translate(55.615234 0)"/> - <use xlink:href="#ArialMT-65" transform="translate(111.230469 0)"/> - <use xlink:href="#ArialMT-70" transform="translate(166.845703 0)"/> - <use xlink:href="#ArialMT-73" transform="translate(222.460938 0)"/> - <use xlink:href="#ArialMT-65" transform="translate(272.460938 0)"/> - <use xlink:href="#ArialMT-65" transform="translate(328.076172 0)"/> - <use xlink:href="#ArialMT-6b" transform="translate(383.691406 0)"/> - <use xlink:href="#ArialMT-2d" transform="translate(433.691406 0)"/> - <use xlink:href="#ArialMT-72" transform="translate(466.992188 0)"/> - <use xlink:href="#ArialMT-31" transform="translate(500.292969 0)"/> - </g> - </g> - </g> - <g id="text_5"> - <!-- Model --> - <g style="fill: #262626" transform="translate(352.659375 437.13095) scale(0.12 -0.12)"> - <defs> - <path id="ArialMT-4d" d="M 475 0 -L 475 4581 -L 1388 4581 -L 2472 1338 -Q 2622 884 2691 659 -Q 2769 909 2934 1394 -L 4031 4581 -L 4847 4581 -L 4847 0 -L 4263 0 -L 4263 3834 -L 2931 0 -L 2384 0 -L 1059 3900 -L 1059 0 -L 475 0 -z " transform="scale(0.015625)"/> </defs> <use xlink:href="#ArialMT-4d"/> @@ -504,9 +429,9 @@ z <g id="line2d_1"> <path d="M 90 369.36 L 648 369.36 -" clip-path="url(#p4d718ef8b1)" style="fill: none; stroke: #cccccc; stroke-linecap: round"/> +" clip-path="url(#pd32a051487)" style="fill: none; stroke: #cccccc; stroke-linecap: round"/> </g> - <g id="text_6"> + <g id="text_5"> <!-- 0.1 --> <g style="fill: #262626" transform="translate(65.21 373.296797) scale(0.11 -0.11)"> <defs> @@ -541,6 +466,18 @@ L 1222 641 L 1222 0 L 581 0 z +" transform="scale(0.015625)"/> + <path id="ArialMT-31" d="M 2384 0 +L 1822 0 +L 1822 3584 +Q 1619 3391 1289 3197 +Q 959 3003 697 2906 +L 697 3450 +Q 1169 3672 1522 3987 +Q 1875 4303 2022 4600 +L 2384 4600 +L 2384 0 +z " transform="scale(0.015625)"/> </defs> <use xlink:href="#ArialMT-30"/> @@ -551,13 +488,13 @@ z </g> <g id="ytick_2"> <g id="line2d_2"> - <path d="M 90 315.666818 -L 648 315.666818 -" clip-path="url(#p4d718ef8b1)" style="fill: none; stroke: #cccccc; stroke-linecap: round"/> + <path d="M 90 298.072871 +L 648 298.072871 +" clip-path="url(#pd32a051487)" style="fill: none; stroke: #cccccc; stroke-linecap: round"/> </g> - <g id="text_7"> + <g id="text_6"> <!-- 0.2 --> - <g style="fill: #262626" transform="translate(65.21 319.603615) scale(0.11 -0.11)"> + <g style="fill: #262626" transform="translate(65.21 302.009668) scale(0.11 -0.11)"> <defs> <path id="ArialMT-32" d="M 3222 541 L 3222 0 @@ -593,13 +530,13 @@ z </g> <g id="ytick_3"> <g id="line2d_3"> - <path d="M 90 261.973636 -L 648 261.973636 -" clip-path="url(#p4d718ef8b1)" style="fill: none; stroke: #cccccc; stroke-linecap: round"/> + <path d="M 90 226.785743 +L 648 226.785743 +" clip-path="url(#pd32a051487)" style="fill: none; stroke: #cccccc; stroke-linecap: round"/> </g> - <g id="text_8"> + <g id="text_7"> <!-- 0.3 --> - <g style="fill: #262626" transform="translate(65.21 265.910433) scale(0.11 -0.11)"> + <g style="fill: #262626" transform="translate(65.21 230.722539) scale(0.11 -0.11)"> <use xlink:href="#ArialMT-30"/> <use xlink:href="#ArialMT-2e" transform="translate(55.615234 0)"/> <use xlink:href="#ArialMT-33" transform="translate(83.398438 0)"/> @@ -608,13 +545,13 @@ L 648 261.973636 </g> <g id="ytick_4"> <g id="line2d_4"> - <path d="M 90 208.280455 -L 648 208.280455 -" clip-path="url(#p4d718ef8b1)" style="fill: none; stroke: #cccccc; stroke-linecap: round"/> + <path d="M 90 155.498614 +L 648 155.498614 +" clip-path="url(#pd32a051487)" style="fill: none; stroke: #cccccc; stroke-linecap: round"/> </g> - <g id="text_9"> + <g id="text_8"> <!-- 0.4 --> - <g style="fill: #262626" transform="translate(65.21 212.217251) scale(0.11 -0.11)"> + <g style="fill: #262626" transform="translate(65.21 159.435411) scale(0.11 -0.11)"> <defs> <path id="ArialMT-34" d="M 2069 0 L 2069 1097 @@ -644,13 +581,13 @@ z </g> <g id="ytick_5"> <g id="line2d_5"> - <path d="M 90 154.587273 -L 648 154.587273 -" clip-path="url(#p4d718ef8b1)" style="fill: none; stroke: #cccccc; stroke-linecap: round"/> + <path d="M 90 84.211485 +L 648 84.211485 +" clip-path="url(#pd32a051487)" style="fill: none; stroke: #cccccc; stroke-linecap: round"/> </g> - <g id="text_10"> + <g id="text_9"> <!-- 0.5 --> - <g style="fill: #262626" transform="translate(65.21 158.52407) scale(0.11 -0.11)"> + <g style="fill: #262626" transform="translate(65.21 88.148282) scale(0.11 -0.11)"> <defs> <path id="ArialMT-35" d="M 266 1200 L 856 1250 @@ -684,57 +621,7 @@ z </g> </g> </g> - <g id="ytick_6"> - <g id="line2d_6"> - <path d="M 90 100.894091 -L 648 100.894091 -" clip-path="url(#p4d718ef8b1)" style="fill: none; stroke: #cccccc; stroke-linecap: round"/> - </g> - <g id="text_11"> - <!-- 0.6 --> - <g style="fill: #262626" transform="translate(65.21 104.830888) scale(0.11 -0.11)"> - <defs> - <path id="ArialMT-36" d="M 3184 3459 -L 2625 3416 -Q 2550 3747 2413 3897 -Q 2184 4138 1850 4138 -Q 1581 4138 1378 3988 -Q 1113 3794 959 3422 -Q 806 3050 800 2363 -Q 1003 2672 1297 2822 -Q 1591 2972 1913 2972 -Q 2475 2972 2870 2558 -Q 3266 2144 3266 1488 -Q 3266 1056 3080 686 -Q 2894 316 2569 119 -Q 2244 -78 1831 -78 -Q 1128 -78 684 439 -Q 241 956 241 2144 -Q 241 3472 731 4075 -Q 1159 4600 1884 4600 -Q 2425 4600 2770 4297 -Q 3116 3994 3184 3459 -z -M 888 1484 -Q 888 1194 1011 928 -Q 1134 663 1356 523 -Q 1578 384 1822 384 -Q 2178 384 2434 671 -Q 2691 959 2691 1453 -Q 2691 1928 2437 2201 -Q 2184 2475 1800 2475 -Q 1419 2475 1153 2201 -Q 888 1928 888 1484 -z -" transform="scale(0.015625)"/> - </defs> - <use xlink:href="#ArialMT-30"/> - <use xlink:href="#ArialMT-2e" transform="translate(55.615234 0)"/> - <use xlink:href="#ArialMT-36" transform="translate(83.398438 0)"/> - </g> - </g> - </g> - <g id="text_12"> + <g id="text_10"> <!-- CCEI Value --> <g style="fill: #262626" transform="translate(58.825 249.064687) rotate(-90) scale(0.12 -0.12)"> <defs> @@ -835,67 +722,97 @@ z </g> </g> <g id="patch_3"> - <path d="M 117.9 330.888835 -L 201.6 330.888835 -L 201.6 270.765895 -L 117.9 270.765895 -L 117.9 330.888835 + <path d="M 127.2 309.282772 +L 238.8 309.282772 +L 238.8 237.26495 +L 127.2 237.26495 +L 127.2 309.282772 z -" clip-path="url(#p4d718ef8b1)" style="fill: #333333; stroke: #1f1f1f; stroke-linejoin: miter"/> +" clip-path="url(#pd32a051487)" style="fill: #333333; stroke: #1f1f1f; stroke-linejoin: miter"/> + </g> + <g id="line2d_6"> + <path d="M 183 309.282772 +L 183 366.009505 +" clip-path="url(#pd32a051487)" style="fill: none; stroke: #1f1f1f"/> </g> <g id="line2d_7"> - <path d="M 159.75 330.888835 -L 159.75 366.299489 -" clip-path="url(#p4d718ef8b1)" style="fill: none; stroke: #1f1f1f"/> + <path d="M 183 237.26495 +L 183 141.098614 +" clip-path="url(#pd32a051487)" style="fill: none; stroke: #1f1f1f"/> </g> <g id="line2d_8"> - <path d="M 159.75 270.765895 -L 159.75 188.521364 -" clip-path="url(#p4d718ef8b1)" style="fill: none; stroke: #1f1f1f"/> + <path d="M 155.1 366.009505 +L 210.9 366.009505 +" clip-path="url(#pd32a051487)" style="fill: none; stroke: #1f1f1f; stroke-linecap: round"/> </g> <g id="line2d_9"> - <path d="M 138.825 366.299489 -L 180.675 366.299489 -" clip-path="url(#p4d718ef8b1)" style="fill: none; stroke: #1f1f1f; stroke-linecap: round"/> - </g> - <g id="line2d_10"> - <path d="M 138.825 188.521364 -L 180.675 188.521364 -" clip-path="url(#p4d718ef8b1)" style="fill: none; stroke: #1f1f1f; stroke-linecap: round"/> + <path d="M 155.1 141.098614 +L 210.9 141.098614 +" clip-path="url(#pd32a051487)" style="fill: none; stroke: #1f1f1f; stroke-linecap: round"/> </g> - <g id="line2d_11"/> + <g id="line2d_10"/> <g id="patch_4"> - <path d="M 257.4 303.679815 -L 341.1 303.679815 -L 341.1 227.824773 -L 257.4 227.824773 -L 257.4 303.679815 + <path d="M 313.2 303.847129 +L 424.8 303.847129 +L 424.8 201.853069 +L 313.2 201.853069 +L 313.2 303.847129 z -" clip-path="url(#p4d718ef8b1)" style="fill: #409884; stroke: #1f1f1f; stroke-linejoin: miter"/> +" clip-path="url(#pd32a051487)" style="fill: #409884; stroke: #1f1f1f; stroke-linejoin: miter"/> + </g> + <g id="line2d_11"> + <path d="M 369 303.847129 +L 369 338.777822 +" clip-path="url(#pd32a051487)" style="fill: none; stroke: #1f1f1f"/> </g> <g id="line2d_12"> - <path d="M 299.25 303.679815 -L 299.25 349.493523 -" clip-path="url(#p4d718ef8b1)" style="fill: none; stroke: #1f1f1f"/> + <path d="M 369 201.853069 +L 369 66.96 +" clip-path="url(#pd32a051487)" style="fill: none; stroke: #1f1f1f"/> </g> <g id="line2d_13"> - <path d="M 299.25 227.824773 -L 299.25 130.156875 -" clip-path="url(#p4d718ef8b1)" style="fill: none; stroke: #1f1f1f"/> + <path d="M 341.1 338.777822 +L 396.9 338.777822 +" clip-path="url(#pd32a051487)" style="fill: none; stroke: #1f1f1f; stroke-linecap: round"/> </g> <g id="line2d_14"> - <path d="M 278.325 349.493523 -L 320.175 349.493523 -" clip-path="url(#p4d718ef8b1)" style="fill: none; stroke: #1f1f1f; stroke-linecap: round"/> + <path d="M 341.1 66.96 +L 396.9 66.96 +" clip-path="url(#pd32a051487)" style="fill: none; stroke: #1f1f1f; stroke-linecap: round"/> </g> - <g id="line2d_15"> - <path d="M 278.325 130.156875 -L 320.175 130.156875 -" clip-path="url(#p4d718ef8b1)" style="fill: none; stroke: #1f1f1f; stroke-linecap: round"/> + <g id="line2d_15"/> + <g id="patch_5"> + <path d="M 499.2 361.447129 +L 610.8 361.447129 +L 610.8 338.777822 +L 499.2 338.777822 +L 499.2 361.447129 +z +" clip-path="url(#pd32a051487)" style="fill: #e77759; stroke: #1f1f1f; stroke-linejoin: miter"/> </g> <g id="line2d_16"> + <path d="M 555 361.447129 +L 555 369.36 +" clip-path="url(#pd32a051487)" style="fill: none; stroke: #1f1f1f"/> + </g> + <g id="line2d_17"> + <path d="M 555 338.777822 +L 555 321.811485 +" clip-path="url(#pd32a051487)" style="fill: none; stroke: #1f1f1f"/> + </g> + <g id="line2d_18"> + <path d="M 527.1 369.36 +L 582.9 369.36 +" clip-path="url(#pd32a051487)" style="fill: none; stroke: #1f1f1f; stroke-linecap: round"/> + </g> + <g id="line2d_19"> + <path d="M 527.1 321.811485 +L 582.9 321.811485 +" clip-path="url(#pd32a051487)" style="fill: none; stroke: #1f1f1f; stroke-linecap: round"/> + </g> + <g id="line2d_20"> <defs> - <path id="mf4da1d586f" d="M 0 3 + <path id="mba13d3f3f8" d="M 0 3 C 0.795609 3 1.55874 2.683901 2.12132 2.12132 C 2.683901 1.55874 3 0.795609 3 0 C 3 -0.795609 2.683901 -1.55874 2.12132 -2.12132 @@ -907,115 +824,48 @@ C -1.55874 2.683901 -0.795609 3 0 3 z " style="stroke: #1f1f1f"/> </defs> - <g clip-path="url(#p4d718ef8b1)"> - <use xlink:href="#mf4da1d586f" x="299.25" y="66.96" style="fill-opacity: 0; stroke: #1f1f1f"/> + <g clip-path="url(#pd32a051487)"> + <use xlink:href="#mba13d3f3f8" x="555" y="282.247129" style="fill-opacity: 0; stroke: #1f1f1f"/> + <use xlink:href="#mba13d3f3f8" x="555" y="298.072871" style="fill-opacity: 0; stroke: #1f1f1f"/> + <use xlink:href="#mba13d3f3f8" x="555" y="298.072871" style="fill-opacity: 0; stroke: #1f1f1f"/> </g> </g> - <g id="patch_5"> - <path d="M 396.9 307.075909 -L 480.6 307.075909 -L 480.6 248.228182 -L 396.9 248.228182 -L 396.9 307.075909 -z -" clip-path="url(#p4d718ef8b1)" style="fill: #e77759; stroke: #1f1f1f; stroke-linejoin: miter"/> - </g> - <g id="line2d_17"> - <path d="M 438.75 307.075909 -L 438.75 335.640682 -" clip-path="url(#p4d718ef8b1)" style="fill: none; stroke: #1f1f1f"/> - </g> - <g id="line2d_18"> - <path d="M 438.75 248.228182 -L 438.75 189.595227 -" clip-path="url(#p4d718ef8b1)" style="fill: none; stroke: #1f1f1f"/> - </g> - <g id="line2d_19"> - <path d="M 417.825 335.640682 -L 459.675 335.640682 -" clip-path="url(#p4d718ef8b1)" style="fill: none; stroke: #1f1f1f; stroke-linecap: round"/> - </g> - <g id="line2d_20"> - <path d="M 417.825 189.595227 -L 459.675 189.595227 -" clip-path="url(#p4d718ef8b1)" style="fill: none; stroke: #1f1f1f; stroke-linecap: round"/> - </g> - <g id="line2d_21"/> - <g id="patch_6"> - <path d="M 536.4 345.627614 -L 620.1 345.627614 -L 620.1 270.698778 -L 536.4 270.698778 -L 536.4 345.627614 -z -" clip-path="url(#p4d718ef8b1)" style="fill: #6b72da; stroke: #1f1f1f; stroke-linejoin: miter"/> + <g id="line2d_21"> + <path d="M 127.2 264.496634 +L 238.8 264.496634 +" clip-path="url(#pd32a051487)" style="fill: none; stroke: #1f1f1f"/> </g> <g id="line2d_22"> - <path d="M 578.25 345.627614 -L 578.25 369.36 -" clip-path="url(#p4d718ef8b1)" style="fill: none; stroke: #1f1f1f"/> + <path d="M 313.2 245.106535 +L 424.8 245.106535 +" clip-path="url(#pd32a051487)" style="fill: none; stroke: #1f1f1f"/> </g> <g id="line2d_23"> - <path d="M 578.25 270.698778 -L 578.25 212.951761 -" clip-path="url(#p4d718ef8b1)" style="fill: none; stroke: #1f1f1f"/> - </g> - <g id="line2d_24"> - <path d="M 557.325 369.36 -L 599.175 369.36 -" clip-path="url(#p4d718ef8b1)" style="fill: none; stroke: #1f1f1f; stroke-linecap: round"/> - </g> - <g id="line2d_25"> - <path d="M 557.325 212.951761 -L 599.175 212.951761 -" clip-path="url(#p4d718ef8b1)" style="fill: none; stroke: #1f1f1f; stroke-linecap: round"/> - </g> - <g id="line2d_26"> - <g clip-path="url(#p4d718ef8b1)"> - <use xlink:href="#mf4da1d586f" x="578.25" y="79.416818" style="fill-opacity: 0; stroke: #1f1f1f"/> - </g> - </g> - <g id="line2d_27"> - <path d="M 117.9 293.625767 -L 201.6 293.625767 -" clip-path="url(#p4d718ef8b1)" style="fill: none; stroke: #1f1f1f"/> - </g> - <g id="line2d_28"> - <path d="M 257.4 241.650767 -L 341.1 241.650767 -" clip-path="url(#p4d718ef8b1)" style="fill: none; stroke: #1f1f1f"/> - </g> - <g id="line2d_29"> - <path d="M 396.9 274.86 -L 480.6 274.86 -" clip-path="url(#p4d718ef8b1)" style="fill: none; stroke: #1f1f1f"/> + <path d="M 499.2 361.447129 +L 610.8 361.447129 +" clip-path="url(#pd32a051487)" style="fill: none; stroke: #1f1f1f"/> </g> - <g id="line2d_30"> - <path d="M 536.4 324.794659 -L 620.1 324.794659 -" clip-path="url(#p4d718ef8b1)" style="fill: none; stroke: #1f1f1f"/> - </g> - <g id="patch_7"> + <g id="patch_6"> <path d="M 90 384.48 L 90 51.84 " style="fill: none; stroke: #cccccc; stroke-width: 1.25; stroke-linejoin: miter; stroke-linecap: square"/> </g> - <g id="patch_8"> + <g id="patch_7"> <path d="M 648 384.48 L 648 51.84 " style="fill: none; stroke: #cccccc; stroke-width: 1.25; stroke-linejoin: miter; stroke-linecap: square"/> </g> - <g id="patch_9"> + <g id="patch_8"> <path d="M 90 384.48 L 648 384.48 " style="fill: none; stroke: #cccccc; stroke-width: 1.25; stroke-linejoin: miter; stroke-linecap: square"/> </g> - <g id="patch_10"> + <g id="patch_9"> <path d="M 90 51.84 L 648 51.84 " style="fill: none; stroke: #cccccc; stroke-width: 1.25; stroke-linejoin: miter; stroke-linecap: square"/> </g> - <g id="text_13"> + <g id="text_11"> <!-- CCEI Distribution by Model --> <g style="fill: #262626" transform="translate(284.972656 45.84) scale(0.14 -0.14)"> <defs> @@ -1125,7 +975,7 @@ z </g> </g> <defs> - <clipPath id="p4d718ef8b1"> + <clipPath id="pd32a051487"> <rect x="90" y="51.84" width="558" height="332.64"/> </clipPath> </defs> diff --git a/src/investment/__init__.py b/src/investment/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/dictator/dictator_consistency.py b/src/investment/investment.py similarity index 63% rename from src/dictator/dictator_consistency.py rename to src/investment/investment.py index 04282d2..4c54be5 100644 --- a/src/dictator/dictator_consistency.py +++ b/src/investment/investment.py @@ -1,17 +1,13 @@ -import os import asyncio +import os +import random from typing import Dict, List - -from gpytorch.settings import debug -from ollama import generate -from pydantic import BaseModel +import numpy as np from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.messages import TextMessage from autogen_core import CancellationToken from autogen_ext.models.openai import OpenAIChatCompletionClient -import json -import random -import numpy as np +from pydantic import BaseModel from scipy.optimize import linprog # Load API key from environment variable @@ -21,20 +17,20 @@ if not OPENAI_API_KEY: # Define the expected response format as a Pydantic model class AgentResponse(BaseModel): - my_share: int - other_share: int + assetA: int + assetB: int reasoning: str -# The dictator game simulation class -class DictatorConsistency: +# The investment game simulation class +class Investment: def __init__(self, model: str, temperature: float, max_retries: int = 3): - self.debug = False + self.debug = True self.model = model self.temperature = temperature self.strategy = random self.max_retries = max_retries # Maximum retry attempts in case of hallucinations - if not model == "random": + if not model == "random" and not model == "optimal": is_openai_model = model.startswith("gpt") base_url = "https://api.openai.com/v1" if is_openai_model else "http://localhost:11434/v1" @@ -59,18 +55,20 @@ class DictatorConsistency: """Runs the model if strategy is False, otherwise uses a classical method.""" if self.model == "random": return self.apply_random(m, n) + if self.model == "optimal": + return self.apply_optimal(m, n) instruction = f""" - You have 100 points to allocate between yourself and an anonymous person. - In this round, allocating every 1 point for yourself returns {m} dollars for yourself, - and allocating every 1 point for the other one returns {n} dollars for him/her. + You have 100 points to allocate between Asset A and Asset B. + In this round, allocating 1 point to Asset A yields {m} dollars, + while allocating 1 point to Asset B yields {n} dollars. What is your allocation? - Your response should be in JSON format with `my_share`, `other_share`, and `reasoning`. + Your response should be in JSON format with `assetA`, `assetB`, and `reasoning`. """ for attempt in range(self.max_retries): agent = AssistantAgent( - name="Dictator", + name="Investor", model_client=self.model_client, system_message="You are a helpful assistant. You will be given 25 rounds of decision-making tasks and will be responsible for making decisions. You should use your best judgment to come up with solutions that you like most." ) @@ -83,29 +81,42 @@ class DictatorConsistency: try: response_data = response.chat_message.content agent_response = AgentResponse.model_validate_json(response_data) # Parse JSON - my_share, other_share = agent_response.my_share, agent_response.other_share + assetA, assetB = agent_response.assetA, agent_response.assetB if self.debug: print(f"Response (Attempt {attempt+1}): {response_data}") # Validate values: ensure they sum to $100 considering the values M and N - if 0 <= my_share and my_share <= 100 and 0 <= other_share and other_share <= 100 and my_share + other_share == 100: + if 0 <= assetA and assetA <= 100 and 0 <= assetB and assetB <= 100 and assetA + assetB == 100: return agent_response.model_dump() else: - if self.debug : + if self.debug: print(f"Invalid response detected (Attempt {attempt+1}): {response_data}") except Exception as e: print(f"Error parsing response (Attempt {attempt+1}): {e}") raise ValueError("Model failed to provide a valid response after multiple attempts.") - def apply_random(self, m:int, n:int) -> Dict: + def apply_random(self, m: int, n: int) -> Dict: """Generates a response.""" - my_share = random.randint(0, 100) - other_share = 100 - my_share + assetA = random.randint(0, 100) + assetB = 100 - assetA return { - "my_share": my_share, - "other_share": other_share, + "assetA": assetA, + "assetB": assetB, "reasoning": "Random choice" - } + } + def apply_optimal(self, m: int, n: int) -> Dict: + """Generates a response.""" + if m > n: + assetA = 100 + assetB = 0 + else: + assetA = 0 + assetB = 100 + return { + "assetA": assetA, + "assetB": assetB, + "reasoning": "Optimal choice" + } def generate_M_N(self): while True: @@ -114,9 +125,8 @@ class DictatorConsistency: if max(M, N) >= 0.5: # Ensure max(M, N) is at least 0.5 return round(M, 1), round(N, 1) - - async def run_rounds(self, nb_rounds: int) -> List[Dict]: - """Runs the dictator game for n rounds and returns the results.""" + async def run_rounds(self, nb_rounds: int) -> float: + """Runs the investment game for n rounds and computes the CCEI.""" results = [] prices = [] choices = [] @@ -130,51 +140,58 @@ class DictatorConsistency: print(f"result: {result}") results.append(result) prices.append([m, n]) - budgets.append(m * result['my_share'] + n * result['other_share']) - choices.append([result['my_share'], result['other_share']]) - ccei_value = self.compute_ccei(prices, choices,budgets) + budget = round(m * result['assetA'] + n * result['assetB'], 4) + budgets.append(budget) + choices.append([result['assetA'], result['assetB']]) + + # Compute CCEI + ccei_value = self.compute_ccei(prices, choices, budgets) if self.debug: print(f"prices: {prices}") print(f"choices: {choices}") print(f"budgets: {budgets}") print(f"CCEI: {ccei_value}") + return ccei_value def compute_ccei(self, prices, choices, budgets): """ Computes the Critical Cost Efficiency Index (CCEI). - :param prices: List of price vectors (list of lists) - :param choices: List of chosen consumption bundles (list of lists) - :param budgets: List of budget values (list) - :return: CCEI value (between 0 and 1) """ n = len(prices) # Number of observations - # Objective: maximize lambda (equivalent to minimizing -lambda) - c = [-1] # We minimize -lambda to maximize lambda + c = [1] # Minimize theta A_ub = [] # Constraint matrix b_ub = [] # Right-hand side values for t in range(n): for s in range(n): lhs = np.dot(prices[t], choices[s]) # p_t * x_s - rhs = budgets[t] # I_t - # Corrected constraint: p_t * x_s - lambda * I_t <= 0 - A_ub.append([rhs]) # Correctly include I_t as coefficient of lambda - b_ub.append(lhs) # p_t * x_s moved to RHS - # Bounds for lambda: between 0 and 1 - bounds = [(0, 1)] + rhs = np.dot(prices[t], choices[t]) # p_t * x_t + if lhs > rhs: # Only add constraints where direct revealed preference exists + A_ub.append([-budgets[t]]) # -theta * I_t + b_ub.append(lhs - rhs) + # Ensure A_ub is a valid 2D array + if A_ub: + A_ub = np.array(A_ub, dtype=float) + if A_ub.ndim == 1: # Ensure it's 2D + A_ub = A_ub.reshape(-1, 1) + else: + A_ub = np.zeros((1, 1), dtype=float) # If no constraints, use a trivial 1x1 matrix + # Ensure b_ub is also valid + b_ub = np.array(b_ub, dtype=float) if b_ub else np.zeros(1, dtype=float) + + bounds = [(0, 1)] # Theta bounds # Solve the linear program result = linprog(c, A_ub=A_ub, b_ub=b_ub, bounds=bounds, method="highs") if result.success: - return round(-result.fun, 4) # Extract the optimized lambda + return round(result.x[0], 4) # Return optimized theta value else: - if self.debug: - print("CCEI computation failed. Check constraints.") - return 0 # Return 0 instead of None to indicate irrationality + print("CCEI computation failed. Check constraints.") + return 0 # Return 0 if LP fails # Run the async function and return the response if __name__ == "__main__": - game_agent = DictatorConsistency(model="mistral-small", temperature=0.7) # Toggle strategy here - response = asyncio.run(game_agent.run_rounds(25)) + game_agent = Investment(model="mistral-small", temperature=0.0) # Toggle strategy here + response = asyncio.run(game_agent.run_rounds(10)) print(response) diff --git a/src/dictator/draw_consistency_draw.py b/src/investment/investment_draw.py similarity index 88% rename from src/dictator/draw_consistency_draw.py rename to src/investment/investment_draw.py index 849e73d..d2e47da 100644 --- a/src/dictator/draw_consistency_draw.py +++ b/src/investment/investment_draw.py @@ -12,7 +12,7 @@ color_palette = { } # Load CSV file -file_path = "../../data/dictator/dictator_consistency.csv" # Update path +file_path = "../../data/investment/investment.csv" # Update path df = pd.read_csv(file_path) # Clean column names @@ -40,5 +40,5 @@ plt.ylabel("CCEI Value", fontsize=12) plt.xticks(rotation=20) # Save the figure -output_path = "../../figures/dictator/dictator_consistency.svg" +output_path = ("../../figures/investment/investment.svg") plt.savefig(output_path, format="svg") diff --git a/src/dictator/dictator_consistency_experiments.py b/src/investment/investment_experiments.py similarity index 68% rename from src/dictator/dictator_consistency_experiments.py rename to src/investment/investment_experiments.py index ac425e7..ed828f0 100644 --- a/src/dictator/dictator_consistency_experiments.py +++ b/src/investment/investment_experiments.py @@ -1,15 +1,12 @@ -import os import asyncio import csv -from typing import List -import random -from dictator_consistency import DictatorConsistency # Assuming this is in a separate file +from investment import Investment # Assuming this is in a separate file # Define models, temperature, and iterations -models = ["random", "llama3", "mistral-small", "deepseek-r1"] # "gpt-4.5-preview-2025-02-27" +models = ["optimal", "random"] # "gpt-4.5-preview-2025-02-27" "random", "llama3", "mistral-small", "deepseek-r1" temperature = 0.0 -iterations = 30 -output_file = "../../data/dictator/dictator_consistency.csv" +iterations = 10 +output_file = "../../data/investment/investment.csv" async def run_experiment(): # Open CSV file to store results @@ -24,8 +21,8 @@ async def run_experiment(): print(f"Iteration {iteration}/{iterations} for {model}") # Run DictatorConsistency experiment - game_agent = DictatorConsistency(model=model, temperature=temperature) - ccei_value = await game_agent.run_rounds(25) # Run 25 rounds + game_agent = Investment(model=model, temperature=temperature) + ccei_value = await game_agent.run_rounds(10) # Run 25 rounds # Write results to CSV writer.writerow([iteration, model, temperature, ccei_value]) -- GitLab