I wrote code that executes a function it receives from the (future) client, in a loop with some parameters. will call it func(name it).
Inside the function the client usually generate expression in the same variables(by GetUncertainty - each variable must be cleared before use). To do so , the simple idea is to use Block. Later , a code is executed that handles di and i outside the function.So, di and i must be globals(there could be more, it is flexible).
BTW, I know it is not efficient, but efficiency is not an issue.
func[v_, a_, r_] :=
(V = v; A = a; R = r;
Block[{V, A, R},i = V A + A 10 + R 100; di = GetUncertainty[i, {V, A, R}];] ;
Print[di])
The problem is that the client must reset the vars by hand. That means that the function parameters can't be V_,A_,R_ , otherwise The vars in the block will be replace by the values. I didn't manage to overcome this in any other way.
Another question in a similar issue. if I have
vars = {V,A,R,DR} , then
Block[vars , ..code.. ] , throws error that it is not a list.whereas Block[ {V,A,R,DR},..code..] works. How to overcome this?
Thanks.
its hard to unravel what you are trying to do, but the best approach may be to simply never assign values to symbols that need to be used as pure symbols in some context. Then you don't even need the Block[].
func[v_, a_, r_] := (
i = V A + A 10 + R 100;
di = GetUncertainty[i, {V, A, R}];
Print[di /. {V->v,A->a,R->r])
starting your own symbol names with Caps is frowned upon by the way as you risk conflict with built in symbols.
Note also there is a dedicated site mathematica.stackexchange.com
If I understand your application what you need are Formal Symbols. These are a set of Symbols with the Attribute Protected so that they cannot accidentally be assigned a value. They may be entered with e.g. Esc$AEsc for Formal Capital A. You can then use ReplaceAll (short form /.) as george showed to substitute your desired values.
Your code would be something like this:
func[v_, a_, r_] :=
Module[{i, di},
i = \[FormalCapitalV] \[FormalCapitalA] + \[FormalCapitalA] 10 + \[FormalCapitalR] 100;
di = GetUncertainty[i, {\[FormalCapitalV], \[FormalCapitalA], \[FormalCapitalR]}];
di /. {\[FormalCapitalV] -> v, \[FormalCapitalA] -> a, \[FormalCapitalR] -> r}
]
That looks horrible here but in a Notebook it looks like this:
I included Module to show how you should properly localize utility Symbols such as i and di but this particuarly simple function could also be written without them:
Your second question regarding "vars = {V,A,R,DR} then Block[vars , ..code.. ]" is answered here: How to set Block local variables by code?
Dedicated StackExchange site:
Related
I am looking for a general-purpose way of defining textual expressions which allow a value to be validated.
For example, I have a value which should only be set to 1, 2, 3, 10, 11, or 12.
Its constraint might be defined as: (value >= 1 && value <= 3) || (value >= 10 && value <= 12)
Or another value which can be 1, 3, 5, 7, 9 etc... would have a constraint like value % 2 == 1 or IsOdd(value).
(To help the user correct invalid values, I'd like to show the constraint - so something descriptive like IsOdd is preferable.)
These constraints would be evaluated both on client-side (after user input) and server-side.
Therefore a multi-platform solution would be ideal (specifically Win C#/Linux C++).
Is there an existing language/project which allows evaluation or parsing of similar simple expressions?
If not, where might I start creating my own?
I realise this question is somewhat vague as I am not entirely sure what I am after. Searching turned up no results, so even some terms as a starting point would be helpful. I can then update/tag the question accordingly.
You may want to investigate dependently typed languages like Idris or Agda.
The type system of such languages allows encoding of value constraints in types. Programs that cannot guarantee the constraints will simply not compile. The usual example is that of matrix multiplication, where the dimensions must match. But this is so to speak the "hello world" of dependently typed languages, the type system can do much more for you.
If you end up starting your own language I'd try to stay implementation-independent as long as possible. Look for the formal expression grammars of a suitable programming language (e.g. C) and add special keywords/functions as required. Once you have a formal definition of your language, implement a parser using your favourite parser generator.
That way, even if your parser is not portable to a certain platform you at least have a formal standard from where to start a separate parser implementation.
You may also want to look at creating a Domain Specific Language (DSL) in Ruby. (Here's a good article on what that means and what it would look like: http://jroller.com/rolsen/entry/building_a_dsl_in_ruby)
This would definitely give you the portability you're looking for, including maybe using IronRuby in your C# environment, and you'd be able to leverage the existing logic and mathematical operations of Ruby. You could then have constraint definition files that looked like this:
constrain 'wakeup_time' do
6 <= value && value <= 10
end
constrain 'something_else' do
check (value % 2 == 1), MustBeOdd
end
# constrain is a method that takes one argument and a code block
# check is a function you've defined that takes a two arguments
# MustBeOdd is the name of an exception type you've created in your standard set
But really, the great thing about a DSL is that you have a lot of control over what the constraint files look like.
there are a number of ways to verify a list of values across multiple languages. My preferred method is to make a list of the permitted values and load them into a dictionary/hashmap/list/vector (dependant on the language and your preference) and write a simple isIn() or isValid() function, that will check that the value supplied is valid based on its presence in the data structure. The beauty of this is that the code is trivial and can be implemented in just about any language very easily. for odd-only or even-only numeric validity again, a small library of different language isOdd() functions will suffice: if it isn't odd it must by definition be even (apart from 0 but then a simple exception can be set up to handle that, or you can simply specify in your code documentation that for logical purposes your code evaluates 0 as odd/even (your choice)).
I normally cart around a set of c++ and c# functions to evaluate isOdd() for similar reasons to what you have alluded to, and the code is as follows:
C++
bool isOdd( int integer ){ return (integer%2==0)?false:true; }
you can also add inline and/or fastcall to the function depending on need or preference; I tend to use it as an inline and fastcall unless there is a need to do otherwise (huge performance boost on xeon processors).
C#
Beautifully the same line works in C# just add static to the front if it is not going to be part of another class:
static bool isOdd( int integer ){ return (integer%2==0)?false:true; }
Hope this helps, in any event let me know if you need any further info:)
Not sure if it's what you looking for, but judging from your starting conditions (Win C#/Linux C++) you may not need it to be totally language agnostic. You can implement such a parser yourself in C++ with all the desired features and then just use it in both C++ and C# projects - thus also bypassing the need to add external libraries.
On application design level, it would be (relatively) simple - you create a library which is buildable cross-platform and use it in both projects. The interface may be something simple like:
bool VerifyConstraint_int(int value, const char* constraint);
bool VerifyConstraint_double(double value, const char* constraint);
// etc
Such interface will be usable both in Linux C++ (by static or dynamic linking) and in Windows C# (using P/Invoke). You can have same codebase compiling on both platforms.
The parser (again, judging from what you've described in the question) may be pretty simple - a tree holding elements of types Variable and Expression which can be Evaluated with a given Variable value.
Example class definitions:
class Entity {public: virtual VARIANT Evaluate() = 0;} // boost::variant may be used typedef'd as VARIANT
class BinaryOperation: public Entity {
private:
Entity& left;
Entity& right;
enum Operation {PLUS,MINUS,EQUALS,AND,OR,GREATER_OR_EQUALS,LESS_OR_EQUALS};
public:
virtual VARIANT Evaluate() override; // Evaluates left and right operands and combines them
}
class Variable: public Entity {
private:
VARIANT value;
public:
virtual VARIANT Evaluate() override {return value;};
}
Or, you can just write validation code in C++ and use it both in C# and C++ applications :)
My personal choice would be Lua. The downside to any DSL is the learning curve of a new language and how to glue the code with the scripts but I've found Lua has lots of support from the user base and several good books to help you learn.
If you are after making somewhat generic code that a non programmer can inject rules for allowable input it's going to take some upfront work regardless of the route you take. I highly suggest not rolling your own because you'll likely find people wanting more features that an already made DSL will have.
If you are using Java then you can use the Object Graph Navigation Library.
It enables you to write java applications that can parse,compile and evaluate OGNL expressions.
OGNL expressions include basic java,C,C++,C# expressions.
You can compile an expression that uses some variables, and then evaluate that expression
for some given variables.
An easy way to achieve validation of expressions is to use Python's eval method. It can be used to evaluate expressions just like the one you wrote. Python's syntax is easy enough to learn for simple expressions and english-like. Your expression example is translated to:
(value >= 1 and value <= 3) or (value >= 10 and value <= 12)
Code evaluation provided by users might pose a security risk though as certain functions could be used to be executed on the host machine (such as the open function, to open a file). But the eval function takes extra arguments to restrict the allowed functions. Hence you can create a safe evaluation environment.
# Import math functions, and we'll use a few of them to create
# a list of safe functions from the math module to be used by eval.
from math import *
# A user-defined method won't be reachable in the evaluation, as long
# as we provide the list of allowed functions and vars to eval.
def dangerous_function(filename):
print open(filename).read()
# We're building the list of safe functions to use by eval:
safe_list = ['math','acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'cosh', 'degrees', 'e', 'exp', 'fabs', 'floor', 'fmod', 'frexp', 'hypot', 'ldexp', 'log', 'log10', 'modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh']
safe_dict = dict([ (k, locals().get(k, None)) for k in safe_list ])
# Let's test the eval method with your example:
exp = "(value >= 1 and value <= 3) or (value >= 10 and value <= 12)"
safe_dict['value'] = 2
print "expression evaluation: ", eval(exp, {"__builtins__":None},safe_dict)
-> expression evaluation: True
# Test with a forbidden method, such as 'abs'
exp = raw_input("type an expression: ")
-> type an expression: (abs(-2) >= 1 and abs(-2) <= 3) or (abs(-2) >= 10 and abs(-2) <= 12)
print "expression evaluation: ", eval(exp, {"__builtins__":None},safe_dict)
-> expression evaluation:
-> Traceback (most recent call last):
-> File "<stdin>", line 1, in <module>
-> File "<string>", line 1, in <module>
-> NameError: name 'abs' is not defined
# Let's test it again, without any extra parameters to the eval method
# that would prevent its execution
print "expression evaluation: ", eval(exp)
-> expression evaluation: True
# Works fine without the safe dict! So the restrictions were active
# in the previous example..
# is odd?
def isodd(x): return bool(x & 1)
safe_dict['isodd'] = isodd
print "expression evaluation: ", eval("isodd(7)", {"__builtins__":None},safe_dict)
-> expression evaluation: True
print "expression evaluation: ", eval("isodd(42)", {"__builtins__":None},safe_dict)
-> expression evaluation: False
# A bit more complex this time, let's ask the user a function:
user_func = raw_input("type a function: y = ")
-> type a function: y = exp(x)
# Let's test it:
for x in range(1,10):
# add x in the safe dict
safe_dict['x']=x
print "x = ", x , ", y = ", eval(user_func,{"__builtins__":None},safe_dict)
-> x = 1 , y = 2.71828182846
-> x = 2 , y = 7.38905609893
-> x = 3 , y = 20.0855369232
-> x = 4 , y = 54.5981500331
-> x = 5 , y = 148.413159103
-> x = 6 , y = 403.428793493
-> x = 7 , y = 1096.63315843
-> x = 8 , y = 2980.95798704
-> x = 9 , y = 8103.08392758
So you can control the allowed functions that should be used by the eval method, and have a sandbox environment that can evaluate expressions.
This is what we used in a previous project I worked in. We used Python expressions in custom Eclipse IDE plug-ins, using Jython to run in the JVM. You could do the same with IronPython to run in the CLR.
The examples I used in part inspired / copied from the Lybniz project explanation on how to run a safe Python eval environment. Read it for more details!
You might want to look at Regular-Expressions or RegEx. It's proven and been around for a long time. There's a regex library all the major programming/script languages out there.
Libraries:
C++: what regex library should I use?
C# Regex Class
Usage
Regex Email validation
Regex to validate date format dd/mm/yyyy
What is the best way to define a numerical constant in Mathematica?
For example, say I want g to be the approximate acceleration due to gravity on the surface of the Earth. I give it a numerical value (in m/s^2), tell Mathematica it's numeric, positive and a constant using
Unprotect[g];
ClearAll[g]
N[g] = 9.81;
NumericQ[g] ^= True;
Positive[g] ^= True;
SetAttributes[g, Constant];
Protect[g];
Then I can use it as a symbol in symbolic calculations that will automatically evaluate to 9.81 when numerical results are called for. For example 1.0 g evaluates to 9.81.
This does not seem as well tied into Mathematica as built in numerical constants. For example Pi > 0 will evaluate to True, but g > 0 will not. (I could add g > 0 to the global $Assumptions but even then I need a call to Simplify for it to take effect.)
Also, Positive[g] returns True, but Positive[g^2] does not evaluate - compare this with the equivalent statements using Pi.
So my question is, what else should I do to define a numerical constant? What other attributes/properties can be set? Is there an easier way to go about this? Etc...
I'd recommend using a zero-argument "function". That way it can be given both the NumericFunction attribute and a numeric evaluation rule. that latter is important for predicates such as Positive.
SetAttributes[gravUnit, NumericFunction]
N[gravUnit[], prec_: $MachinePrecision] := N[981/100, prec]
In[121]:= NumericQ[gravitUnit[]]
Out[121]= True
In[122]:= Positive[gravUnit[]^2 - 30]
Out[122]= True
Daniel Lichtblau
May be I am naive, but to my mind your definitions are a good start. Things like g > 0->True can be added via UpValues. For Positive[g^2] to return True, you probably have to overload Positive, because of the depth-1 limitation for UpValues. Generally, I think the exact set of auto-evaluated expressions involving a constant is a moving target, even for built-in constants. In other words, those extra built-in rules seem to be determined from convenience and frequent uses, on a case-by-case basis, rather than from the first principles. I would just add new rules as you go, whenever you feel that you need them. You probably can not expect your constants to be as well integrated in the system as built-ins, but I think you can get pretty close. You will probably have to overload a number of built-in functions on these symbols, but again, which ones those will be, will depend on what you need from your symbol.
EDIT
I was hesitating to include this, since the code below is a hack, but it may be useful in some circumstances. Here is the code:
Clear[evalFunction];
evalFunction[fun_Symbol, HoldComplete[sym_Symbol]] := False;
Clear[defineAutoNValue];
defineAutoNValue[s_Symbol] :=
Module[{inSUpValue},
s /: expr : f_[left___, s, right___] :=
Block[{inSUpValue = True},
With[{stack = Stack[_]},
If[
expr === Unevaluated[expr] &&
(evalFunction[f, HoldComplete[s]] ||
MemberQ[
stack,
HoldForm[(op_Symbol /; evalFunction[op, HoldComplete[s]])
[___, x_ /; ! FreeQ[Unevaluated[x], HoldPattern#expr], ___]],
Infinity
]
),
f[left, N[s], right],
(* else *)
expr
]]] /; ! TrueQ[inSUpValue]];
ClearAll[substituteNumeric];
SetAttributes[substituteNumeric, HoldFirst];
substituteNumeric[code_, rules : {(_Symbol :> {__Symbol}) ..}] :=
Internal`InheritedBlock[{evalFunction},
MapThread[
Map[Function[f, evalFunction[f, HoldComplete[#]] = True], #2] &,
Transpose[List ### rules]
];
code]
With this, you may enable a symbol to auto-substitute its numerical value in places where we indicate some some functions surrounding those function calls may benefit from it. Here is an example:
ClearAll[g, f];
SetAttributes[g, Constant];
N[g] = 9.81;
NumericQ[g] ^= True;
defineAutoNValue[g];
f[g] := "Do something with g";
Here we will try to compute some expressions involving g, first normally:
In[391]:= {f[g],g^2,g^2>0, 2 g, Positive[2 g+1],Positive[2g-a],g^2+a^2,g^2+a^2>0,g<0,g^2+a^2<0}
Out[391]= {Do something with g,g^2,g^2>0,2 g,Positive[1+2 g],
Positive[-a+2 g],a^2+g^2,a^2+g^2>0,g<0,a^2+g^2<0}
And now inside our wrapper (the second argument gives a list of rules, to indicate for which symbols which functions, when wrapped around the code containing those symbols, should lead to those symbols being replaced with their numerical values):
In[392]:=
substituteNumeric[{f[g],g^2,g^2>0, 2 g, Positive[2 g+1],Positive[2g-a],g^2+a^2,g^2+a^2>0,
g<0,g^2+a^2<0},
{g:>{Positive,Negative,Greater}}]
Out[392]= {Do something with g,g^2,True,2 g,True,Positive[19.62\[VeryThinSpace]-a],
a^2+g^2,96.2361\[VeryThinSpace]+a^2>0,g<0,a^2+g^2<0}
Since the above is a hack, I can not guarantee anything about it. It may be useful in some cases, but that must be decided on a case-by-case basis.
You may want to consider working with units rather than just constants. There are a few options available in Mathematica
Units
Automatic Units
Designer units
There are quite a few technical issues and subtleties about working with units. I found the backgrounder at Designer Units very useful. There are also some interesting discussions on MathGroup. (e.g. here).
I find it useful sometimes to be able to make a local module (inside a parent module) with its own local symbols, which does a small task to be used only by the parent module. This is useful when the module becomes large, and there is no good reason to make smaller helper functions OUTSIDE the module as those helper functions are really needed and used by only that one parent module.
Here is a silly example with one module, and a helper module inside it to something
foo[x_] := Module[{r},
r = Module[{y, sol},
sol = First#Solve[y^2 + 3 y + 2 == 0];
y /. sol
];
x^r
]
But the problem in the above, is that the local variables for the inner module, could conflict with local variables with the parent module, because M notebook makes the inner module local variables red when I do the following, which tells me I am doing something I am not supposed to do: (I do not want to worry all the time with checking if I am using a unique local symbol for the inner module which is different from one used as local symbols for the parent Module, after all, it is supposed to be local. And also having to come up with a different symbol name when this is the case)
foo[x_] := Module[{r, y=0},
r = Module[{y, sol},
sol = First#Solve[y^2 + 3 y + 2 == 0];
y /. sol
];
x^r
]
Notice the red coloring, which according to the help, it is local scope conflict or shadowing in multiple contexts.
(M needs to use better colors, hard to make a difference between many colors, all shades of red).
(I think it is a shadowing warniong) Either way, it tells me I am not supposed to do this, even though I did not see any problem with such construct when I used it.
Value of parent module local variable 'y' in this example did not get over-written by the call to the inner module 'r' which is good.
Again, I did not want to make a function outside foo, because this small task is only used by foo[] and no need to move it to the Global context.
Ofcourse, I could always just write:
foo[x_] := Module[{r, y, sol},
sol = First#Solve[y^2 + 3 y + 2 == 0];
r = y /. sol;
x^r
]
But I am just giving an example, and this is for large module, where it helps to break the tasks inside the module itself into even few smaller tasks. Internal functions, inside functions is something I used before in other languages such as Ada/Pascal and such which has this construct and can be useful for large programs.
My question is: Just want to check with the experts here if it is safe for me to use the above, even though M gives me this red coloring warning? and if there is something I need to worry about doing this
thanks,
Yes, it is safe to use the same variable in nested Modules as long as you don't lose track of them. Mathematica treats each variable defined in a Module as local to that module. Local variables are Temporary, and are numbered as variable$ModuleNumber. You can check this for yourself with the following example:
Module[{x = 1},
Print[HoldForm#x, " = ", x]
Module[{x = 2},
Print[HoldForm#x, " = ", x]
Module[{x = 3},
Print[HoldForm#x, " = ", x]
];
Print[HoldForm#x, " = ", x]
];
Print[HoldForm#x, " = ", x]
]
(*Output
x$4576 = 1
x$4577 = 2
x$4578 = 3
x$4577 = 2
x$4576 = 1
*)
To the best of my knowledge this is a small issue with the detection.
As the Documentation says, "DumpSave writes out definitions in a binary format that is optimized for input by Mathematica." Is there a way to convert a Mathematica binary dump file back to the list of definitions without evaluating them? Import["file.mx","HeldExpression"] does not work...
DumpSave stores values associated with the symbol, i.e. OwnValues, DownValues, UpValues, SubValues, DefaultValues, NValues, FormatValues.
All the evaluation was done in the session on Mathematica, and then DumpSave saved the result of it.
These values are stored in internal formal. Reading the MX files only creates symbols and populates them with these values by reading this internal format back, bypassing the evaluator.
Maybe you could share the problem that prompted you to ask this question.
[EDIT] Clarifying on the issue raised by Alexey. MX files save internal representation of symbol definitions. It appears that Mathematica internally keeps track of:
f[x_Real] := x^2 + 1
DumpSave[FileNameJoin[{$HomeDirectory, "Desktop", "set_delayed.mx"}],
f];
Remove[f]
f[x_Real] = x^2 + 1;
DumpSave[FileNameJoin[{$HomeDirectory, "Desktop", "set.mx"}], f];
setBytes =
Import[FileNameJoin[{$HomeDirectory, "Desktop", "set.mx"}], "Byte"];
setDelayedBytes =
Import[FileNameJoin[{$HomeDirectory, "Desktop", "set_delayed.mx"}],
"Byte"];
One can, then, use SequenceAlignment[setBytes, setDelayedBytes] to see the difference. I do not know why it is done that way, but my point stands. All the evaluation on values constructed using Set has already been done in Mathematica session before they were saved by DumpSave. When MX file is read the internal representation is read back into Mathematica sessions, and no evaluation of loaded definitions is actually performed.
You can assign Rules instead of RuleDelayed's to DownValues, which is equivalent to the immediate definitions. The right-hand side of the assignment stays unevaluated and is copied literally, so the command corresponding to
Clear[f];
f[x_Real] = x^2 + 1;
DumpSave["f.mx", f];
Clear[f];
f = a;
<< f.mx;
Definition[f]
would be
Clear[f];
f = a;
DownValues[f] := {f[x_Real] -> x^2 + 1}
Definition[f]
f = a
f[x_Real] = x^2+1
(cf. with your example of Clear[f]; f = a; f[x_Real] = x^2 + 1; Definition[f] which does not work, assigning a rule for a[x_Real] instead). This is robust to prior assignments to x as well.
Edit: It is not robust to side effects of the right-hand side, as an example in the comments below shows. To assign a downvalue avoiding any evaluation one can use the undocumented System`Private`ValueList like in the following:
Clear[f];
f := Print["f is evaluated!"];
DownValues[f] := System`Private`ValueList[f[x_Real] -> Print["definition is evaluated!"]];
(no output)
Note that the assignment got seemingly converted to delayed rules:
DownValues[f]
{HoldPattern[f[x_Real]] :> x^2 + 1}
but Definition (and Save) show that the distinction from a := has internally been kept. I don't know why DownValues don't display the truth.
To answer the original question, you would probably do best with importing the dump file and exporting the relevant symbols using Save, then, if expecting this to be loaded into a kernel tainted by prior definitions, convert the assignments into assignments to DownValues as above programatically. It might be easier to scope the variables in a private context before the export, though, which is what the system files do to prevent collisions.
I would like to define a symbol pt to hold a point (and eventually cache some data related to that point):
pt::"usage" = "pt[{x,y}] represents a point at {x,y}";
I would like to be able to use such pt objects as points in as many ways as possible, an particularly, I would like to be able to write
{a0,a1}+pt[{b0,b1}]
and have it return pt[{a0+b0,a1+b1}] rather than {a0+pt[{b0,b1}],a1+pt[{b0,b1}]}.
My original idea was to use:
pt /: Plus[pt[p0_], p1 : {_, _}] = pt[p0 + p1];
But this doesn't work (because Plus is Listable?). Is there a way to do this without unprotecting Plus?
Update:
As Leonid points out, this is not possible without globally or locally hacking Plus, since the Listable attribute is considered before any *values. This is actually described very precisely in the evaluation tutorial.
Mathematica's evaluator seems not flexible enough to do this easily. UpValues for pt indeed are applied before DownValues for Plus, but threading over lists due to Listability happens even before that. In this particular case, the following might work for you:
eval = Function[code,Block[{Plus = Plus, attr = DeleteCases[Attributes[Plus], Listable]},
SetAttributes[Plus, attr]; code], HoldAll]
To use it, wrap it around a piece of code where you want your rule for pt to apply, e.g.:
eval[{a0, a1} + pt[{b0, b1}]]
You can use $Pre as $Pre = eval to avoid typing eval every time, although generally I would not recommend this. Blocking Plus is a softer way of disabling some or all of its Attributes temporarily. The advantage w.r.t. clearing and setting attributes without Block is that you can not end up in a global state with Listable attribute permanently disabled, even if exception is thrown or the computation is Abort-ed.
Since Listable attribute directly affects evaluation rather than pattern-matching (the latter may of course be affected indirectly if some pattern has to match the result of Plus threaded over a list), this should be ok in most cases. In theory, it may still lead to some unwanted effects in some cases, particularly where pattern-matching is involved. But in practice, it might be good enough. A cleaner but more complex solution would be to create a custom evaluator tailored to your needs.
The following is a bit wasteful, but it works: The idea is to simply watch for cases where the Listable attribute of Plus has put the same pt into all elements of a list (i.e. a raw point) -- and then pull it back out. First, define a function for adding pt objects:
SetAttributes[ptPlus, {Orderless}]
ptPlus[pt[pa : {_, _}], pt[pb : {_, _}], r___] :=
ptPlus[pt[pa + pb], r];
ptPlus[p_pt] := p;
Then we make sure that any Plus which involves a pt is mapped to ptPlus (an associate the rule with pt).
Plus[h___, a_pt, t___] ^:= ptPlus[h, a, t];
The above rules means that: {x0,y0}+pt[{x1,y1}] will be expanded from {x0+pt[{x1,y1}],y0+pt[{x1,y1}]} to {ptPlus[x0,pt[{x1,y1}]],ptPlus[y0,pt[{x1,y1}]]}. Now we just make a rule to transform this to pt[{x0,y0}]+pt[{x1,y1}] (note the deferred condition which checks that the pts are equal):
{ptPlus[x__], ptPlus[y__]} ^:= Module[{
ptCases = Cases[{{x}, {y}}, _pt, {2}]},
ptCases[[1]] + pt[Plus ### DeleteCases[{{x}, {y}}, _pt, {2}]]
/; Equal ## ptCases]
A more opaque, but slightly more careful version which is easier to generalize to higher dimensions:
ptPlus /: p : {_ptPlus, _ptPlus} := Module[{ptCases, rest,
lp = ReleaseHold#Apply[List, Hold[p], {2}]},
ptCases = Cases[lp, _pt, {2}];
rest = Plus ### DeleteCases[lp, _pt, {2}];
ptCases[[1]] + pt[rest] /; And[Equal ## ptCases, VectorQ#rest]]
This whole approach will of course lead to horribly subtle bugs when {a+pt[{0,0}],a+pt[{0,b}]} /. {a -> pt[{0,0}]} evaluates to pt[{0,0}] when c==0 and {pt[{0,0}],pt[{0,c}]} otherwise...
HTH -- said the guy to himself...