Remove ratio_circulation: the score is already a ratio
Owner: "I think a corridor could be worth a sixth of a room, this is ok. maybe we should dump the ratio_circulation altogether if there is already a pressure in circulation caused by the cost benefit ratio per msq. this is the kind of thing we want to root out of the scoring model: anything that is double counting, or using a gaussian where a linear ramp is appropriate, etc." value_circulation = 50 stands; hxi's rate question is closed. The duplication argument is stronger than it first looks. score = value/cost is already a ratio, so the per-m2 economics (50 against a build cost of 200) is not merely an absolute pressure -- adding corridor moves value/cost by an amount that depends on how much of the building is already corridor. It is ALREADY proportional. ratio_circulation said the same thing again as a whole-building multiplier, on a curve where twice the corridor is far more than twice as bad. Correction to my own first measurement: I overrode ratio_circulation and got scores going DOWN when a <=1 multiplier was removed, which is impossible. All four corpus programmes DECLARE ratio_circulation, so the CONF_DEFAULTS value I had changed was never in play and the two arms differed only in sigma. Same trap as value_supported in 39.19. Against the keep-it case, recorded because it is the one real argument: three of four declare a POSITIVE target (harbor/maple 0.08, health-centre 0.10), making the term formally two-sided rather than "less is better". It does not survive the numbers -- the lower side is worth at most 13.3% on the large programmes against 99% on the upper side, and "a building needs some circulation" is enforced structurally by access and connectivity, which no amount of value can buy off. Disabled in CONF_DEFAULTS and the four corpus configs, each with the reason inline and a note that a [target, sigma] pair re-enables it. Fail sets unchanged; it was always a value multiplier. Scores +42% to +7712%. 39.24 also sweeps every remaining term against the owner's two tests. Verdicts: perpendicular, proportion, width, crinkliness, access, size's lower side, ratio_outside, staircase volume and the count/limit fails are all sound. Filed as homemaker-py-dpt: size's UPPER side (cost already charges area; 82% of size fails are over-target), the minimum-internal-area factor (a third statement of "build the rooms"), the 0.5**n_fails curve (a ruling, not a measurement), and two dead paths -- ratio_public/private_outside, which no config declares, and the daylight factor pinned to 1.0 since the descope. Also updated a test I added last turn which asserted ratio_circulation was the second charge; it now pins that the linear ramp is the ONLY one. 419 passed. Closes homemaker-py-hxi. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MJ84Feep79Hhm3E4zZJmnB
This commit is contained in:
parent
f07b3865ef
commit
a7ef9e2fa0
7 changed files with 144 additions and 16 deletions
80
DESIGN.md
80
DESIGN.md
|
|
@ -7971,3 +7971,83 @@ untouched and unruled: `value_circulation` = 50 against `value_inside` = 300, a
|
||||||
room per square metre is a design judgement, not something measurement settles,
|
room per square metre is a design judgement, not something measurement settles,
|
||||||
and the linear ramp the owner describes is only as steep as that number makes
|
and the linear ramp the owner describes is only as steep as that number makes
|
||||||
it. Left open on the bead.
|
it. Left open on the bead.
|
||||||
|
|
||||||
|
### 39.24 `ratio_circulation` removed, and a sweep for the rest of its kind (`homemaker-py-hxi`)
|
||||||
|
|
||||||
|
Owner, closing the rate question and opening a general one:
|
||||||
|
|
||||||
|
> I think a corridor could be worth a sixth of a room, this is ok. maybe we
|
||||||
|
> should dump the ratio_circulation altogether if there is already a pressure in
|
||||||
|
> circulation caused by the cost benefit ratio per msq. this is the kind of
|
||||||
|
> thing we want to root out of the scoring model: anything that is double
|
||||||
|
> counting, or using a gaussian where a linear ramp is appropriate, etc.
|
||||||
|
|
||||||
|
So `value_circulation = 50` stands, and `hxi`'s rate question is closed.
|
||||||
|
|
||||||
|
**`ratio_circulation` is a duplicate, and the argument is stronger than it first
|
||||||
|
looks.** The score is `value / cost` — already a ratio. So the per-m² economics
|
||||||
|
(50 against a build cost of 200) is not merely an *absolute* pressure against
|
||||||
|
corridor area: adding corridor moves `value/cost` by an amount that depends on
|
||||||
|
how much of the building is already corridor. It is **already proportional**.
|
||||||
|
`ratio_circulation` states the same thing a second time, as a whole-building
|
||||||
|
multiplier, on a curve where twice the corridor is far more than twice as bad.
|
||||||
|
|
||||||
|
**A correction to my own first measurement.** I initially measured this by
|
||||||
|
overriding `ratio_circulation` and comparing — and got scores going *down* when
|
||||||
|
a ≤1 multiplier was removed, which is impossible. The cause: all four corpus
|
||||||
|
programmes **declare** `ratio_circulation` themselves, so the `CONF_DEFAULTS`
|
||||||
|
value I had changed was never in play, and my "with" arm was accidentally
|
||||||
|
comparing two different sigmas. The same trap as `value_supported` in §39.19.
|
||||||
|
Measured properly, disabling it raises every score, by +42% to +7712%
|
||||||
|
(programme-house s2, which is 44% circulation).
|
||||||
|
|
||||||
|
**And the declared values are not what the default suggests:**
|
||||||
|
|
||||||
|
| programme | declared | worst the *lower* side can cost |
|
||||||
|
|---|---|---|
|
||||||
|
| harbor-house | [0.08, 0.15] | 13.3% |
|
||||||
|
| maple-court | [0.08, 0.15] | 13.3% |
|
||||||
|
| health-centre | [0.10, 0.12] | 29.3% |
|
||||||
|
| programme-house | [0.00, 0.15] | 0% |
|
||||||
|
| `CONF_DEFAULTS` | [0.00, 0.20] | 0% |
|
||||||
|
|
||||||
|
Three of the four target a *positive* circulation fraction, so the term is
|
||||||
|
formally two-sided, not "less is better" — and a two-sided target is exactly
|
||||||
|
what a gaussian is for. That is the one argument for keeping it. It does not
|
||||||
|
survive the numbers: the lower side ("a building needs some circulation") is
|
||||||
|
worth at most 13% on the two large programmes, while the upper side reaches
|
||||||
|
99%, and the lower side's job is done structurally anyway by the access and
|
||||||
|
connectivity checks, which no amount of value can buy off. What is left is an
|
||||||
|
upper-side penalty, and the upper side is the duplicated one.
|
||||||
|
|
||||||
|
**Shipped:** `ratio_circulation` disabled — `None` in `CONF_DEFAULTS` and in the
|
||||||
|
four corpus `patterns.config` files, each with the reason inline and a note that
|
||||||
|
a `[target, sigma]` pair re-enables it. Fail sets are unchanged; it was always a
|
||||||
|
value multiplier, never a fail source.
|
||||||
|
|
||||||
|
**The sweep.** Every term in the objective, against the two tests the owner
|
||||||
|
named — does it double-count, and is a gaussian the right curve for what it
|
||||||
|
measures?
|
||||||
|
|
||||||
|
| term | measures | shape | verdict |
|
||||||
|
|---|---|---|---|
|
||||||
|
| perpendicular | corner angle vs 90° | two-sided gaussian | **OK** — a right angle is a genuine optimum |
|
||||||
|
| proportion | aspect vs target | clipped, one free side | **OK** |
|
||||||
|
| width | narrowest vs minimum | clipped, one free side | **OK** |
|
||||||
|
| crinkliness | daylight per unit floor | one-sided since §39.14 | **OK** |
|
||||||
|
| access | has a circulation neighbour | binary | **OK** — not a curve |
|
||||||
|
| size, *lower* side | area vs programme target | gaussian | **OK** — a room has a right size |
|
||||||
|
| size, *upper* side | area over target | gaussian | **SUSPECT** — `cost` already charges floor area, and an oversize room is wasteful in proportion, not quadratically. §39.15 found 82% of size fails are over-target. Not changed: §39.15 also found this upper half is the main brake on growth, so removing it needs the value rates looked at first. |
|
||||||
|
| ratio_outside | outdoor fraction vs target | two-sided gaussian | **OK** — and its binding side counters the economics rather than duplicating it, since outdoor space is profitable |
|
||||||
|
| ratio_circulation | circulation fraction | gaussian, effectively one-sided | **REMOVED** |
|
||||||
|
| min internal area | total room area below 1.2× the programme | one-sided gaussian | **SUSPECT** — "build the rooms you were asked for" is already said by the missing-space fails and again by `quality_size`. A third statement of it. |
|
||||||
|
| staircase volume | stair fit | gaussian | **OK** — a stair has a right size |
|
||||||
|
| stair count, storey limits | counts vs bounds | binary fails | **OK** |
|
||||||
|
| `ratio_public_outside`, `ratio_private_outside` | boundary-length ratios | gaussian | **DEAD** — absent from `CONF_DEFAULTS` and from every corpus config, so the branch never runs |
|
||||||
|
| `daylight` factor | pinned to 1.0 | constant | **DEAD** — `URB_NO_OCCLUSION` (§6); it is a factor that can never be anything but 1 |
|
||||||
|
| `0.5 ** n_fails` | fail count | exponential | **RULING WANTED** — each failure independently halves the building. Coherent as a product of independent defects, but it is not "twice as many failures is twice as bad", and it is the single largest term in the objective. |
|
||||||
|
|
||||||
|
The three SUSPECT entries and the fail multiplier are filed rather than changed
|
||||||
|
— each needs a ruling or a rate change behind it, and §39.16 is the standing
|
||||||
|
reminder about acting on an inherited constant before understanding what it
|
||||||
|
measures. The two DEAD entries are inert and cost nothing but confusion.
|
||||||
|
|
|
||||||
|
|
@ -267,9 +267,14 @@ storey_limit: 3
|
||||||
force_roof_garden: 0
|
force_roof_garden: 0
|
||||||
|
|
||||||
# Circulation ratio (allow more circulation for larger building)
|
# Circulation ratio (allow more circulation for larger building)
|
||||||
|
# homemaker-py-hxi (DESIGN.md §39.24): disabled. The score is value/cost, a
|
||||||
|
# ratio, so the per-m2 economics (circulation worth 50 against a build cost of
|
||||||
|
# 200) is ALREADY a proportional pressure against circulation -- this said the
|
||||||
|
# same thing a second time, and with a curve where twice the corridor is far
|
||||||
|
# more than twice as bad. Its other side, "a building needs some circulation",
|
||||||
|
# was worth at most 13% here and is enforced structurally anyway by the access
|
||||||
|
# and connectivity checks. Set a [target, sigma] pair to re-enable.
|
||||||
ratio_circulation:
|
ratio_circulation:
|
||||||
- 0.08
|
|
||||||
- 0.15
|
|
||||||
|
|
||||||
# Outside space ratio (courtyard requirement)
|
# Outside space ratio (courtyard requirement)
|
||||||
ratio_outside:
|
ratio_outside:
|
||||||
|
|
|
||||||
|
|
@ -351,9 +351,14 @@ storey_minimum: 1
|
||||||
storey_limit: 2
|
storey_limit: 2
|
||||||
force_roof_garden: 0
|
force_roof_garden: 0
|
||||||
|
|
||||||
|
# homemaker-py-hxi (DESIGN.md §39.24): disabled. The score is value/cost, a
|
||||||
|
# ratio, so the per-m2 economics (circulation worth 50 against a build cost of
|
||||||
|
# 200) is ALREADY a proportional pressure against circulation -- this said the
|
||||||
|
# same thing a second time, and with a curve where twice the corridor is far
|
||||||
|
# more than twice as bad. Its other side, "a building needs some circulation",
|
||||||
|
# was worth at most 13% here and is enforced structurally anyway by the access
|
||||||
|
# and connectivity checks. Set a [target, sigma] pair to re-enable.
|
||||||
ratio_circulation:
|
ratio_circulation:
|
||||||
- 0.10
|
|
||||||
- 0.12
|
|
||||||
|
|
||||||
ratio_outside:
|
ratio_outside:
|
||||||
- 0.06
|
- 0.06
|
||||||
|
|
|
||||||
|
|
@ -406,9 +406,14 @@ storey_limit: 4
|
||||||
force_roof_garden: 0
|
force_roof_garden: 0
|
||||||
|
|
||||||
# Circulation ratio (allow more circulation for larger building)
|
# Circulation ratio (allow more circulation for larger building)
|
||||||
|
# homemaker-py-hxi (DESIGN.md §39.24): disabled. The score is value/cost, a
|
||||||
|
# ratio, so the per-m2 economics (circulation worth 50 against a build cost of
|
||||||
|
# 200) is ALREADY a proportional pressure against circulation -- this said the
|
||||||
|
# same thing a second time, and with a curve where twice the corridor is far
|
||||||
|
# more than twice as bad. Its other side, "a building needs some circulation",
|
||||||
|
# was worth at most 13% here and is enforced structurally anyway by the access
|
||||||
|
# and connectivity checks. Set a [target, sigma] pair to re-enable.
|
||||||
ratio_circulation:
|
ratio_circulation:
|
||||||
- 0.08
|
|
||||||
- 0.15
|
|
||||||
|
|
||||||
# Outside space ratio (courtyard requirement)
|
# Outside space ratio (courtyard requirement)
|
||||||
ratio_outside:
|
ratio_outside:
|
||||||
|
|
|
||||||
|
|
@ -82,9 +82,14 @@ storey_limit: 5
|
||||||
force_roof_garden: 0
|
force_roof_garden: 0
|
||||||
|
|
||||||
# Circulation ratio (penalise excessive corridors)
|
# Circulation ratio (penalise excessive corridors)
|
||||||
|
# homemaker-py-hxi (DESIGN.md §39.24): disabled. The score is value/cost, a
|
||||||
|
# ratio, so the per-m2 economics (circulation worth 50 against a build cost of
|
||||||
|
# 200) is ALREADY a proportional pressure against circulation -- this said the
|
||||||
|
# same thing a second time, and with a curve where twice the corridor is far
|
||||||
|
# more than twice as bad. Its other side, "a building needs some circulation",
|
||||||
|
# was worth at most 13% here and is enforced structurally anyway by the access
|
||||||
|
# and connectivity checks. Set a [target, sigma] pair to re-enable.
|
||||||
ratio_circulation:
|
ratio_circulation:
|
||||||
- 0.00
|
|
||||||
- 0.15
|
|
||||||
|
|
||||||
# Outside space ratio
|
# Outside space ratio
|
||||||
ratio_outside:
|
ratio_outside:
|
||||||
|
|
|
||||||
|
|
@ -210,7 +210,25 @@ CONF_DEFAULTS: dict = {
|
||||||
"door_width": 1.2,
|
"door_width": 1.2,
|
||||||
"plot_ratio": [2.00, 0.50],
|
"plot_ratio": [2.00, 0.50],
|
||||||
"ratio_outside": [0.33, 0.15],
|
"ratio_outside": [0.33, 0.15],
|
||||||
"ratio_circulation": [0.00, 0.20],
|
# homemaker-py-hxi (DESIGN.md §39.24). Was [0.00, 0.20] -- a gaussian on
|
||||||
|
# the circulation FRACTION, targeting zero, applied as a multiplier to the
|
||||||
|
# whole building's value (0.013..0.70 across the corpus). `None` disables
|
||||||
|
# it, because it double-counts and does so with the wrong curve.
|
||||||
|
#
|
||||||
|
# The score is `value / cost`, which is already a ratio, so the per-m2
|
||||||
|
# economics -- circulation worth 50 against a build cost of 200 -- is
|
||||||
|
# already a PROPORTIONAL pressure and not merely an absolute one: adding
|
||||||
|
# corridor moves value/cost by an amount that depends on how much of the
|
||||||
|
# building is already corridor. A second, super-linear term on the same
|
||||||
|
# quantity says the same thing twice, and says it with a curve where twice
|
||||||
|
# the corridor is far more than twice as bad (0.10 -> x0.882, 0.20 ->
|
||||||
|
# x0.607, 0.40 -> x0.135).
|
||||||
|
#
|
||||||
|
# Contrast `ratio_outside`, which is KEPT: its target is 0.33, not zero, so
|
||||||
|
# it is a genuine two-sided requirement rather than "less is better", and
|
||||||
|
# its binding side (do not build too much outdoor space) is not something
|
||||||
|
# the economics expresses -- outdoor space is profitable.
|
||||||
|
"ratio_circulation": None,
|
||||||
# PROVENANCE (DESIGN.md §39.16). This is Christopher Alexander, A Pattern
|
# PROVENANCE (DESIGN.md §39.16). This is Christopher Alexander, A Pattern
|
||||||
# Language 159, "Light on Two Sides of Every Room" -- not an arbitrary
|
# Language 159, "Light on Two Sides of Every Room" -- not an arbitrary
|
||||||
# constant. The factor is evaluated at `1/crink = A/(L*h)`: floor area per
|
# constant. The factor is evaluated at `1/crink = A/(L*h)`: floor area per
|
||||||
|
|
@ -2048,7 +2066,8 @@ class Fitness:
|
||||||
factor *= self.ratio_o(ratios)
|
factor *= self.ratio_o(ratios)
|
||||||
|
|
||||||
circ_ratio = self.conf("ratio_circulation")
|
circ_ratio = self.conf("ratio_circulation")
|
||||||
factor *= self.ratio_type(ratios, "c", circ_ratio[0], circ_ratio[1])
|
if circ_ratio is not None: # §39.24: off by default
|
||||||
|
factor *= self.ratio_type(ratios, "c", circ_ratio[0], circ_ratio[1])
|
||||||
|
|
||||||
min_required = 0.0
|
min_required = 0.0
|
||||||
for req in (self._programme or {}).values():
|
for req in (self._programme or {}).values():
|
||||||
|
|
|
||||||
|
|
@ -150,13 +150,22 @@ def test_twice_the_corridor_is_exactly_twice_as_bad():
|
||||||
"so, §39.23's justification needs revisiting")
|
"so, §39.23's justification needs revisiting")
|
||||||
|
|
||||||
|
|
||||||
def test_the_amount_of_circulation_is_still_priced():
|
def test_the_amount_of_circulation_is_priced_exactly_once():
|
||||||
"""Removing the per-leaf cap must not make corridors free. Two charges
|
"""Removing the per-leaf cap must not make corridors free -- but the charge
|
||||||
remain, and they are the ones that do not depend on how it is cut up."""
|
that remains must also be the ONLY one (§39.24).
|
||||||
|
|
||||||
|
The linear ramp is `value_circulation` against the build cost: every square
|
||||||
|
metre of corridor is worth less than it costs, and because the score is
|
||||||
|
`value / cost` that pressure is already proportional to how much of the
|
||||||
|
building is corridor. `ratio_circulation` said the same thing a second time
|
||||||
|
and is disabled; if it comes back, either it has a justification this test
|
||||||
|
does not know about or the double count has returned.
|
||||||
|
"""
|
||||||
fit = _fit()
|
fit = _fit()
|
||||||
assert fit.conf("value_circulation") < fit.cost("inside"), (
|
assert fit.conf("value_circulation") < fit.cost("inside"), (
|
||||||
"a corridor must cost more to build than it is worth, or there is no "
|
"a corridor must cost more to build than it is worth, or there is no "
|
||||||
"linear ramp pushing the search to use less of it")
|
"linear ramp pushing the search to use less of it")
|
||||||
assert fit.conf("ratio_circulation") is not None, (
|
assert fit.conf("ratio_circulation") is None, (
|
||||||
"the building-level circulation fraction check is the other charge"
|
"ratio_circulation duplicates the per-m2 economics (§39.24)")
|
||||||
)
|
assert fit.conf("size_circulation") is None, "§39.23"
|
||||||
|
assert fit.conf("proportion_circulation") is None, "§39.22"
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue