[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M7BYRM6TV8ZWJSVCREYNEM7Y":3,"skill-same:01M7BYRM6TV8ZWJSVCREYNEM7Y":45},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":19,"linkOnly":20,"markdownContent":21,"markdownBody":22,"frontMatter":23,"refName":24,"commitSha":25,"skillDirectory":26,"forksCount":27,"repositoryHtmlUrl":28,"repositoryHomepageUrl":6,"ownerHtmlUrl":29,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":30,"install":31,"resources":44},"01M7BYRM6TV8ZWJSVCREYNEM7Y","locational-marginal-prices",null,"Extract locational marginal prices (LMPs) from DC-OPF solutions using dual values. Use when computing nodal electricity prices, reserve clearing prices, or performing price impact analysis.","linyouxue\u002Fskill-repair-benchmark","linyouxue","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F216151464?v=4","01M7BJEVCXKD74KH6FG9CBVSQB","林宥学","01M7BJEVE02NP217V93BKZFC0J",0,"Apache-2.0","https:\u002F\u002Fgithub.com\u002Flinyouxue\u002Fskill-repair-benchmark\u002Fblob\u002Fmain\u002Fevaluation\u002Fresults\u002FSkillAxe\u002Ftasks\u002Fenergy-market-pricing\u002Frepaired_run\u002Finputs\u002Fskills\u002Flocational-marginal-prices\u002FSKILL.md",[],[],"2026-11-15 14:19:17",false,"---\nname: locational-marginal-prices\ndescription: \"Extract locational marginal prices (LMPs) from DC-OPF solutions using dual values. Use when computing nodal electricity prices, reserve clearing prices, or performing price impact analysis.\"\n---\n\n# Locational Marginal Prices (LMPs)\n\nLMPs are the marginal cost of serving one additional MW of load at each bus. In optimization terms, they are the **dual values** (shadow prices) of the nodal power balance constraints.\n\n## LMP Extraction from CVXPY\n\nTo extract LMPs, you must:\n1. Store references to the balance constraints\n2. Solve the problem\n3. Read the dual values after solving\n\n```python\nimport cvxpy as cp\n\n# Store balance constraints separately for dual extraction\nbalance_constraints = []\n\nfor i in range(n_bus):\n    pg_at_bus = sum(Pg[g] for g in range(n_gen) if gen_bus[g] == i)\n    pd = buses[i, 2] \u002F baseMVA\n\n    # Create constraint and store reference\n    balance_con = pg_at_bus - pd == B[i, :] @ theta\n    balance_constraints.append(balance_con)\n    constraints.append(balance_con)\n\n# Solve\nprob = cp.Problem(cp.Minimize(cost), constraints)\nprob.solve(solver=cp.CLARABEL)\n\n# Extract LMPs from duals\nlmp_by_bus = []\nfor i in range(n_bus):\n    bus_num = int(buses[i, 0])\n    dual_val = balance_constraints[i].dual_value\n\n    # Scale: constraint is in per-unit, multiply by baseMVA to get $\u002FMWh\n    lmp = float(dual_val) * baseMVA if dual_val is not None else 0.0\n    lmp_by_bus.append({\n        \"bus\": bus_num,\n        \"lmp_dollars_per_MWh\": round(lmp, 2)\n    })\n```\n\n### Unit and sign sanity checks (do this before writing report.json)\n\nDual scaling is only correct if you are consistent about whether your balance constraint is written in **per-unit** or **MW**.\nA reliable way to avoid silent scaling errors:\n\n1. **Decide the balance units up front**\n- If your balance is in **MW** (recommended for clarity), e.g.\n  `G@Pg_MW - Pd_MW == B_MW@theta + Pshift_MW`,\n  then the dual is already in **$\u002FMW** (= $\u002FMWh), and you should **not multiply by baseMVA**.\n- If your balance is in **per-unit**, then multiplying by `baseMVA` is typically needed to convert $\u002Fpu to $\u002FMW.\n\n2. **Check for absurd magnitudes**\nIf you see LMPs that are orders of magnitude larger than typical marginal costs (e.g., millions of $\u002FMWh) in a normal dispatch,\nthat is a strong indicator of a unit\u002Fscaling mistake or solver failure.\n\n3. **Check a cheap consistency condition**\nWhen there is little\u002Fno congestion, many buses should have very similar LMPs. If LMPs vary wildly everywhere,\nre-check:\n- balance equation units\n- baseMVA conversions\n- whether line limits\u002Fstatus were modeled correctly\n- solver status\u002Faccuracy\n\n## LMP Sign Convention\n\nFor a balance constraint written as `generation - load == net_export`:\n- **Positive LMP**: Increasing load at that bus increases total cost (typical case)\n- **Negative LMP**: Increasing load at that bus *decreases* total cost\n\nNegative LMPs commonly occur when:\n- Cheap generation is trapped behind a congested line (can't export power)\n- Adding load at that bus relieves congestion by consuming local excess generation\n- The magnitude can be very large in heavily congested networks (thousands of $\u002FMWh)\n\nNegative LMPs are physically valid and expected in congested systems — they are not errors.\n\n## Reserve Clearing Price\n\nThe reserve MCP is the dual of the system reserve requirement constraint:\n\n```python\n# Store reference to reserve constraint\nreserve_con = cp.sum(Rg) >= reserve_requirement\nconstraints.append(reserve_con)\n\n# After solving:\nreserve_mcp = float(reserve_con.dual_value) if reserve_con.dual_value is not None else 0.0\n```\n\n### Reserve MCP checks\n\n- **Only interpret MCP if the constraint is (near) binding.**\n\n```python\nreserve_slack = float(np.sum(Rg.value) - reserve_requirement)\nis_binding = reserve_slack \u003C= 1e-3\nreserve_mcp = float(reserve_con.dual_value or 0.0)\nif not is_binding:\n    # dual should be ~0; force to 0 for reporting stability\n    reserve_mcp = 0.0\n```\n\n- **Units must match your reserve formulation.**\nIf `Rg` is in MW and the objective is $\u002Fhr, then the dual of `sum(Rg) >= R` is in $\u002FMW-hr (= $\u002FMWh).\n\n## Finding Binding Lines\n\nLines at or near thermal limits (≥99% loading) cause congestion and LMP separation. See the `dc-power-flow` skill for line flow calculation details.\n\n```python\nBINDING_THRESHOLD = 99.0  # Percent loading\n\nbinding_lines = []\nfor k, br in enumerate(branches):\n    f = bus_num_to_idx[int(br[0])]\n    t = bus_num_to_idx[int(br[1])]\n    x, rate = br[3], br[5]\n\n    if x != 0 and rate > 0:\n        b = 1.0 \u002F x\n        flow_MW = b * (theta.value[f] - theta.value[t]) * baseMVA\n        loading_pct = abs(flow_MW) \u002F rate * 100\n\n        if loading_pct >= BINDING_THRESHOLD:\n            binding_lines.append({\n                \"from\": int(br[0]),\n                \"to\": int(br[1]),\n                \"flow_MW\": round(float(flow_MW), 2),\n                \"limit_MW\": round(float(rate), 2)\n            })\n```\n\nTip: In MATPOWER cases with tap\u002Fshift transformers, use the tap\u002Fshift-aware flow expression from `dc-power-flow`.\n\n## Counterfactual Analysis\n\nTo analyze the impact of relaxing a transmission constraint:\n\n1. **Solve base case** — record costs, LMPs, and binding lines\n2. **Modify constraint** — e.g., increase a line's thermal limit\n3. **Solve counterfactual** — with the relaxed constraint\n4. **Compute impact** — compare costs and LMPs\n\n```python\n# Modify line limit (e.g., increase by 20%)\nfor k in range(n_branch):\n    br_from, br_to = int(branches[k, 0]), int(branches[k, 1])\n    if (br_from == target_from and br_to == target_to) or \\\n       (br_from == target_to and br_to == target_from):\n        branches[k, 5] *= 1.20  # 20% increase\n        break\n\n# After solving both cases:\ncost_reduction = base_cost - cf_cost  # Should be >= 0\n\n# LMP changes per bus\nfor bus_num in base_lmp_map:\n    delta = cf_lmp_map[bus_num] - base_lmp_map[bus_num]\n    # Negative delta = price decreased (congestion relieved)\n\n# Congestion relieved if line was binding in base but not in counterfactual\ncongestion_relieved = was_binding_in_base and not is_binding_in_cf\n```\n\n### Economic Intuition\n\n- **Relaxing a binding constraint** cannot increase cost (may decrease or stay same)\n- **Cost reduction** quantifies the shadow price of the constraint\n- **LMP convergence** after relieving congestion indicates reduced price separation\n","# Locational Marginal Prices (LMPs)\n\nLMPs are the marginal cost of serving one additional MW of load at each bus. In optimization terms, they are the **dual values** (shadow prices) of the nodal power balance constraints.\n\n## LMP Extraction from CVXPY\n\nTo extract LMPs, you must:\n1. Store references to the balance constraints\n2. Solve the problem\n3. Read the dual values after solving\n\n```python\nimport cvxpy as cp\n\n# Store balance constraints separately for dual extraction\nbalance_constraints = []\n\nfor i in range(n_bus):\n    pg_at_bus = sum(Pg[g] for g in range(n_gen) if gen_bus[g] == i)\n    pd = buses[i, 2] \u002F baseMVA\n\n    # Create constraint and store reference\n    balance_con = pg_at_bus - pd == B[i, :] @ theta\n    balance_constraints.append(balance_con)\n    constraints.append(balance_con)\n\n# Solve\nprob = cp.Problem(cp.Minimize(cost), constraints)\nprob.solve(solver=cp.CLARABEL)\n\n# Extract LMPs from duals\nlmp_by_bus = []\nfor i in range(n_bus):\n    bus_num = int(buses[i, 0])\n    dual_val = balance_constraints[i].dual_value\n\n    # Scale: constraint is in per-unit, multiply by baseMVA to get $\u002FMWh\n    lmp = float(dual_val) * baseMVA if dual_val is not None else 0.0\n    lmp_by_bus.append({\n        \"bus\": bus_num,\n        \"lmp_dollars_per_MWh\": round(lmp, 2)\n    })\n```\n\n### Unit and sign sanity checks (do this before writing report.json)\n\nDual scaling is only correct if you are consistent about whether your balance constraint is written in **per-unit** or **MW**.\nA reliable way to avoid silent scaling errors:\n\n1. **Decide the balance units up front**\n- If your balance is in **MW** (recommended for clarity), e.g.\n  `G@Pg_MW - Pd_MW == B_MW@theta + Pshift_MW`,\n  then the dual is already in **$\u002FMW** (= $\u002FMWh), and you should **not multiply by baseMVA**.\n- If your balance is in **per-unit**, then multiplying by `baseMVA` is typically needed to convert $\u002Fpu to $\u002FMW.\n\n2. **Check for absurd magnitudes**\nIf you see LMPs that are orders of magnitude larger than typical marginal costs (e.g., millions of $\u002FMWh) in a normal dispatch,\nthat is a strong indicator of a unit\u002Fscaling mistake or solver failure.\n\n3. **Check a cheap consistency condition**\nWhen there is little\u002Fno congestion, many buses should have very similar LMPs. If LMPs vary wildly everywhere,\nre-check:\n- balance equation units\n- baseMVA conversions\n- whether line limits\u002Fstatus were modeled correctly\n- solver status\u002Faccuracy\n\n## LMP Sign Convention\n\nFor a balance constraint written as `generation - load == net_export`:\n- **Positive LMP**: Increasing load at that bus increases total cost (typical case)\n- **Negative LMP**: Increasing load at that bus *decreases* total cost\n\nNegative LMPs commonly occur when:\n- Cheap generation is trapped behind a congested line (can't export power)\n- Adding load at that bus relieves congestion by consuming local excess generation\n- The magnitude can be very large in heavily congested networks (thousands of $\u002FMWh)\n\nNegative LMPs are physically valid and expected in congested systems — they are not errors.\n\n## Reserve Clearing Price\n\nThe reserve MCP is the dual of the system reserve requirement constraint:\n\n```python\n# Store reference to reserve constraint\nreserve_con = cp.sum(Rg) >= reserve_requirement\nconstraints.append(reserve_con)\n\n# After solving:\nreserve_mcp = float(reserve_con.dual_value) if reserve_con.dual_value is not None else 0.0\n```\n\n### Reserve MCP checks\n\n- **Only interpret MCP if the constraint is (near) binding.**\n\n```python\nreserve_slack = float(np.sum(Rg.value) - reserve_requirement)\nis_binding = reserve_slack \u003C= 1e-3\nreserve_mcp = float(reserve_con.dual_value or 0.0)\nif not is_binding:\n    # dual should be ~0; force to 0 for reporting stability\n    reserve_mcp = 0.0\n```\n\n- **Units must match your reserve formulation.**\nIf `Rg` is in MW and the objective is $\u002Fhr, then the dual of `sum(Rg) >= R` is in $\u002FMW-hr (= $\u002FMWh).\n\n## Finding Binding Lines\n\nLines at or near thermal limits (≥99% loading) cause congestion and LMP separation. See the `dc-power-flow` skill for line flow calculation details.\n\n```python\nBINDING_THRESHOLD = 99.0  # Percent loading\n\nbinding_lines = []\nfor k, br in enumerate(branches):\n    f = bus_num_to_idx[int(br[0])]\n    t = bus_num_to_idx[int(br[1])]\n    x, rate = br[3], br[5]\n\n    if x != 0 and rate > 0:\n        b = 1.0 \u002F x\n        flow_MW = b * (theta.value[f] - theta.value[t]) * baseMVA\n        loading_pct = abs(flow_MW) \u002F rate * 100\n\n        if loading_pct >= BINDING_THRESHOLD:\n            binding_lines.append({\n                \"from\": int(br[0]),\n                \"to\": int(br[1]),\n                \"flow_MW\": round(float(flow_MW), 2),\n                \"limit_MW\": round(float(rate), 2)\n            })\n```\n\nTip: In MATPOWER cases with tap\u002Fshift transformers, use the tap\u002Fshift-aware flow expression from `dc-power-flow`.\n\n## Counterfactual Analysis\n\nTo analyze the impact of relaxing a transmission constraint:\n\n1. **Solve base case** — record costs, LMPs, and binding lines\n2. **Modify constraint** — e.g., increase a line's thermal limit\n3. **Solve counterfactual** — with the relaxed constraint\n4. **Compute impact** — compare costs and LMPs\n\n```python\n# Modify line limit (e.g., increase by 20%)\nfor k in range(n_branch):\n    br_from, br_to = int(branches[k, 0]), int(branches[k, 1])\n    if (br_from == target_from and br_to == target_to) or \\\n       (br_from == target_to and br_to == target_from):\n        branches[k, 5] *= 1.20  # 20% increase\n        break\n\n# After solving both cases:\ncost_reduction = base_cost - cf_cost  # Should be >= 0\n\n# LMP changes per bus\nfor bus_num in base_lmp_map:\n    delta = cf_lmp_map[bus_num] - base_lmp_map[bus_num]\n    # Negative delta = price decreased (congestion relieved)\n\n# Congestion relieved if line was binding in base but not in counterfactual\ncongestion_relieved = was_binding_in_base and not is_binding_in_cf\n```\n\n### Economic Intuition\n\n- **Relaxing a binding constraint** cannot increase cost (may decrease or stay same)\n- **Cost reduction** quantifies the shadow price of the constraint\n- **LMP convergence** after relieving congestion indicates reduced price separation\n",{"name":5,"description":7},"main","cdcb6d230f3b15c3c33f8a2bdd16439f43602cbe","evaluation\u002Fresults\u002FSkillAxe\u002Ftasks\u002Fenergy-market-pricing\u002Frepaired_run\u002Finputs\u002Fskills\u002Flocational-marginal-prices",1,"https:\u002F\u002Fgithub.com\u002Flinyouxue\u002Fskill-repair-benchmark","https:\u002F\u002Fgithub.com\u002Flinyouxue","2026-11-14 20:28:35",{"source":8,"skillName":5,"commands":32,"prompt":42,"zipAvailable":43},[33,36,39],{"tool":34,"command":35},"npx","npx skills add linyouxue\u002Fskill-repair-benchmark --skill locational-marginal-prices",{"tool":37,"command":38},"bunx","bunx skills add linyouxue\u002Fskill-repair-benchmark --skill locational-marginal-prices",{"tool":40,"command":41},"pnpm","pnpm dlx skills add linyouxue\u002Fskill-repair-benchmark --skill locational-marginal-prices","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Flinyouxue\u002Fskill-repair-benchmark\u002Fblob\u002Fmain\u002Fevaluation\u002Fresults\u002FSkillAxe\u002Ftasks\u002Fenergy-market-pricing\u002Frepaired_run\u002Finputs\u002Fskills\u002Flocational-marginal-prices\u002FSKILL.md",true,[],[46,53,60,67,72,77],{"skillNo":47,"name":48,"nameZh":6,"description":49,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":50,"categories":51,"keywords":52,"publishedAt":19},"01M7E1HGVRY73NBJ022CJG13X6","video-frame-extraction","Extract frames from video files and save them as images using OpenCV","https:\u002F\u002Fgithub.com\u002Flinyouxue\u002Fskill-repair-benchmark\u002Fblob\u002Fmain\u002Fjpg-ocr-stat\u002Fresult\u002Fskilltta-claude4.7\u002Fgroup_03\u002Frun_03\u002Finputs\u002Fskills\u002Fvideo-frame-extraction\u002FSKILL.md",[],[],{"skillNo":54,"name":55,"nameZh":6,"description":56,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":57,"categories":58,"keywords":59,"publishedAt":19},"01M7E1HAG5R7CJ9C8NYJS771MB","openai-vision","Analyze images and multi-frame sequences using OpenAI GPT vision models","https:\u002F\u002Fgithub.com\u002Flinyouxue\u002Fskill-repair-benchmark\u002Fblob\u002Fmain\u002Fjpg-ocr-stat\u002Fresult\u002Fskilltta-claude4.7\u002Fgroup_03\u002Frun_03\u002Finputs\u002Fskills\u002Fopenai-vision\u002FSKILL.md",[],[],{"skillNo":61,"name":62,"nameZh":6,"description":63,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":64,"categories":65,"keywords":66,"publishedAt":19},"01M7E1H7DADKB6QBWKC2KQ63SZ","image-ocr","Extract text content from images using Tesseract OCR via Python, including structured field extraction from receipts and forms","https:\u002F\u002Fgithub.com\u002Flinyouxue\u002Fskill-repair-benchmark\u002Fblob\u002Fmain\u002Fjpg-ocr-stat\u002Fresult\u002Fskilltta-claude4.7\u002Fgroup_03\u002Frun_03\u002Finputs\u002Fskills\u002Fimage-ocr\u002FSKILL.md",[],[],{"skillNo":68,"name":48,"nameZh":6,"description":49,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":69,"categories":70,"keywords":71,"publishedAt":19},"01M7E1H0WBNT43TENGQY7AVZHD","https:\u002F\u002Fgithub.com\u002Flinyouxue\u002Fskill-repair-benchmark\u002Fblob\u002Fmain\u002Fjpg-ocr-stat\u002Fresult\u002Fskilltta-claude4.7\u002Fgroup_03\u002Frun_02\u002Finputs\u002Fskills\u002Fvideo-frame-extraction\u002FSKILL.md",[],[],{"skillNo":73,"name":55,"nameZh":6,"description":56,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":74,"categories":75,"keywords":76,"publishedAt":19},"01M7E1GTC7D4N4Q2EF03875J9E","https:\u002F\u002Fgithub.com\u002Flinyouxue\u002Fskill-repair-benchmark\u002Fblob\u002Fmain\u002Fjpg-ocr-stat\u002Fresult\u002Fskilltta-claude4.7\u002Fgroup_03\u002Frun_02\u002Finputs\u002Fskills\u002Fopenai-vision\u002FSKILL.md",[],[],{"skillNo":78,"name":62,"nameZh":6,"description":63,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":79,"categories":80,"keywords":81,"publishedAt":19},"01M7E1GQ92CWFMGH53KSSE4WER","https:\u002F\u002Fgithub.com\u002Flinyouxue\u002Fskill-repair-benchmark\u002Fblob\u002Fmain\u002Fjpg-ocr-stat\u002Fresult\u002Fskilltta-claude4.7\u002Fgroup_03\u002Frun_02\u002Finputs\u002Fskills\u002Fimage-ocr\u002FSKILL.md",[],[]]