0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

絶対領域の黄金比

Last updated at Posted at 2024-08-09

導入

絶対領域の黄金比は、

スカート丈:絶対領域:ニーソ丈 = 4:1:2.5

とされている。

われわれは例えば、常にスカート丈からそれぞれの丈を求めたいわけではなく、この関係性は双方向である。つまり、スカート丈、絶対領域部の丈およびニーソ丈のいずれからも各部位の丈を計算したいわけである。この双方向性を実現するために、「制約の拡散」を利用することにしよう。

制約の拡散については、「計算器プログラムの構造と解釈」第3章3.5節を参照されたい。
https://sicp.iijlab.net/fulltext/x335.html

プログラム

(define nil '())

(define (adder a1 a2 sum)
  (define (process-new-value)
    (cond ((and (has-value? a1) (has-value? a2))
           (set-value! sum
                       (+ (get-value a1) (get-value a2))
                       me))
          ((and (has-value? a1) (has-value? sum))
           (set-value! a2
                       (- (get-value sum) (get-value a1))
                       me))
          ((and (has-value? a2) (has-value? sum))
           (set-value! a1
                       (- (get-value sum) (get-value a2))
                       me))))
  (define (process-forget-value)
    (forget-value! sum me)
    (forget-value! a1 me)
    (forget-value! a2 me)
    (process-new-value))
  (define (me request)
    (cond ((eq? request 'I-have-a-value)
           (process-new-value))
          ((eq? request 'I-lost-my-value)
           (process-forget-value))
          (else
           (error "Unknown request -- ADDER" request))))
  (connect a1 me)
  (connect a2 me)
  (connect sum me)
  me)

(define (multiplier m1 m2 product)
  (define (process-new-value)
    (cond ((or (and (has-value? m1) (= (get-value m1) 0))
               (and (has-value? m2) (= (get-value m2) 0)))
           (set-value! product 0 me))
          ((and (has-value? m1) (has-value? m2))
           (set-value! product
                       (* (get-value m1) (get-value m2))
                       me))
          ((and (has-value? product) (has-value? m1))
           (set-value! m2
                       (/ (get-value product) (get-value m1))
                       me))
          ((and (has-value? product) (has-value? m2))
           (set-value! m1
                       (/ (get-value product) (get-value m2))
                       me))))
  (define (process-forget-value)
    (forget-value! product me)
    (forget-value! m1 me)
    (forget-value! m2 me)
    (process-new-value))
  (define (me request)
    (cond ((eq? request 'I-have-a-value)
           (process-new-value))
          ((eq? request 'I-lost-my-value)
           (process-forget-value))
          (else
           (error "Unknown request -- MULTIPLIER" request))))
  (connect m1 me)
  (connect m2 me)
  (connect product me)
  me)

(define (constant value connector)
  (define (me request)
    (error "Unknown request -- CONSTANT" request))
  (connect connector me)
  (set-value! connector value me)
  me)

(define (probe name connector)
  (define (print-probe value)
    (display "Probe: ")
    (display name)
    (display " = ")
    (display value)
    (newline))
  (define (process-new-value)
    (print-probe (get-value connector)))
  (define (process-forget-value)
    (print-probe "?"))
  (define (me request)
    (cond ((eq? request 'I-have-a-value)
           (process-new-value))
          ((eq? request 'I-lost-my-value)
           (process-forget-value))
          (else
           (error "Unknown request -- PROBE" request))))
  (connect connector me)
  me)
  
(define (inform-about-value constraint)
  (constraint 'I-have-a-value))
(define (inform-about-no-value constraint)
  (constraint 'I-lost-my-value))

(define (make-connector)
  (let ((value #f) (informant #f) (constraints nil))
    (define (set-my-value newval setter)
      (cond ((not (has-value? me))
             (set! value newval)
             (set! informant setter)
             (for-each-except setter
                              inform-about-value
                              constraints))
            ((not (= value newval))
             (error "Contradiction" (list value newval)))
            (else 'ignored)))
    (define (forget-my-value retractor)
      (if (eq? retractor informant)
          (begin (set! informant #f)
                 (for-each-except retractor
                                  inform-about-no-value
                                  constraints))
          'ignored))
    (define (connect new-constraint)
      (if (not (memq new-constraint constraints))
          (set! constraints
                (cons new-constraint constraints)))
      (if (has-value? me)
          (inform-about-value new-constraint))
      'done)
    (define (me request)
      (cond ((eq? request 'has-value?)
             (if informant #t #f))
            ((eq? request 'value) value)
            ((eq? request 'set-value!) set-my-value)
            ((eq? request 'forget) forget-my-value)
            ((eq? request 'connect) connect)
            (else (error "Unknown operation -- CONNECTOR" request))))
    me))

(define (for-each-except exception procedure list)
  (define (loop items)
    (cond ((null? items) 'done)
          ((eq? (car items) exception) (loop (cdr items)))
          (else (procedure (car items))
                (loop (cdr items)))))
  (loop list))

(define (has-value? connector)
  (connector 'has-value?))

(define (get-value connector)
  (connector 'value))

(define (set-value! connector new-value informant)
  ((connector 'set-value!) new-value informant))

(define (forget-value! connector retractor)
  ((connector 'forget) retractor))

(define (connect connector new-constraint)
  ((connector 'connect) new-constraint))

;;

(define skirt (make-connector))
(define atf (make-connector))
(define kneesocks (make-connector))

(define (absolute-terror-field skirt atf kneesocks)
  (let ((u (make-connector))
        (v (make-connector)))
    (multiplier atf u skirt)
    (multiplier atf v kneesocks)
    (constant 4.0 u)
    (constant 2.5 v)
    'ok))

(absolute-terror-field skirt atf kneesocks)

(probe "skirt" skirt)
(probe "atf" atf)
(probe "kneesocks" kneesocks)

実行

わかりやすくスカート丈を 40cm にしてみる。

gosh> (set-value! skirt 40 'user)
Probe: skirt = 40
Probe: atf = 10.0
Probe: kneesocks = 25.0
done

絶対領域丈は 10cm、ニーソ丈 25cm が最適である。

再計算するときは一旦値を忘れさせる。

gosh> (forget-value! skirt 'user)
Probe: skirt = ?
Probe: atf = ?
Probe: kneesocks = ?
done

次は絶対領域丈を 8cm にしてみよう。

gosh> (set-value! atf 8 'user)
Probe: atf = 8
Probe: kneesocks = 20.0
Probe: skirt = 32.0
done

スカート丈は 32cm、ニーソ丈は 20cm が最適である。

まとめ

制約の拡散を使って、絶対領域の黄金比を双方向に計算することができた。
紳士淑女(※)の皆様におかれては、絶対領域を展開する際にぜひ活用していただきたい。

※ 男子が女装しても良いのである。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?