Foundations · The Valuation Engineer
Machine-readable Prolog representation of this entry's facts, rules, and worked example.
Download entry.pl%% entry.pl
%%
%% Prolog companion to Foundations Vol. 1, Issue 1, Article 002
%% Title: Characteristics Space
%% Author: Bert Craytor
%% Concept: characteristics_space
%% Version: 0.1.0-draft
% =====================================================================
% DICTIONARY IMPORT
% =====================================================================
:- use_module('../../../../tools/dictionary/dictionary').
:- dictionary_release('dictionary-2026.1').
% --- From the dictionary (loaded via :- use_module above) -----------
% term(characteristics_space, "Characteristics Space", economic_theory,
% "The characteristics space of a class of heterogeneous goods is
% the vector space whose coordinates index the attributes that
% buyers value, and in which each good is represented by the
% vector of its attribute levels.", published, 'dictionary-2026.1').
%
% term(heterogeneous_good, ...).
% term(hedonic_price_function, ...).
% term(implicit_price, ...).
%
% generalized_by(characteristics_space, lancaster_1966).
% depends_on(characteristics_space, heterogeneous_good).
% ---------------------------------------------------------------------
:- use_terms([ characteristics_space, heterogeneous_good,
hedonic_price_function, implicit_price,
comp_selection, sales_comparison_approach,
real_estate ]).
:- use_relations([related/2, depends_on/2, generalized_by/2]).
% =====================================================================
% ARTICLE SUBJECT
% =====================================================================
article_concept(characteristics_space).
article_issue(volume(1), number(1), year(2026)).
article_id('foundations.2026.002').
% =====================================================================
% LOCAL VOCABULARY
% =====================================================================
%
% Narrow article-local field names + the dimensions of the worked
% example's characteristics space.
local_term(dimension).
local_term(coordinate).
local_term(euclidean_distance).
local_term(distance_metric).
local_term(nearest_neighbor).
% =====================================================================
% FORMAL ATTRIBUTION
% =====================================================================
% The construction is due to Lancaster (1966), as noted in citations.
attributed_construction(characteristics_space, lancaster_1966).
% =====================================================================
% THE ARTICLE'S CLAIM ABOUT REPRESENTATION
% =====================================================================
%
% A heterogeneous good becomes a point in a vector space. Each axis is
% a characteristic buyers value; each good is the vector of its
% attribute levels.
representation_of(heterogeneous_good, point_in_vector_space).
% Examples of dimensions relevant to residential appraisal.
residential_dimension(gla_sqft).
residential_dimension(lot_sqft).
residential_dimension(view).
residential_dimension(cond).
residential_dimension(bedrooms).
residential_dimension(baths).
residential_dimension(age).
residential_dimension(quality).
residential_dimension(school_district).
residential_dimension(distance_to_amenity).
residential_dimension(zoning).
% Examples of dimensions relevant to commercial appraisal — included
% to make the article's point that the dimensions shift with market.
commercial_dimension(lease_structure).
commercial_dimension(tenant_quality).
commercial_dimension(occupancy).
commercial_dimension(cash_flow_profile).
% =====================================================================
% APPRAISER ENCOUNTERS
% =====================================================================
%
% Mapping appraisal practice onto the characteristics-space framework.
practice_to_space_correspondence(
sales_comparison_grid_line, coordinate_axis,
"A grid line is an axis.").
practice_to_space_correspondence(
comp_row, row_vector,
"A comp is a vector of coordinate values.").
practice_to_space_correspondence(
adjustment, movement_along_axis,
"An adjustment moves along one axis holding others fixed.").
% =====================================================================
% WORKED EXAMPLE
% =====================================================================
%
% The 8 Pacifica comps are points in a 4D characteristics space spanned
% by GLA, lot_sqft, view, cond_numeric. Bring in the shared dataset.
:- consult('../../kb/pacifica_comps').
% Axes of the chosen space for this article's analysis.
axis(gla_sqft).
axis(lot_sqft).
axis(view).
axis(cond_numeric).
% Numeric encoding for non-numeric axes.
encode(view, no, 0).
encode(view, yes, 1).
encode(cond_numeric, 1, 1).
encode(cond_numeric, 2, 2).
encode(cond_numeric, 3, 3).
%! coord(?Property, ?Axis, ?Numeric) is nondet.
%
% Numeric coordinate of Property along Axis. Handles symbolic attribute
% values by encoding them.
coord(P, A, N) :-
attribute_value(P, A, V),
( number(V) -> N = V ; encode(A, V, N) ).
%! point(?Property, -Vector) is det.
%
% Vector representation of Property in the 4D characteristics space.
point(P, [GLA, Lot, View, Cond]) :-
coord(P, gla_sqft, GLA),
coord(P, lot_sqft, Lot),
coord(P, view, View),
coord(P, cond_numeric, Cond).
% =====================================================================
% THE HYPOTHETICAL SUBJECT
% =====================================================================
%
% The article tests distance metrics against this hypothetical property.
hypothetical_subject(subject).
attribute_value(subject, gla_sqft, 1700).
attribute_value(subject, lot_sqft, 7500).
attribute_value(subject, view, yes).
attribute_value(subject, cond_numeric, 2).
% =====================================================================
% NAIVE EUCLIDEAN DISTANCE (the article's straw distance metric)
% =====================================================================
%
% Computes the unscaled Euclidean distance between Property and the
% hypothetical subject. Used to demonstrate that unscaled distances
% mislead: the lot dimension dominates because its numeric range is
% much larger than view (0..1) or cond (1..3).
naive_distance_to_subject(P, D) :-
point(P, V_P),
point(subject, V_S),
sum_of_squares(V_P, V_S, S),
D is sqrt(S).
sum_of_squares([], [], 0).
sum_of_squares([X|Xs], [Y|Ys], S) :-
sum_of_squares(Xs, Ys, S0),
D is X - Y,
S is S0 + D * D.
% =====================================================================
% THE ARTICLE'S CENTRAL OBSERVATION
% =====================================================================
%
% Under naive Euclidean distance, Comp H is the nearest neighbor. But
% Comp H has no view and the subject does; view matters more to price
% than the naive metric admits. The fix (developed in entries 003-005)
% is to scale each axis by its implicit price.
claim(naive_metric_misleads,
"Unscaled Euclidean distance crowds out small-range axes (like view) under large-range axes (like lot_sqft). A market-defensible distance scales each axis by its implicit price.").
% =====================================================================
% DEFENSIBILITY QUESTIONS RAISED
% =====================================================================
%
% Three questions the characteristics-space framing makes explicit.
defensibility_question(which_dimensions,
"The choice of axes is a modeling decision. Defending an appraisal requires defending the axes, not just the values on them.").
defensibility_question(distance_metric,
"Untransformed Euclidean distance treats one sqft of GLA as equivalent to one sqft of lot, which the market does not. Distance requires a scaling per axis.").
defensibility_question(extrapolation_region,
"If the subject sits in a sparsely-sampled corner of the space, no comp is truly close and the indication is extrapolative.").
% =====================================================================
% INFERENCE RULES
% =====================================================================
%! same_point(?A, ?B) is nondet.
%
% Two properties occupy the same point in the characteristics space.
% (Doesn't occur in the running example, but the article notes that it
% would if all coordinates matched.)
same_point(A, B) :-
point(A, V),
point(B, V),
A \== B.
%! nearest_neighbor_by_naive_distance(-P) is semidet.
%
% The comp closest to the subject under the naive Euclidean metric.
% Used to illustrate the article's point that the naive metric chooses
% Comp H, not Comp A.
nearest_neighbor_by_naive_distance(P) :-
findall(D-Q,
( property(Q), Q \== subject, naive_distance_to_subject(Q, D) ),
Pairs),
keysort(Pairs, [_-P|_]).
% =====================================================================
% CROSS-REFERENCES
% =====================================================================
cross_reference(heterogeneous_good).
cross_reference(hedonic_price_function).
cross_reference(implicit_price).
The source above is the canonical Prolog form of this entry. It imports the journal-wide dictionary (Issues/tools/dictionary/) and can be queried using SWI-Prolog. See the article's prose form (PDF / HTML galleys) for the human-readable exposition.